xref: /petsc/src/ts/tutorials/advection-diffusion-reaction/ex5.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1*c4762a1bSJed Brown 
2*c4762a1bSJed Brown static char help[] = "Demonstrates Pattern Formation with Reaction-Diffusion Equations.\n";
3*c4762a1bSJed Brown 
4*c4762a1bSJed Brown /*F
5*c4762a1bSJed Brown      This example is taken from the book, Numerical Solution of Time-Dependent Advection-Diffusion-Reaction Equations by
6*c4762a1bSJed Brown       W. Hundsdorf and J.G. Verwer,  Page 21, Pattern Formation with Reaction-Diffusion Equations
7*c4762a1bSJed Brown \begin{eqnarray*}
8*c4762a1bSJed Brown         u_t = D_1 (u_{xx} + u_{yy})  - u*v^2 + \gamma(1 -u)           \\
9*c4762a1bSJed Brown         v_t = D_2 (v_{xx} + v_{yy})  + u*v^2 - (\gamma + \kappa)v
10*c4762a1bSJed Brown \end{eqnarray*}
11*c4762a1bSJed Brown     Unlike in the book this uses periodic boundary conditions instead of Neumann
12*c4762a1bSJed Brown     (since they are easier for finite differences).
13*c4762a1bSJed Brown F*/
14*c4762a1bSJed Brown 
15*c4762a1bSJed Brown /*
16*c4762a1bSJed Brown       Helpful runtime monitor options:
17*c4762a1bSJed Brown            -ts_monitor_draw_solution
18*c4762a1bSJed Brown            -draw_save -draw_save_movie
19*c4762a1bSJed Brown 
20*c4762a1bSJed Brown       Helpful runtime linear solver options:
21*c4762a1bSJed Brown            -pc_type mg -pc_mg_galerkin pmat -da_refine 1 -snes_monitor -ksp_monitor -ts_view  (note that these Jacobians are so well-conditioned multigrid may not be the best solver)
22*c4762a1bSJed Brown 
23*c4762a1bSJed Brown       Point your browser to localhost:8080 to monitor the simulation
24*c4762a1bSJed Brown            ./ex5  -ts_view_pre saws  -stack_view saws -draw_save -draw_save_single_file -x_virtual -ts_monitor_draw_solution -saws_root .
25*c4762a1bSJed Brown 
26*c4762a1bSJed Brown */
27*c4762a1bSJed Brown 
28*c4762a1bSJed Brown /*
29*c4762a1bSJed Brown 
30*c4762a1bSJed Brown    Include "petscdmda.h" so that we can use distributed arrays (DMDAs).
31*c4762a1bSJed Brown    Include "petscts.h" so that we can use SNES numerical (ODE) integrators.  Note that this
32*c4762a1bSJed Brown    file automatically includes:
33*c4762a1bSJed Brown      petscsys.h       - base PETSc routines   petscvec.h  - vectors
34*c4762a1bSJed Brown      petscmat.h - matrices                    petscis.h   - index sets
35*c4762a1bSJed Brown      petscksp.h - Krylov subspace methods     petscpc.h   - preconditioners
36*c4762a1bSJed Brown      petscviewer.h - viewers                  petscsnes.h - nonlinear solvers
37*c4762a1bSJed Brown */
38*c4762a1bSJed Brown #include <petscdm.h>
39*c4762a1bSJed Brown #include <petscdmda.h>
40*c4762a1bSJed Brown #include <petscts.h>
41*c4762a1bSJed Brown 
42*c4762a1bSJed Brown /*  Simple C struct that allows us to access the two velocity (x and y directions) values easily in the code */
43*c4762a1bSJed Brown typedef struct {
44*c4762a1bSJed Brown   PetscScalar u,v;
45*c4762a1bSJed Brown } Field;
46*c4762a1bSJed Brown 
47*c4762a1bSJed Brown /*  Data structure to store the model parameters */
48*c4762a1bSJed Brown typedef struct {
49*c4762a1bSJed Brown   PetscReal D1,D2,gamma,kappa;
50*c4762a1bSJed Brown } AppCtx;
51*c4762a1bSJed Brown 
52*c4762a1bSJed Brown /*
53*c4762a1bSJed Brown    User-defined routines
54*c4762a1bSJed Brown */
55*c4762a1bSJed Brown extern PetscErrorCode RHSFunction(TS,PetscReal,Vec,Vec,void*),InitialConditions(DM,Vec);
56*c4762a1bSJed Brown extern PetscErrorCode RHSJacobian(TS,PetscReal,Vec,Mat,Mat,void*);
57*c4762a1bSJed Brown 
58*c4762a1bSJed Brown int main(int argc,char **argv)
59*c4762a1bSJed Brown {
60*c4762a1bSJed Brown   TS             ts;                  /* ODE integrator */
61*c4762a1bSJed Brown   Vec            x;                   /* solution */
62*c4762a1bSJed Brown   PetscErrorCode ierr;
63*c4762a1bSJed Brown   DM             da;
64*c4762a1bSJed Brown   AppCtx         appctx;
65*c4762a1bSJed Brown 
66*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
67*c4762a1bSJed Brown      Initialize program
68*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
69*c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
70*c4762a1bSJed Brown   PetscFunctionBeginUser;
71*c4762a1bSJed Brown   appctx.D1    = 8.0e-5;
72*c4762a1bSJed Brown   appctx.D2    = 4.0e-5;
73*c4762a1bSJed Brown   appctx.gamma = .024;
74*c4762a1bSJed Brown   appctx.kappa = .06;
75*c4762a1bSJed Brown 
76*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
77*c4762a1bSJed Brown      Create distributed array (DMDA) to manage parallel grid and vectors
78*c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
79*c4762a1bSJed Brown   ierr = DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_PERIODIC,DM_BOUNDARY_PERIODIC,DMDA_STENCIL_STAR,65,65,PETSC_DECIDE,PETSC_DECIDE,2,1,NULL,NULL,&da);CHKERRQ(ierr);
80*c4762a1bSJed Brown   ierr = DMSetFromOptions(da);CHKERRQ(ierr);
81*c4762a1bSJed Brown   ierr = DMSetUp(da);CHKERRQ(ierr);
82*c4762a1bSJed Brown   ierr = DMDASetFieldName(da,0,"u");CHKERRQ(ierr);
83*c4762a1bSJed Brown   ierr = DMDASetFieldName(da,1,"v");CHKERRQ(ierr);
84*c4762a1bSJed Brown 
85*c4762a1bSJed Brown   /*  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
86*c4762a1bSJed Brown      Create global vector from DMDA; this will be used to store the solution
87*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
88*c4762a1bSJed Brown   ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr);
89*c4762a1bSJed Brown 
90*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
91*c4762a1bSJed Brown      Create timestepping solver context
92*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
93*c4762a1bSJed Brown   ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr);
94*c4762a1bSJed Brown   ierr = TSSetType(ts,TSARKIMEX);CHKERRQ(ierr);
95*c4762a1bSJed Brown   ierr = TSARKIMEXSetFullyImplicit(ts,PETSC_TRUE);CHKERRQ(ierr);
96*c4762a1bSJed Brown   ierr = TSSetDM(ts,da);CHKERRQ(ierr);
97*c4762a1bSJed Brown   ierr = TSSetProblemType(ts,TS_NONLINEAR);CHKERRQ(ierr);
98*c4762a1bSJed Brown   ierr = TSSetRHSFunction(ts,NULL,RHSFunction,&appctx);CHKERRQ(ierr);
99*c4762a1bSJed Brown   ierr = TSSetRHSJacobian(ts,NULL,NULL,RHSJacobian,&appctx);CHKERRQ(ierr);
100*c4762a1bSJed Brown 
101*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
102*c4762a1bSJed Brown      Set initial conditions
103*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
104*c4762a1bSJed Brown   ierr = InitialConditions(da,x);CHKERRQ(ierr);
105*c4762a1bSJed Brown   ierr = TSSetSolution(ts,x);CHKERRQ(ierr);
106*c4762a1bSJed Brown 
107*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
108*c4762a1bSJed Brown      Set solver options
109*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
110*c4762a1bSJed Brown   ierr = TSSetMaxTime(ts,2000.0);CHKERRQ(ierr);
111*c4762a1bSJed Brown   ierr = TSSetTimeStep(ts,.0001);CHKERRQ(ierr);
112*c4762a1bSJed Brown   ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER);CHKERRQ(ierr);
113*c4762a1bSJed Brown   ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
114*c4762a1bSJed Brown 
115*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
116*c4762a1bSJed Brown      Solve ODE system
117*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
118*c4762a1bSJed Brown   ierr = TSSolve(ts,x);CHKERRQ(ierr);
119*c4762a1bSJed Brown 
120*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
121*c4762a1bSJed Brown      Free work space.
122*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
123*c4762a1bSJed Brown   ierr = VecDestroy(&x);CHKERRQ(ierr);
124*c4762a1bSJed Brown   ierr = TSDestroy(&ts);CHKERRQ(ierr);
125*c4762a1bSJed Brown   ierr = DMDestroy(&da);CHKERRQ(ierr);
126*c4762a1bSJed Brown 
127*c4762a1bSJed Brown   ierr = PetscFinalize();
128*c4762a1bSJed Brown   return ierr;
129*c4762a1bSJed Brown }
130*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
131*c4762a1bSJed Brown /*
132*c4762a1bSJed Brown    RHSFunction - Evaluates nonlinear function, that defines the right
133*c4762a1bSJed Brown      hand side of the ODE
134*c4762a1bSJed Brown 
135*c4762a1bSJed Brown    Input Parameters:
136*c4762a1bSJed Brown .  ts - the TS context
137*c4762a1bSJed Brown .  time - current time
138*c4762a1bSJed Brown .  U - input vector
139*c4762a1bSJed Brown .  ptr - optional user-defined context, as set by TSSetRHSFunction()
140*c4762a1bSJed Brown 
141*c4762a1bSJed Brown    Output Parameter:
142*c4762a1bSJed Brown .  F - function vector
143*c4762a1bSJed Brown  */
144*c4762a1bSJed Brown PetscErrorCode RHSFunction(TS ts,PetscReal time,Vec U,Vec F,void *ptr)
145*c4762a1bSJed Brown {
146*c4762a1bSJed Brown   AppCtx         *appctx = (AppCtx*)ptr;
147*c4762a1bSJed Brown   DM             da;
148*c4762a1bSJed Brown   PetscErrorCode ierr;
149*c4762a1bSJed Brown   PetscInt       i,j,Mx,My,xs,ys,xm,ym;
150*c4762a1bSJed Brown   PetscReal      hx,hy,sx,sy;
151*c4762a1bSJed Brown   PetscScalar    uc,uxx,uyy,vc,vxx,vyy;
152*c4762a1bSJed Brown   Field          **u,**f;
153*c4762a1bSJed Brown   Vec            localU;
154*c4762a1bSJed Brown 
155*c4762a1bSJed Brown   PetscFunctionBegin;
156*c4762a1bSJed Brown   ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
157*c4762a1bSJed Brown   /* Get local (ghosted) work vector */
158*c4762a1bSJed Brown   ierr = DMGetLocalVector(da,&localU);CHKERRQ(ierr);
159*c4762a1bSJed Brown   /* Get information about mesh needed for discretization */
160*c4762a1bSJed Brown   ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr);
161*c4762a1bSJed Brown 
162*c4762a1bSJed Brown   hx = 2.50/(PetscReal)(Mx); sx = 1.0/(hx*hx);
163*c4762a1bSJed Brown   hy = 2.50/(PetscReal)(My); sy = 1.0/(hy*hy);
164*c4762a1bSJed Brown 
165*c4762a1bSJed Brown   /*
166*c4762a1bSJed Brown      Scatter ghost points to local vector, using the 2-step process
167*c4762a1bSJed Brown   */
168*c4762a1bSJed Brown   ierr = DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
169*c4762a1bSJed Brown   ierr = DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
170*c4762a1bSJed Brown 
171*c4762a1bSJed Brown   /*
172*c4762a1bSJed Brown      Get pointers to actual vector data
173*c4762a1bSJed Brown   */
174*c4762a1bSJed Brown   ierr = DMDAVecGetArrayRead(da,localU,&u);CHKERRQ(ierr);
175*c4762a1bSJed Brown   ierr = DMDAVecGetArray(da,F,&f);CHKERRQ(ierr);
176*c4762a1bSJed Brown 
177*c4762a1bSJed Brown   /*
178*c4762a1bSJed Brown      Get local grid boundaries; this is the region that this process owns and must operate on
179*c4762a1bSJed Brown   */
180*c4762a1bSJed Brown   ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
181*c4762a1bSJed Brown 
182*c4762a1bSJed Brown   /*
183*c4762a1bSJed Brown      Compute function over the locally owned part of the grid with standard finite differences
184*c4762a1bSJed Brown   */
185*c4762a1bSJed Brown   for (j=ys; j<ys+ym; j++) {
186*c4762a1bSJed Brown     for (i=xs; i<xs+xm; i++) {
187*c4762a1bSJed Brown       uc        = u[j][i].u;
188*c4762a1bSJed Brown       uxx       = (-2.0*uc + u[j][i-1].u + u[j][i+1].u)*sx;
189*c4762a1bSJed Brown       uyy       = (-2.0*uc + u[j-1][i].u + u[j+1][i].u)*sy;
190*c4762a1bSJed Brown       vc        = u[j][i].v;
191*c4762a1bSJed Brown       vxx       = (-2.0*vc + u[j][i-1].v + u[j][i+1].v)*sx;
192*c4762a1bSJed Brown       vyy       = (-2.0*vc + u[j-1][i].v + u[j+1][i].v)*sy;
193*c4762a1bSJed Brown       f[j][i].u = appctx->D1*(uxx + uyy) - uc*vc*vc + appctx->gamma*(1.0 - uc);
194*c4762a1bSJed Brown       f[j][i].v = appctx->D2*(vxx + vyy) + uc*vc*vc - (appctx->gamma + appctx->kappa)*vc;
195*c4762a1bSJed Brown     }
196*c4762a1bSJed Brown   }
197*c4762a1bSJed Brown   ierr = PetscLogFlops(16*xm*ym);CHKERRQ(ierr);
198*c4762a1bSJed Brown 
199*c4762a1bSJed Brown   /*
200*c4762a1bSJed Brown      Restore access to vectors and return no longer needed work vector
201*c4762a1bSJed Brown   */
202*c4762a1bSJed Brown   ierr = DMDAVecRestoreArrayRead(da,localU,&u);CHKERRQ(ierr);
203*c4762a1bSJed Brown   ierr = DMDAVecRestoreArray(da,F,&f);CHKERRQ(ierr);
204*c4762a1bSJed Brown   ierr = DMRestoreLocalVector(da,&localU);CHKERRQ(ierr);
205*c4762a1bSJed Brown   PetscFunctionReturn(0);
206*c4762a1bSJed Brown }
207*c4762a1bSJed Brown 
208*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
209*c4762a1bSJed Brown PetscErrorCode InitialConditions(DM da,Vec U)
210*c4762a1bSJed Brown {
211*c4762a1bSJed Brown   PetscErrorCode ierr;
212*c4762a1bSJed Brown   PetscInt       i,j,xs,ys,xm,ym,Mx,My;
213*c4762a1bSJed Brown   Field          **u;
214*c4762a1bSJed Brown   PetscReal      hx,hy,x,y;
215*c4762a1bSJed Brown 
216*c4762a1bSJed Brown   PetscFunctionBegin;
217*c4762a1bSJed Brown   ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr);
218*c4762a1bSJed Brown 
219*c4762a1bSJed Brown   hx = 2.5/(PetscReal)(Mx);
220*c4762a1bSJed Brown   hy = 2.5/(PetscReal)(My);
221*c4762a1bSJed Brown 
222*c4762a1bSJed Brown   /*
223*c4762a1bSJed Brown      Get pointers to actual vector data
224*c4762a1bSJed Brown   */
225*c4762a1bSJed Brown   ierr = DMDAVecGetArray(da,U,&u);CHKERRQ(ierr);
226*c4762a1bSJed Brown 
227*c4762a1bSJed Brown   /*
228*c4762a1bSJed Brown      Get local grid boundaries
229*c4762a1bSJed Brown   */
230*c4762a1bSJed Brown   ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
231*c4762a1bSJed Brown 
232*c4762a1bSJed Brown   /*
233*c4762a1bSJed Brown      Compute function over the locally owned part of the grid
234*c4762a1bSJed Brown   */
235*c4762a1bSJed Brown   for (j=ys; j<ys+ym; j++) {
236*c4762a1bSJed Brown     y = j*hy;
237*c4762a1bSJed Brown     for (i=xs; i<xs+xm; i++) {
238*c4762a1bSJed Brown       x = i*hx;
239*c4762a1bSJed Brown       if ((1.0 <= x) && (x <= 1.5) && (1.0 <= y) && (y <= 1.5)) u[j][i].v = .25*PetscPowReal(PetscSinReal(4.0*PETSC_PI*x),2.0)*PetscPowReal(PetscSinReal(4.0*PETSC_PI*y),2.0);
240*c4762a1bSJed Brown       else u[j][i].v = 0.0;
241*c4762a1bSJed Brown 
242*c4762a1bSJed Brown       u[j][i].u = 1.0 - 2.0*u[j][i].v;
243*c4762a1bSJed Brown     }
244*c4762a1bSJed Brown   }
245*c4762a1bSJed Brown 
246*c4762a1bSJed Brown   /*
247*c4762a1bSJed Brown      Restore access to vector
248*c4762a1bSJed Brown   */
249*c4762a1bSJed Brown   ierr = DMDAVecRestoreArray(da,U,&u);CHKERRQ(ierr);
250*c4762a1bSJed Brown   PetscFunctionReturn(0);
251*c4762a1bSJed Brown }
252*c4762a1bSJed Brown 
253*c4762a1bSJed Brown /*
254*c4762a1bSJed Brown    RHSJacobian - Evaluates the Jacobian of the right hand side
255*c4762a1bSJed Brown      function of the ODE.
256*c4762a1bSJed Brown 
257*c4762a1bSJed Brown    Input Parameters:
258*c4762a1bSJed Brown .  ts - the TS context
259*c4762a1bSJed Brown .  time - current time
260*c4762a1bSJed Brown .  U - input vector
261*c4762a1bSJed Brown .  ptr - optional user-defined context, as set by TSSetRHSJacobian()
262*c4762a1bSJed Brown 
263*c4762a1bSJed Brown    Output Parameter:
264*c4762a1bSJed Brown .  A - the Jacobian
265*c4762a1bSJed Brown .  BB - optional additional matrix where an approximation to the Jacobian
266*c4762a1bSJed Brown         may be stored from which the preconditioner is constructed
267*c4762a1bSJed Brown  */
268*c4762a1bSJed Brown PetscErrorCode RHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat BB,void *ctx)
269*c4762a1bSJed Brown {
270*c4762a1bSJed Brown   AppCtx         *appctx = (AppCtx*)ctx;     /* user-defined application context */
271*c4762a1bSJed Brown   DM             da;
272*c4762a1bSJed Brown   PetscErrorCode ierr;
273*c4762a1bSJed Brown   PetscInt       i,j,Mx,My,xs,ys,xm,ym;
274*c4762a1bSJed Brown   PetscReal      hx,hy,sx,sy;
275*c4762a1bSJed Brown   PetscScalar    uc,vc;
276*c4762a1bSJed Brown   Field          **u;
277*c4762a1bSJed Brown   Vec            localU;
278*c4762a1bSJed Brown   MatStencil     stencil[6],rowstencil;
279*c4762a1bSJed Brown   PetscScalar    entries[6];
280*c4762a1bSJed Brown 
281*c4762a1bSJed Brown   PetscFunctionBegin;
282*c4762a1bSJed Brown   ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
283*c4762a1bSJed Brown   ierr = DMGetLocalVector(da,&localU);CHKERRQ(ierr);
284*c4762a1bSJed Brown   ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr);
285*c4762a1bSJed Brown 
286*c4762a1bSJed Brown   hx = 2.50/(PetscReal)(Mx); sx = 1.0/(hx*hx);
287*c4762a1bSJed Brown   hy = 2.50/(PetscReal)(My); sy = 1.0/(hy*hy);
288*c4762a1bSJed Brown 
289*c4762a1bSJed Brown   /*
290*c4762a1bSJed Brown      Scatter ghost points to local vector,using the 2-step process
291*c4762a1bSJed Brown   */
292*c4762a1bSJed Brown   ierr = DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
293*c4762a1bSJed Brown   ierr = DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
294*c4762a1bSJed Brown 
295*c4762a1bSJed Brown   /*
296*c4762a1bSJed Brown      Get pointers to vector data
297*c4762a1bSJed Brown   */
298*c4762a1bSJed Brown   ierr = DMDAVecGetArrayRead(da,localU,&u);CHKERRQ(ierr);
299*c4762a1bSJed Brown 
300*c4762a1bSJed Brown   /*
301*c4762a1bSJed Brown      Get local grid boundaries
302*c4762a1bSJed Brown   */
303*c4762a1bSJed Brown   ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
304*c4762a1bSJed Brown 
305*c4762a1bSJed Brown   stencil[0].k = 0;
306*c4762a1bSJed Brown   stencil[1].k = 0;
307*c4762a1bSJed Brown   stencil[2].k = 0;
308*c4762a1bSJed Brown   stencil[3].k = 0;
309*c4762a1bSJed Brown   stencil[4].k = 0;
310*c4762a1bSJed Brown   stencil[5].k = 0;
311*c4762a1bSJed Brown   rowstencil.k = 0;
312*c4762a1bSJed Brown   /*
313*c4762a1bSJed Brown      Compute function over the locally owned part of the grid
314*c4762a1bSJed Brown   */
315*c4762a1bSJed Brown   for (j=ys; j<ys+ym; j++) {
316*c4762a1bSJed Brown 
317*c4762a1bSJed Brown     stencil[0].j = j-1;
318*c4762a1bSJed Brown     stencil[1].j = j+1;
319*c4762a1bSJed Brown     stencil[2].j = j;
320*c4762a1bSJed Brown     stencil[3].j = j;
321*c4762a1bSJed Brown     stencil[4].j = j;
322*c4762a1bSJed Brown     stencil[5].j = j;
323*c4762a1bSJed Brown     rowstencil.k = 0; rowstencil.j = j;
324*c4762a1bSJed Brown     for (i=xs; i<xs+xm; i++) {
325*c4762a1bSJed Brown       uc = u[j][i].u;
326*c4762a1bSJed Brown       vc = u[j][i].v;
327*c4762a1bSJed Brown 
328*c4762a1bSJed Brown       /*      uxx       = (-2.0*uc + u[j][i-1].u + u[j][i+1].u)*sx;
329*c4762a1bSJed Brown       uyy       = (-2.0*uc + u[j-1][i].u + u[j+1][i].u)*sy;
330*c4762a1bSJed Brown 
331*c4762a1bSJed Brown       vxx       = (-2.0*vc + u[j][i-1].v + u[j][i+1].v)*sx;
332*c4762a1bSJed Brown       vyy       = (-2.0*vc + u[j-1][i].v + u[j+1][i].v)*sy;
333*c4762a1bSJed Brown        f[j][i].u = appctx->D1*(uxx + uyy) - uc*vc*vc + appctx->gamma*(1.0 - uc);*/
334*c4762a1bSJed Brown 
335*c4762a1bSJed Brown       stencil[0].i = i; stencil[0].c = 0; entries[0] = appctx->D1*sy;
336*c4762a1bSJed Brown       stencil[1].i = i; stencil[1].c = 0; entries[1] = appctx->D1*sy;
337*c4762a1bSJed Brown       stencil[2].i = i-1; stencil[2].c = 0; entries[2] = appctx->D1*sx;
338*c4762a1bSJed Brown       stencil[3].i = i+1; stencil[3].c = 0; entries[3] = appctx->D1*sx;
339*c4762a1bSJed Brown       stencil[4].i = i; stencil[4].c = 0; entries[4] = -2.0*appctx->D1*(sx + sy) - vc*vc - appctx->gamma;
340*c4762a1bSJed Brown       stencil[5].i = i; stencil[5].c = 1; entries[5] = -2.0*uc*vc;
341*c4762a1bSJed Brown       rowstencil.i = i; rowstencil.c = 0;
342*c4762a1bSJed Brown 
343*c4762a1bSJed Brown       ierr = MatSetValuesStencil(A,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr);
344*c4762a1bSJed Brown 
345*c4762a1bSJed Brown       stencil[0].c = 1; entries[0] = appctx->D2*sy;
346*c4762a1bSJed Brown       stencil[1].c = 1; entries[1] = appctx->D2*sy;
347*c4762a1bSJed Brown       stencil[2].c = 1; entries[2] = appctx->D2*sx;
348*c4762a1bSJed Brown       stencil[3].c = 1; entries[3] = appctx->D2*sx;
349*c4762a1bSJed Brown       stencil[4].c = 1; entries[4] = -2.0*appctx->D2*(sx + sy) + 2.0*uc*vc - appctx->gamma - appctx->kappa;
350*c4762a1bSJed Brown       stencil[5].c = 0; entries[5] = vc*vc;
351*c4762a1bSJed Brown       rowstencil.c = 1;
352*c4762a1bSJed Brown 
353*c4762a1bSJed Brown       ierr = MatSetValuesStencil(A,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr);
354*c4762a1bSJed Brown       /* f[j][i].v = appctx->D2*(vxx + vyy) + uc*vc*vc - (appctx->gamma + appctx->kappa)*vc; */
355*c4762a1bSJed Brown     }
356*c4762a1bSJed Brown   }
357*c4762a1bSJed Brown 
358*c4762a1bSJed Brown   /*
359*c4762a1bSJed Brown      Restore vectors
360*c4762a1bSJed Brown   */
361*c4762a1bSJed Brown   ierr = PetscLogFlops(19*xm*ym);CHKERRQ(ierr);
362*c4762a1bSJed Brown   ierr = DMDAVecRestoreArrayRead(da,localU,&u);CHKERRQ(ierr);
363*c4762a1bSJed Brown   ierr = DMRestoreLocalVector(da,&localU);CHKERRQ(ierr);
364*c4762a1bSJed Brown   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
365*c4762a1bSJed Brown   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
366*c4762a1bSJed Brown   ierr = MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
367*c4762a1bSJed Brown   PetscFunctionReturn(0);
368*c4762a1bSJed Brown }
369*c4762a1bSJed Brown 
370*c4762a1bSJed Brown 
371*c4762a1bSJed Brown /*TEST
372*c4762a1bSJed Brown 
373*c4762a1bSJed Brown    test:
374*c4762a1bSJed Brown       args: -ts_view  -ts_monitor -ts_max_time 500
375*c4762a1bSJed Brown       requires: double
376*c4762a1bSJed Brown       timeoutfactor: 3
377*c4762a1bSJed Brown 
378*c4762a1bSJed Brown    test:
379*c4762a1bSJed Brown       suffix: 2
380*c4762a1bSJed Brown       args: -ts_view  -ts_monitor -ts_max_time 500 -ts_monitor_draw_solution
381*c4762a1bSJed Brown       requires: x double
382*c4762a1bSJed Brown       output_file: output/ex5_1.out
383*c4762a1bSJed Brown       timeoutfactor: 3
384*c4762a1bSJed Brown 
385*c4762a1bSJed Brown TEST*/
386