Actual source code: ex1.c

  1: /*$Id: ex1.c,v 1.31 2001/08/07 21:31:30 bsmith Exp $*/

  3: static char help[] ="Solves the time dependent Bratu problem using pseudo-timestepping.";

  5: /*
  6:    Concepts: TS^pseudo-timestepping
  7:    Concepts: pseudo-timestepping
  8:    Concepts: nonlinear problems
  9:    Processors: 1

 11: */

 13: /* ------------------------------------------------------------------------

 15:     This code demonstrates how one may solve a nonlinear problem 
 16:     with pseudo-timestepping. In this simple example, the pseudo-timestep
 17:     is the same for all grid points, i.e., this is equivalent to using
 18:     the backward Euler method with a variable timestep.

 20:     Note: This example does not require pseudo-timestepping since it
 21:     is an easy nonlinear problem, but it is included to demonstrate how
 22:     the pseudo-timestepping may be done.

 24:     See snes/examples/tutorials/ex4.c[ex4f.F] and 
 25:     snes/examples/tutorials/ex5.c[ex5f.F] where the problem is described
 26:     and solved using Newton's method alone.

 28:   ----------------------------------------------------------------------------- */
 29: /*
 30:     Include "petscts.h" to use the PETSc timestepping routines. Note that
 31:     this file automatically includes "petsc.h" and other lower-level
 32:     PETSc include files.
 33: */
 34:  #include petscts.h

 36: /*
 37:   Create an application context to contain data needed by the 
 38:   application-provided call-back routines, FormJacobian() and
 39:   FormFunction().
 40: */
 41: typedef struct {
 42:   PetscReal   param;        /* test problem parameter */
 43:   int         mx;           /* Discretization in x-direction */
 44:   int         my;           /* Discretization in y-direction */
 45: } AppCtx;

 47: /* 
 48:    User-defined routines
 49: */
 50: extern int  FormJacobian(TS,PetscReal,Vec,Mat*,Mat*,MatStructure*,void*),
 51:      FormFunction(TS,PetscReal,Vec,Vec,void*),
 52:      FormInitialGuess(Vec,AppCtx*);

 54: int main(int argc,char **argv)
 55: {
 56:   TS        ts;                 /* timestepping context */
 57:   Vec       x,r;               /* solution, residual vectors */
 58:   Mat       J;                  /* Jacobian matrix */
 59:   AppCtx    user;               /* user-defined work context */
 60:   int       its;                /* iterations for convergence */
 61:   int       ierr,N;
 62:   PetscReal param_max = 6.81,param_min = 0.,dt;
 63:   PetscReal ftime;

 65:   PetscInitialize(&argc,&argv,PETSC_NULL,help);
 66:   user.mx        = 4;
 67:   user.my        = 4;
 68:   user.param     = 6.0;
 69: 
 70:   /*
 71:      Allow user to set the grid dimensions and nonlinearity parameter at run-time
 72:   */
 73:   PetscOptionsGetInt(PETSC_NULL,"-mx",&user.mx,PETSC_NULL);
 74:   PetscOptionsGetInt(PETSC_NULL,"-my",&user.my,PETSC_NULL);
 75:   PetscOptionsGetReal(PETSC_NULL,"-param",&user.param,PETSC_NULL);
 76:   if (user.param >= param_max || user.param <= param_min) {
 77:     SETERRQ(1,"Parameter is out of range");
 78:   }
 79:   dt = .5/PetscMax(user.mx,user.my);
 80:   PetscOptionsGetReal(PETSC_NULL,"-dt",&dt,PETSC_NULL);
 81:   N          = user.mx*user.my;
 82: 
 83:   /* 
 84:       Create vectors to hold the solution and function value
 85:   */
 86:   VecCreateSeq(PETSC_COMM_SELF,N,&x);
 87:   VecDuplicate(x,&r);

 89:   /*
 90:     Create matrix to hold Jacobian. Preallocate 5 nonzeros per row
 91:     in the sparse matrix. Note that this is not the optimal strategy; see
 92:     the Performance chapter of the users manual for information on 
 93:     preallocating memory in sparse matrices.
 94:   */
 95:   MatCreateSeqAIJ(PETSC_COMM_SELF,N,N,5,0,&J);

 97:   /* 
 98:      Create timestepper context 
 99:   */
100:   TSCreate(PETSC_COMM_WORLD,&ts);
101:   TSSetProblemType(ts,TS_NONLINEAR);

103:   /*
104:      Tell the timestepper context where to compute solutions
105:   */
106:   TSSetSolution(ts,x);

108:   /*
109:      Provide the call-back for the nonlinear function we are 
110:      evaluating. Thus whenever the timestepping routines need the
111:      function they will call this routine. Note the final argument
112:      is the application context used by the call-back functions.
113:   */
114:   TSSetRHSFunction(ts,FormFunction,&user);

116:   /*
117:      Set the Jacobian matrix and the function used to compute 
118:      Jacobians.
119:   */
120:   TSSetRHSJacobian(ts,J,J,FormJacobian,&user);

122:   /*
123:        For the initial guess for the problem
124:   */
125:   FormInitialGuess(x,&user);

127:   /*
128:        This indicates that we are using pseudo timestepping to 
129:      find a steady state solution to the nonlinear problem.
130:   */
131:   TSSetType(ts,TS_PSEUDO);

133:   /*
134:        Set the initial time to start at (this is arbitrary for 
135:      steady state problems; and the initial timestep given above
136:   */
137:   TSSetInitialTimeStep(ts,0.0,dt);

139:   /*
140:       Set a large number of timesteps and final duration time
141:      to insure convergence to steady state.
142:   */
143:   TSSetDuration(ts,1000,1.e12);

145:   /*
146:       Use the default strategy for increasing the timestep
147:   */
148:   TSPseudoSetTimeStep(ts,TSPseudoDefaultTimeStep,0);

150:   /*
151:       Set any additional options from the options database. This
152:      includes all options for the nonlinear and linear solvers used
153:      internally the the timestepping routines.
154:   */
155:   TSSetFromOptions(ts);

157:   TSSetUp(ts);

159:   /*
160:       Perform the solve. This is where the timestepping takes place.
161:   */
162:   TSStep(ts,&its,&ftime);
163: 
164:   printf("Number of pseudo timesteps = %d final time %4.2en",its,ftime);

166:   /* 
167:      Free the data structures constructed above
168:   */
169:   VecDestroy(x);
170:   VecDestroy(r);
171:   MatDestroy(J);
172:   TSDestroy(ts);
173:   PetscFinalize();

175:   return 0;
176: }
177: /* ------------------------------------------------------------------ */
178: /*           Bratu (Solid Fuel Ignition) Test Problem                 */
179: /* ------------------------------------------------------------------ */

181: /* --------------------  Form initial approximation ----------------- */

183: int FormInitialGuess(Vec X,AppCtx *user)
184: {
185:   int         i,j,row,mx,my,ierr;
186:   PetscReal   one = 1.0,lambda;
187:   PetscReal   temp1,temp,hx,hy;
188:   PetscScalar *x;

190:   mx         = user->mx;
191:   my         = user->my;
192:   lambda = user->param;

194:   hx    = one / (PetscReal)(mx-1);
195:   hy    = one / (PetscReal)(my-1);

197:   VecGetArray(X,&x);
198:   temp1 = lambda/(lambda + one);
199:   for (j=0; j<my; j++) {
200:     temp = (PetscReal)(PetscMin(j,my-j-1))*hy;
201:     for (i=0; i<mx; i++) {
202:       row = i + j*mx;
203:       if (i == 0 || j == 0 || i == mx-1 || j == my-1) {
204:         x[row] = 0.0;
205:         continue;
206:       }
207:       x[row] = temp1*sqrt(PetscMin((PetscReal)(PetscMin(i,mx-i-1))*hx,temp));
208:     }
209:   }
210:   VecRestoreArray(X,&x);
211:   return 0;
212: }
213: /* --------------------  Evaluate Function F(x) --------------------- */

215: int FormFunction(TS ts,PetscReal t,Vec X,Vec F,void *ptr)
216: {
217:   AppCtx      *user = (AppCtx*)ptr;
218:   int         ierr,i,j,row,mx,my;
219:   PetscReal   two = 2.0,one = 1.0,lambda;
220:   PetscReal   hx,hy,hxdhy,hydhx;
221:   PetscScalar ut,ub,ul,ur,u,uxx,uyy,sc,*x,*f;

223:   mx         = user->mx;
224:   my         = user->my;
225:   lambda = user->param;

227:   hx    = one / (PetscReal)(mx-1);
228:   hy    = one / (PetscReal)(my-1);
229:   sc    = hx*hy;
230:   hxdhy = hx/hy;
231:   hydhx = hy/hx;

233:   VecGetArray(X,&x);
234:   VecGetArray(F,&f);
235:   for (j=0; j<my; j++) {
236:     for (i=0; i<mx; i++) {
237:       row = i + j*mx;
238:       if (i == 0 || j == 0 || i == mx-1 || j == my-1) {
239:         f[row] = x[row];
240:         continue;
241:       }
242:       u = x[row];
243:       ub = x[row - mx];
244:       ul = x[row - 1];
245:       ut = x[row + mx];
246:       ur = x[row + 1];
247:       uxx = (-ur + two*u - ul)*hydhx;
248:       uyy = (-ut + two*u - ub)*hxdhy;
249:       f[row] = -uxx + -uyy + sc*lambda*PetscExpScalar(u);
250:     }
251:   }
252:   VecRestoreArray(X,&x);
253:   VecRestoreArray(F,&f);
254:   return 0;
255: }
256: /* --------------------  Evaluate Jacobian F'(x) -------------------- */

258: int FormJacobian(TS ts,PetscReal t,Vec X,Mat *J,Mat *B,MatStructure *flag,void *ptr)
259: {
260:   AppCtx      *user = (AppCtx*)ptr;
261:   Mat         jac = *B;
262:   int         i,j,row,mx,my,col[5],ierr;
263:   PetscScalar two = 2.0,one = 1.0,lambda,v[5],sc,*x;
264:   PetscReal   hx,hy,hxdhy,hydhx;


267:   mx         = user->mx;
268:   my         = user->my;
269:   lambda = user->param;

271:   hx    = 1.0 / (PetscReal)(mx-1);
272:   hy    = 1.0 / (PetscReal)(my-1);
273:   sc    = hx*hy;
274:   hxdhy = hx/hy;
275:   hydhx = hy/hx;

277:   VecGetArray(X,&x);
278:   for (j=0; j<my; j++) {
279:     for (i=0; i<mx; i++) {
280:       row = i + j*mx;
281:       if (i == 0 || j == 0 || i == mx-1 || j == my-1) {
282:         MatSetValues(jac,1,&row,1,&row,&one,INSERT_VALUES);
283:         continue;
284:       }
285:       v[0] = hxdhy; col[0] = row - mx;
286:       v[1] = hydhx; col[1] = row - 1;
287:       v[2] = -two*(hydhx + hxdhy) + sc*lambda*PetscExpScalar(x[row]); col[2] = row;
288:       v[3] = hydhx; col[3] = row + 1;
289:       v[4] = hxdhy; col[4] = row + mx;
290:       MatSetValues(jac,1,&row,5,col,v,INSERT_VALUES);
291:     }
292:   }
293:   MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);
294:   VecRestoreArray(X,&x);
295:   MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);
296:   *flag = SAME_NONZERO_PATTERN;
297:   return 0;
298: }