xref: /petsc/src/ts/tutorials/advection-diffusion-reaction/ex5adj.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1*c4762a1bSJed Brown static char help[] = "Demonstrates adjoint sensitivity analysis for Reaction-Diffusion Equations.\n";
2*c4762a1bSJed Brown 
3*c4762a1bSJed Brown /*
4*c4762a1bSJed Brown   See ex5.c for details on the equation.
5*c4762a1bSJed Brown   This code demonestrates the TSAdjoint interface to a system of time-dependent partial differential equations.
6*c4762a1bSJed Brown   It computes the sensitivity of a component in the final solution, which locates in the center of the 2D domain, w.r.t. the initial conditions.
7*c4762a1bSJed Brown   The user does not need to provide any additional functions. The required functions in the original simulation are reused in the adjoint run.
8*c4762a1bSJed Brown 
9*c4762a1bSJed Brown   Runtime options:
10*c4762a1bSJed Brown     -forwardonly  - run the forward simulation without adjoint
11*c4762a1bSJed Brown     -implicitform - provide IFunction and IJacobian to TS, if not set, RHSFunction and RHSJacobian will be used
12*c4762a1bSJed Brown     -aijpc        - set the preconditioner matrix to be aij (the Jacobian matrix can be of a different type such as ELL)
13*c4762a1bSJed Brown */
14*c4762a1bSJed Brown 
15*c4762a1bSJed Brown #include <petscsys.h>
16*c4762a1bSJed Brown #include <petscdm.h>
17*c4762a1bSJed Brown #include <petscdmda.h>
18*c4762a1bSJed Brown #include <petscts.h>
19*c4762a1bSJed Brown 
20*c4762a1bSJed Brown typedef struct {
21*c4762a1bSJed Brown   PetscScalar u,v;
22*c4762a1bSJed Brown } Field;
23*c4762a1bSJed Brown 
24*c4762a1bSJed Brown typedef struct {
25*c4762a1bSJed Brown   PetscReal D1,D2,gamma,kappa;
26*c4762a1bSJed Brown   PetscBool aijpc;
27*c4762a1bSJed Brown } AppCtx;
28*c4762a1bSJed Brown 
29*c4762a1bSJed Brown /*
30*c4762a1bSJed Brown    User-defined routines
31*c4762a1bSJed Brown */
32*c4762a1bSJed Brown PetscErrorCode RHSFunction(TS,PetscReal,Vec,Vec,void*);
33*c4762a1bSJed Brown PetscErrorCode InitialConditions(DM,Vec);
34*c4762a1bSJed Brown PetscErrorCode RHSJacobian(TS,PetscReal,Vec,Mat,Mat,void*);
35*c4762a1bSJed Brown PetscErrorCode IFunction(TS,PetscReal,Vec,Vec,Vec,void*);
36*c4762a1bSJed Brown PetscErrorCode IJacobian(TS,PetscReal,Vec,Vec,PetscReal,Mat,Mat,void*);
37*c4762a1bSJed Brown 
38*c4762a1bSJed Brown PetscErrorCode InitializeLambda(DM da,Vec lambda,PetscReal x,PetscReal y)
39*c4762a1bSJed Brown {
40*c4762a1bSJed Brown    PetscInt i,j,Mx,My,xs,ys,xm,ym;
41*c4762a1bSJed Brown    PetscErrorCode ierr;
42*c4762a1bSJed Brown    Field **l;
43*c4762a1bSJed Brown    PetscFunctionBegin;
44*c4762a1bSJed Brown 
45*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);
46*c4762a1bSJed Brown    /* locate the global i index for x and j index for y */
47*c4762a1bSJed Brown    i = (PetscInt)(x*(Mx-1));
48*c4762a1bSJed Brown    j = (PetscInt)(y*(My-1));
49*c4762a1bSJed Brown    ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
50*c4762a1bSJed Brown 
51*c4762a1bSJed Brown    if (xs <= i && i < xs+xm && ys <= j && j < ys+ym) {
52*c4762a1bSJed Brown      /* the i,j vertex is on this process */
53*c4762a1bSJed Brown      ierr = DMDAVecGetArray(da,lambda,&l);CHKERRQ(ierr);
54*c4762a1bSJed Brown      l[j][i].u = 1.0;
55*c4762a1bSJed Brown      l[j][i].v = 1.0;
56*c4762a1bSJed Brown      ierr = DMDAVecRestoreArray(da,lambda,&l);CHKERRQ(ierr);
57*c4762a1bSJed Brown    }
58*c4762a1bSJed Brown    PetscFunctionReturn(0);
59*c4762a1bSJed Brown }
60*c4762a1bSJed Brown 
61*c4762a1bSJed Brown int main(int argc,char **argv)
62*c4762a1bSJed Brown {
63*c4762a1bSJed Brown   TS             ts;                  /* ODE integrator */
64*c4762a1bSJed Brown   Vec            x;                   /* solution */
65*c4762a1bSJed Brown   PetscErrorCode ierr;
66*c4762a1bSJed Brown   DM             da;
67*c4762a1bSJed Brown   AppCtx         appctx;
68*c4762a1bSJed Brown   Vec            lambda[1];
69*c4762a1bSJed Brown   PetscBool      forwardonly=PETSC_FALSE,implicitform=PETSC_TRUE;
70*c4762a1bSJed Brown 
71*c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
72*c4762a1bSJed Brown   ierr = PetscOptionsGetBool(NULL,NULL,"-forwardonly",&forwardonly,NULL);CHKERRQ(ierr);
73*c4762a1bSJed Brown   ierr = PetscOptionsGetBool(NULL,NULL,"-implicitform",&implicitform,NULL);CHKERRQ(ierr);
74*c4762a1bSJed Brown   appctx.aijpc = PETSC_FALSE;
75*c4762a1bSJed Brown   ierr = PetscOptionsGetBool(NULL,NULL,"-aijpc",&appctx.aijpc,NULL);CHKERRQ(ierr);
76*c4762a1bSJed Brown 
77*c4762a1bSJed Brown   appctx.D1    = 8.0e-5;
78*c4762a1bSJed Brown   appctx.D2    = 4.0e-5;
79*c4762a1bSJed Brown   appctx.gamma = .024;
80*c4762a1bSJed Brown   appctx.kappa = .06;
81*c4762a1bSJed Brown 
82*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
83*c4762a1bSJed Brown      Create distributed array (DMDA) to manage parallel grid and vectors
84*c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
85*c4762a1bSJed Brown   ierr = DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_PERIODIC,DM_BOUNDARY_PERIODIC,DMDA_STENCIL_STAR,64,64,PETSC_DECIDE,PETSC_DECIDE,2,1,NULL,NULL,&da);CHKERRQ(ierr);
86*c4762a1bSJed Brown   ierr = DMSetFromOptions(da);CHKERRQ(ierr);
87*c4762a1bSJed Brown   ierr = DMSetUp(da);CHKERRQ(ierr);
88*c4762a1bSJed Brown   ierr = DMDASetFieldName(da,0,"u");CHKERRQ(ierr);
89*c4762a1bSJed Brown   ierr = DMDASetFieldName(da,1,"v");CHKERRQ(ierr);
90*c4762a1bSJed Brown 
91*c4762a1bSJed Brown   /*  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
92*c4762a1bSJed Brown      Extract global vectors from DMDA; then duplicate for remaining
93*c4762a1bSJed Brown      vectors that are the same types
94*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
95*c4762a1bSJed Brown   ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr);
96*c4762a1bSJed Brown 
97*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
98*c4762a1bSJed Brown      Create timestepping solver context
99*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
100*c4762a1bSJed Brown   ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr);
101*c4762a1bSJed Brown   ierr = TSSetDM(ts,da);CHKERRQ(ierr);
102*c4762a1bSJed Brown   ierr = TSSetProblemType(ts,TS_NONLINEAR);CHKERRQ(ierr);
103*c4762a1bSJed Brown   ierr = TSSetEquationType(ts,TS_EQ_ODE_EXPLICIT);CHKERRQ(ierr); /* less Jacobian evaluations when adjoint BEuler is used, otherwise no effect */
104*c4762a1bSJed Brown   if (!implicitform) {
105*c4762a1bSJed Brown     ierr = TSSetType(ts,TSRK);CHKERRQ(ierr);
106*c4762a1bSJed Brown     ierr = TSSetRHSFunction(ts,NULL,RHSFunction,&appctx);CHKERRQ(ierr);
107*c4762a1bSJed Brown     ierr = TSSetRHSJacobian(ts,NULL,NULL,RHSJacobian,&appctx);CHKERRQ(ierr);
108*c4762a1bSJed Brown   } else {
109*c4762a1bSJed Brown     ierr = TSSetType(ts,TSCN);CHKERRQ(ierr);
110*c4762a1bSJed Brown     ierr = TSSetIFunction(ts,NULL,IFunction,&appctx);CHKERRQ(ierr);
111*c4762a1bSJed Brown     if (appctx.aijpc) {
112*c4762a1bSJed Brown       Mat                    A,B;
113*c4762a1bSJed Brown 
114*c4762a1bSJed Brown       ierr = DMSetMatType(da,MATSELL);CHKERRQ(ierr);
115*c4762a1bSJed Brown       ierr = DMCreateMatrix(da,&A);CHKERRQ(ierr);
116*c4762a1bSJed Brown       ierr = MatConvert(A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
117*c4762a1bSJed Brown       /* FIXME do we need to change viewer to display matrix in natural ordering as DMCreateMatrix_DA does? */
118*c4762a1bSJed Brown       ierr = TSSetIJacobian(ts,A,B,IJacobian,&appctx);CHKERRQ(ierr);
119*c4762a1bSJed Brown       ierr = MatDestroy(&A);CHKERRQ(ierr);
120*c4762a1bSJed Brown       ierr = MatDestroy(&B);CHKERRQ(ierr);
121*c4762a1bSJed Brown     } else {
122*c4762a1bSJed Brown       ierr = TSSetIJacobian(ts,NULL,NULL,IJacobian,&appctx);CHKERRQ(ierr);
123*c4762a1bSJed Brown     }
124*c4762a1bSJed Brown   }
125*c4762a1bSJed Brown 
126*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
127*c4762a1bSJed Brown      Set initial conditions
128*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
129*c4762a1bSJed Brown   ierr = InitialConditions(da,x);CHKERRQ(ierr);
130*c4762a1bSJed Brown   ierr = TSSetSolution(ts,x);CHKERRQ(ierr);
131*c4762a1bSJed Brown 
132*c4762a1bSJed Brown   /*
133*c4762a1bSJed Brown     Have the TS save its trajectory so that TSAdjointSolve() may be used
134*c4762a1bSJed Brown   */
135*c4762a1bSJed Brown   if (!forwardonly) { ierr = TSSetSaveTrajectory(ts);CHKERRQ(ierr); }
136*c4762a1bSJed Brown 
137*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
138*c4762a1bSJed Brown      Set solver options
139*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
140*c4762a1bSJed Brown   ierr = TSSetMaxTime(ts,200.0);CHKERRQ(ierr);
141*c4762a1bSJed Brown   ierr = TSSetTimeStep(ts,0.5);CHKERRQ(ierr);
142*c4762a1bSJed Brown   ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP);CHKERRQ(ierr);
143*c4762a1bSJed Brown   ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
144*c4762a1bSJed Brown 
145*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
146*c4762a1bSJed Brown      Solve ODE system
147*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
148*c4762a1bSJed Brown   ierr = TSSolve(ts,x);CHKERRQ(ierr);
149*c4762a1bSJed Brown   if (!forwardonly) {
150*c4762a1bSJed Brown     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
151*c4762a1bSJed Brown        Start the Adjoint model
152*c4762a1bSJed Brown        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
153*c4762a1bSJed Brown     ierr = VecDuplicate(x,&lambda[0]);CHKERRQ(ierr);
154*c4762a1bSJed Brown     /*   Reset initial conditions for the adjoint integration */
155*c4762a1bSJed Brown     ierr = InitializeLambda(da,lambda[0],0.5,0.5);CHKERRQ(ierr);
156*c4762a1bSJed Brown     ierr = TSSetCostGradients(ts,1,lambda,NULL);CHKERRQ(ierr);
157*c4762a1bSJed Brown     ierr = TSAdjointSolve(ts);CHKERRQ(ierr);
158*c4762a1bSJed Brown     ierr = VecDestroy(&lambda[0]);CHKERRQ(ierr);
159*c4762a1bSJed Brown   }
160*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
161*c4762a1bSJed Brown      Free work space.  All PETSc objects should be destroyed when they
162*c4762a1bSJed Brown      are no longer needed.
163*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
164*c4762a1bSJed Brown   ierr = VecDestroy(&x);CHKERRQ(ierr);
165*c4762a1bSJed Brown   ierr = TSDestroy(&ts);CHKERRQ(ierr);
166*c4762a1bSJed Brown   ierr = DMDestroy(&da);CHKERRQ(ierr);
167*c4762a1bSJed Brown   ierr = PetscFinalize();
168*c4762a1bSJed Brown   return ierr;
169*c4762a1bSJed Brown }
170*c4762a1bSJed Brown 
171*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
172*c4762a1bSJed Brown /*
173*c4762a1bSJed Brown    RHSFunction - Evaluates nonlinear function, F(x).
174*c4762a1bSJed Brown 
175*c4762a1bSJed Brown    Input Parameters:
176*c4762a1bSJed Brown .  ts - the TS context
177*c4762a1bSJed Brown .  X - input vector
178*c4762a1bSJed Brown .  ptr - optional user-defined context, as set by TSSetRHSFunction()
179*c4762a1bSJed Brown 
180*c4762a1bSJed Brown    Output Parameter:
181*c4762a1bSJed Brown .  F - function vector
182*c4762a1bSJed Brown  */
183*c4762a1bSJed Brown PetscErrorCode RHSFunction(TS ts,PetscReal ftime,Vec U,Vec F,void *ptr)
184*c4762a1bSJed Brown {
185*c4762a1bSJed Brown   AppCtx         *appctx = (AppCtx*)ptr;
186*c4762a1bSJed Brown   DM             da;
187*c4762a1bSJed Brown   PetscErrorCode ierr;
188*c4762a1bSJed Brown   PetscInt       i,j,Mx,My,xs,ys,xm,ym;
189*c4762a1bSJed Brown   PetscReal      hx,hy,sx,sy;
190*c4762a1bSJed Brown   PetscScalar    uc,uxx,uyy,vc,vxx,vyy;
191*c4762a1bSJed Brown   Field          **u,**f;
192*c4762a1bSJed Brown   Vec            localU;
193*c4762a1bSJed Brown 
194*c4762a1bSJed Brown   PetscFunctionBegin;
195*c4762a1bSJed Brown   ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
196*c4762a1bSJed Brown   ierr = DMGetLocalVector(da,&localU);CHKERRQ(ierr);
197*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);
198*c4762a1bSJed Brown   hx = 2.50/(PetscReal)Mx; sx = 1.0/(hx*hx);
199*c4762a1bSJed Brown   hy = 2.50/(PetscReal)My; sy = 1.0/(hy*hy);
200*c4762a1bSJed Brown 
201*c4762a1bSJed Brown   /*
202*c4762a1bSJed Brown      Scatter ghost points to local vector,using the 2-step process
203*c4762a1bSJed Brown         DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
204*c4762a1bSJed Brown      By placing code between these two statements, computations can be
205*c4762a1bSJed Brown      done while messages are in transition.
206*c4762a1bSJed Brown   */
207*c4762a1bSJed Brown   ierr = DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
208*c4762a1bSJed Brown   ierr = DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
209*c4762a1bSJed Brown 
210*c4762a1bSJed Brown   /*
211*c4762a1bSJed Brown      Get pointers to vector data
212*c4762a1bSJed Brown   */
213*c4762a1bSJed Brown   ierr = DMDAVecGetArrayRead(da,localU,&u);CHKERRQ(ierr);
214*c4762a1bSJed Brown   ierr = DMDAVecGetArray(da,F,&f);CHKERRQ(ierr);
215*c4762a1bSJed Brown 
216*c4762a1bSJed Brown   /*
217*c4762a1bSJed Brown      Get local grid boundaries
218*c4762a1bSJed Brown   */
219*c4762a1bSJed Brown   ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
220*c4762a1bSJed Brown 
221*c4762a1bSJed Brown   /*
222*c4762a1bSJed Brown      Compute function over the locally owned part of the grid
223*c4762a1bSJed Brown   */
224*c4762a1bSJed Brown   for (j=ys; j<ys+ym; j++) {
225*c4762a1bSJed Brown     for (i=xs; i<xs+xm; i++) {
226*c4762a1bSJed Brown       uc        = u[j][i].u;
227*c4762a1bSJed Brown       uxx       = (-2.0*uc + u[j][i-1].u + u[j][i+1].u)*sx;
228*c4762a1bSJed Brown       uyy       = (-2.0*uc + u[j-1][i].u + u[j+1][i].u)*sy;
229*c4762a1bSJed Brown       vc        = u[j][i].v;
230*c4762a1bSJed Brown       vxx       = (-2.0*vc + u[j][i-1].v + u[j][i+1].v)*sx;
231*c4762a1bSJed Brown       vyy       = (-2.0*vc + u[j-1][i].v + u[j+1][i].v)*sy;
232*c4762a1bSJed Brown       f[j][i].u = appctx->D1*(uxx + uyy) - uc*vc*vc + appctx->gamma*(1.0 - uc);
233*c4762a1bSJed Brown       f[j][i].v = appctx->D2*(vxx + vyy) + uc*vc*vc - (appctx->gamma + appctx->kappa)*vc;
234*c4762a1bSJed Brown     }
235*c4762a1bSJed Brown   }
236*c4762a1bSJed Brown   ierr = PetscLogFlops(16*xm*ym);CHKERRQ(ierr);
237*c4762a1bSJed Brown 
238*c4762a1bSJed Brown   /*
239*c4762a1bSJed Brown      Restore vectors
240*c4762a1bSJed Brown   */
241*c4762a1bSJed Brown   ierr = DMDAVecRestoreArrayRead(da,localU,&u);CHKERRQ(ierr);
242*c4762a1bSJed Brown   ierr = DMDAVecRestoreArray(da,F,&f);CHKERRQ(ierr);
243*c4762a1bSJed Brown   ierr = DMRestoreLocalVector(da,&localU);CHKERRQ(ierr);
244*c4762a1bSJed Brown   PetscFunctionReturn(0);
245*c4762a1bSJed Brown }
246*c4762a1bSJed Brown 
247*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
248*c4762a1bSJed Brown PetscErrorCode InitialConditions(DM da,Vec U)
249*c4762a1bSJed Brown {
250*c4762a1bSJed Brown   PetscErrorCode ierr;
251*c4762a1bSJed Brown   PetscInt       i,j,xs,ys,xm,ym,Mx,My;
252*c4762a1bSJed Brown   Field          **u;
253*c4762a1bSJed Brown   PetscReal      hx,hy,x,y;
254*c4762a1bSJed Brown 
255*c4762a1bSJed Brown   PetscFunctionBegin;
256*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);
257*c4762a1bSJed Brown 
258*c4762a1bSJed Brown   hx = 2.5/(PetscReal)Mx;
259*c4762a1bSJed Brown   hy = 2.5/(PetscReal)My;
260*c4762a1bSJed Brown 
261*c4762a1bSJed Brown   /*
262*c4762a1bSJed Brown      Get pointers to vector data
263*c4762a1bSJed Brown   */
264*c4762a1bSJed Brown   ierr = DMDAVecGetArray(da,U,&u);CHKERRQ(ierr);
265*c4762a1bSJed Brown 
266*c4762a1bSJed Brown   /*
267*c4762a1bSJed Brown      Get local grid boundaries
268*c4762a1bSJed Brown   */
269*c4762a1bSJed Brown   ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
270*c4762a1bSJed Brown 
271*c4762a1bSJed Brown   /*
272*c4762a1bSJed Brown      Compute function over the locally owned part of the grid
273*c4762a1bSJed Brown   */
274*c4762a1bSJed Brown   for (j=ys; j<ys+ym; j++) {
275*c4762a1bSJed Brown     y = j*hy;
276*c4762a1bSJed Brown     for (i=xs; i<xs+xm; i++) {
277*c4762a1bSJed Brown       x = i*hx;
278*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);
279*c4762a1bSJed Brown       else u[j][i].v = 0.0;
280*c4762a1bSJed Brown 
281*c4762a1bSJed Brown       u[j][i].u = 1.0 - 2.0*u[j][i].v;
282*c4762a1bSJed Brown     }
283*c4762a1bSJed Brown   }
284*c4762a1bSJed Brown 
285*c4762a1bSJed Brown   /*
286*c4762a1bSJed Brown      Restore vectors
287*c4762a1bSJed Brown   */
288*c4762a1bSJed Brown   ierr = DMDAVecRestoreArray(da,U,&u);CHKERRQ(ierr);
289*c4762a1bSJed Brown   PetscFunctionReturn(0);
290*c4762a1bSJed Brown }
291*c4762a1bSJed Brown 
292*c4762a1bSJed Brown PetscErrorCode RHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat BB,void *ctx)
293*c4762a1bSJed Brown {
294*c4762a1bSJed Brown   AppCtx         *appctx = (AppCtx*)ctx;     /* user-defined application context */
295*c4762a1bSJed Brown   DM             da;
296*c4762a1bSJed Brown   PetscErrorCode ierr;
297*c4762a1bSJed Brown   PetscInt       i,j,Mx,My,xs,ys,xm,ym;
298*c4762a1bSJed Brown   PetscReal      hx,hy,sx,sy;
299*c4762a1bSJed Brown   PetscScalar    uc,vc;
300*c4762a1bSJed Brown   Field          **u;
301*c4762a1bSJed Brown   Vec            localU;
302*c4762a1bSJed Brown   MatStencil     stencil[6],rowstencil;
303*c4762a1bSJed Brown   PetscScalar    entries[6];
304*c4762a1bSJed Brown 
305*c4762a1bSJed Brown   PetscFunctionBegin;
306*c4762a1bSJed Brown   ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
307*c4762a1bSJed Brown   ierr = DMGetLocalVector(da,&localU);CHKERRQ(ierr);
308*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);
309*c4762a1bSJed Brown 
310*c4762a1bSJed Brown   hx = 2.50/(PetscReal)Mx; sx = 1.0/(hx*hx);
311*c4762a1bSJed Brown   hy = 2.50/(PetscReal)My; sy = 1.0/(hy*hy);
312*c4762a1bSJed Brown 
313*c4762a1bSJed Brown   /*
314*c4762a1bSJed Brown      Scatter ghost points to local vector,using the 2-step process
315*c4762a1bSJed Brown         DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
316*c4762a1bSJed Brown      By placing code between these two statements, computations can be
317*c4762a1bSJed Brown      done while messages are in transition.
318*c4762a1bSJed Brown   */
319*c4762a1bSJed Brown   ierr = DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
320*c4762a1bSJed Brown   ierr = DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
321*c4762a1bSJed Brown 
322*c4762a1bSJed Brown   /*
323*c4762a1bSJed Brown      Get pointers to vector data
324*c4762a1bSJed Brown   */
325*c4762a1bSJed Brown   ierr = DMDAVecGetArrayRead(da,localU,&u);CHKERRQ(ierr);
326*c4762a1bSJed Brown 
327*c4762a1bSJed Brown   /*
328*c4762a1bSJed Brown      Get local grid boundaries
329*c4762a1bSJed Brown   */
330*c4762a1bSJed Brown   ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
331*c4762a1bSJed Brown 
332*c4762a1bSJed Brown   stencil[0].k = 0;
333*c4762a1bSJed Brown   stencil[1].k = 0;
334*c4762a1bSJed Brown   stencil[2].k = 0;
335*c4762a1bSJed Brown   stencil[3].k = 0;
336*c4762a1bSJed Brown   stencil[4].k = 0;
337*c4762a1bSJed Brown   stencil[5].k = 0;
338*c4762a1bSJed Brown   rowstencil.k = 0;
339*c4762a1bSJed Brown   /*
340*c4762a1bSJed Brown      Compute function over the locally owned part of the grid
341*c4762a1bSJed Brown   */
342*c4762a1bSJed Brown   for (j=ys; j<ys+ym; j++) {
343*c4762a1bSJed Brown 
344*c4762a1bSJed Brown     stencil[0].j = j-1;
345*c4762a1bSJed Brown     stencil[1].j = j+1;
346*c4762a1bSJed Brown     stencil[2].j = j;
347*c4762a1bSJed Brown     stencil[3].j = j;
348*c4762a1bSJed Brown     stencil[4].j = j;
349*c4762a1bSJed Brown     stencil[5].j = j;
350*c4762a1bSJed Brown     rowstencil.k = 0; rowstencil.j = j;
351*c4762a1bSJed Brown     for (i=xs; i<xs+xm; i++) {
352*c4762a1bSJed Brown       uc = u[j][i].u;
353*c4762a1bSJed Brown       vc = u[j][i].v;
354*c4762a1bSJed Brown 
355*c4762a1bSJed Brown       /*      uxx       = (-2.0*uc + u[j][i-1].u + u[j][i+1].u)*sx;
356*c4762a1bSJed Brown       uyy       = (-2.0*uc + u[j-1][i].u + u[j+1][i].u)*sy;
357*c4762a1bSJed Brown 
358*c4762a1bSJed Brown       vxx       = (-2.0*vc + u[j][i-1].v + u[j][i+1].v)*sx;
359*c4762a1bSJed Brown       vyy       = (-2.0*vc + u[j-1][i].v + u[j+1][i].v)*sy;
360*c4762a1bSJed Brown        f[j][i].u = appctx->D1*(uxx + uyy) - uc*vc*vc + appctx->gamma*(1.0 - uc);*/
361*c4762a1bSJed Brown 
362*c4762a1bSJed Brown       stencil[0].i = i; stencil[0].c = 0; entries[0] = appctx->D1*sy;
363*c4762a1bSJed Brown       stencil[1].i = i; stencil[1].c = 0; entries[1] = appctx->D1*sy;
364*c4762a1bSJed Brown       stencil[2].i = i-1; stencil[2].c = 0; entries[2] = appctx->D1*sx;
365*c4762a1bSJed Brown       stencil[3].i = i+1; stencil[3].c = 0; entries[3] = appctx->D1*sx;
366*c4762a1bSJed Brown       stencil[4].i = i; stencil[4].c = 0; entries[4] = -2.0*appctx->D1*(sx + sy) - vc*vc - appctx->gamma;
367*c4762a1bSJed Brown       stencil[5].i = i; stencil[5].c = 1; entries[5] = -2.0*uc*vc;
368*c4762a1bSJed Brown       rowstencil.i = i; rowstencil.c = 0;
369*c4762a1bSJed Brown 
370*c4762a1bSJed Brown       ierr = MatSetValuesStencil(A,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr);
371*c4762a1bSJed Brown       if (appctx->aijpc) {
372*c4762a1bSJed Brown         ierr = MatSetValuesStencil(BB,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr);
373*c4762a1bSJed Brown       }
374*c4762a1bSJed Brown       stencil[0].c = 1; entries[0] = appctx->D2*sy;
375*c4762a1bSJed Brown       stencil[1].c = 1; entries[1] = appctx->D2*sy;
376*c4762a1bSJed Brown       stencil[2].c = 1; entries[2] = appctx->D2*sx;
377*c4762a1bSJed Brown       stencil[3].c = 1; entries[3] = appctx->D2*sx;
378*c4762a1bSJed Brown       stencil[4].c = 1; entries[4] = -2.0*appctx->D2*(sx + sy) + 2.0*uc*vc - appctx->gamma - appctx->kappa;
379*c4762a1bSJed Brown       stencil[5].c = 0; entries[5] = vc*vc;
380*c4762a1bSJed Brown       rowstencil.c = 1;
381*c4762a1bSJed Brown 
382*c4762a1bSJed Brown       ierr = MatSetValuesStencil(A,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr);
383*c4762a1bSJed Brown       if (appctx->aijpc) {
384*c4762a1bSJed Brown         ierr = MatSetValuesStencil(BB,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr);
385*c4762a1bSJed Brown       }
386*c4762a1bSJed Brown       /* f[j][i].v = appctx->D2*(vxx + vyy) + uc*vc*vc - (appctx->gamma + appctx->kappa)*vc; */
387*c4762a1bSJed Brown     }
388*c4762a1bSJed Brown   }
389*c4762a1bSJed Brown 
390*c4762a1bSJed Brown   /*
391*c4762a1bSJed Brown      Restore vectors
392*c4762a1bSJed Brown   */
393*c4762a1bSJed Brown   ierr = PetscLogFlops(19*xm*ym);CHKERRQ(ierr);
394*c4762a1bSJed Brown   ierr = DMDAVecRestoreArrayRead(da,localU,&u);CHKERRQ(ierr);
395*c4762a1bSJed Brown   ierr = DMRestoreLocalVector(da,&localU);CHKERRQ(ierr);
396*c4762a1bSJed Brown   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
397*c4762a1bSJed Brown   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
398*c4762a1bSJed Brown   ierr = MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
399*c4762a1bSJed Brown   if (appctx->aijpc) {
400*c4762a1bSJed Brown     ierr = MatAssemblyBegin(BB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
401*c4762a1bSJed Brown     ierr = MatAssemblyEnd(BB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
402*c4762a1bSJed Brown     ierr = MatSetOption(BB,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
403*c4762a1bSJed Brown   }
404*c4762a1bSJed Brown 
405*c4762a1bSJed Brown   PetscFunctionReturn(0);
406*c4762a1bSJed Brown }
407*c4762a1bSJed Brown 
408*c4762a1bSJed Brown /*
409*c4762a1bSJed Brown    IFunction - Evaluates implicit nonlinear function, xdot - F(x).
410*c4762a1bSJed Brown 
411*c4762a1bSJed Brown    Input Parameters:
412*c4762a1bSJed Brown .  ts - the TS context
413*c4762a1bSJed Brown .  U - input vector
414*c4762a1bSJed Brown .  Udot - input vector
415*c4762a1bSJed Brown .  ptr - optional user-defined context, as set by TSSetRHSFunction()
416*c4762a1bSJed Brown 
417*c4762a1bSJed Brown    Output Parameter:
418*c4762a1bSJed Brown .  F - function vector
419*c4762a1bSJed Brown  */
420*c4762a1bSJed Brown PetscErrorCode IFunction(TS ts,PetscReal ftime,Vec U,Vec Udot,Vec F,void *ptr)
421*c4762a1bSJed Brown {
422*c4762a1bSJed Brown   AppCtx         *appctx = (AppCtx*)ptr;
423*c4762a1bSJed Brown   DM             da;
424*c4762a1bSJed Brown   PetscErrorCode ierr;
425*c4762a1bSJed Brown   PetscInt       i,j,Mx,My,xs,ys,xm,ym;
426*c4762a1bSJed Brown   PetscReal      hx,hy,sx,sy;
427*c4762a1bSJed Brown   PetscScalar    uc,uxx,uyy,vc,vxx,vyy;
428*c4762a1bSJed Brown   Field          **u,**f,**udot;
429*c4762a1bSJed Brown   Vec            localU;
430*c4762a1bSJed Brown 
431*c4762a1bSJed Brown   PetscFunctionBegin;
432*c4762a1bSJed Brown   ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
433*c4762a1bSJed Brown   ierr = DMGetLocalVector(da,&localU);CHKERRQ(ierr);
434*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);
435*c4762a1bSJed Brown   hx = 2.50/(PetscReal)Mx; sx = 1.0/(hx*hx);
436*c4762a1bSJed Brown   hy = 2.50/(PetscReal)My; sy = 1.0/(hy*hy);
437*c4762a1bSJed Brown 
438*c4762a1bSJed Brown   /*
439*c4762a1bSJed Brown      Scatter ghost points to local vector,using the 2-step process
440*c4762a1bSJed Brown         DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
441*c4762a1bSJed Brown      By placing code between these two statements, computations can be
442*c4762a1bSJed Brown      done while messages are in transition.
443*c4762a1bSJed Brown   */
444*c4762a1bSJed Brown   ierr = DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
445*c4762a1bSJed Brown   ierr = DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
446*c4762a1bSJed Brown 
447*c4762a1bSJed Brown   /*
448*c4762a1bSJed Brown      Get pointers to vector data
449*c4762a1bSJed Brown   */
450*c4762a1bSJed Brown   ierr = DMDAVecGetArrayRead(da,localU,&u);CHKERRQ(ierr);
451*c4762a1bSJed Brown   ierr = DMDAVecGetArray(da,F,&f);CHKERRQ(ierr);
452*c4762a1bSJed Brown   ierr = DMDAVecGetArrayRead(da,Udot,&udot);CHKERRQ(ierr);
453*c4762a1bSJed Brown 
454*c4762a1bSJed Brown   /*
455*c4762a1bSJed Brown      Get local grid boundaries
456*c4762a1bSJed Brown   */
457*c4762a1bSJed Brown   ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
458*c4762a1bSJed Brown 
459*c4762a1bSJed Brown   /*
460*c4762a1bSJed Brown      Compute function over the locally owned part of the grid
461*c4762a1bSJed Brown   */
462*c4762a1bSJed Brown   for (j=ys; j<ys+ym; j++) {
463*c4762a1bSJed Brown     for (i=xs; i<xs+xm; i++) {
464*c4762a1bSJed Brown       uc        = u[j][i].u;
465*c4762a1bSJed Brown       uxx       = (-2.0*uc + u[j][i-1].u + u[j][i+1].u)*sx;
466*c4762a1bSJed Brown       uyy       = (-2.0*uc + u[j-1][i].u + u[j+1][i].u)*sy;
467*c4762a1bSJed Brown       vc        = u[j][i].v;
468*c4762a1bSJed Brown       vxx       = (-2.0*vc + u[j][i-1].v + u[j][i+1].v)*sx;
469*c4762a1bSJed Brown       vyy       = (-2.0*vc + u[j-1][i].v + u[j+1][i].v)*sy;
470*c4762a1bSJed Brown       f[j][i].u = udot[j][i].u - ( appctx->D1*(uxx + uyy) - uc*vc*vc + appctx->gamma*(1.0 - uc) );
471*c4762a1bSJed Brown       f[j][i].v = udot[j][i].v - ( appctx->D2*(vxx + vyy) + uc*vc*vc - (appctx->gamma + appctx->kappa)*vc );
472*c4762a1bSJed Brown     }
473*c4762a1bSJed Brown   }
474*c4762a1bSJed Brown   ierr = PetscLogFlops(16*xm*ym);CHKERRQ(ierr);
475*c4762a1bSJed Brown 
476*c4762a1bSJed Brown   /*
477*c4762a1bSJed Brown      Restore vectors
478*c4762a1bSJed Brown   */
479*c4762a1bSJed Brown   ierr = DMDAVecRestoreArrayRead(da,localU,&u);CHKERRQ(ierr);
480*c4762a1bSJed Brown   ierr = DMDAVecRestoreArray(da,F,&f);CHKERRQ(ierr);
481*c4762a1bSJed Brown   ierr = DMDAVecRestoreArrayRead(da,Udot,&udot);CHKERRQ(ierr);
482*c4762a1bSJed Brown   ierr = DMRestoreLocalVector(da,&localU);CHKERRQ(ierr);
483*c4762a1bSJed Brown   PetscFunctionReturn(0);
484*c4762a1bSJed Brown }
485*c4762a1bSJed Brown 
486*c4762a1bSJed Brown PetscErrorCode IJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat A,Mat BB,void *ctx)
487*c4762a1bSJed Brown {
488*c4762a1bSJed Brown   AppCtx         *appctx = (AppCtx*)ctx;     /* user-defined application context */
489*c4762a1bSJed Brown   DM             da;
490*c4762a1bSJed Brown   PetscErrorCode ierr;
491*c4762a1bSJed Brown   PetscInt       i,j,Mx,My,xs,ys,xm,ym;
492*c4762a1bSJed Brown   PetscReal      hx,hy,sx,sy;
493*c4762a1bSJed Brown   PetscScalar    uc,vc;
494*c4762a1bSJed Brown   Field          **u;
495*c4762a1bSJed Brown   Vec            localU;
496*c4762a1bSJed Brown   MatStencil     stencil[6],rowstencil;
497*c4762a1bSJed Brown   PetscScalar    entries[6];
498*c4762a1bSJed Brown 
499*c4762a1bSJed Brown   PetscFunctionBegin;
500*c4762a1bSJed Brown   ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
501*c4762a1bSJed Brown   ierr = DMGetLocalVector(da,&localU);CHKERRQ(ierr);
502*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);
503*c4762a1bSJed Brown 
504*c4762a1bSJed Brown   hx = 2.50/(PetscReal)Mx; sx = 1.0/(hx*hx);
505*c4762a1bSJed Brown   hy = 2.50/(PetscReal)My; sy = 1.0/(hy*hy);
506*c4762a1bSJed Brown 
507*c4762a1bSJed Brown   /*
508*c4762a1bSJed Brown      Scatter ghost points to local vector,using the 2-step process
509*c4762a1bSJed Brown         DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
510*c4762a1bSJed Brown      By placing code between these two statements, computations can be
511*c4762a1bSJed Brown      done while messages are in transition.
512*c4762a1bSJed Brown   */
513*c4762a1bSJed Brown   ierr = DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
514*c4762a1bSJed Brown   ierr = DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);CHKERRQ(ierr);
515*c4762a1bSJed Brown 
516*c4762a1bSJed Brown   /*
517*c4762a1bSJed Brown      Get pointers to vector data
518*c4762a1bSJed Brown   */
519*c4762a1bSJed Brown   ierr = DMDAVecGetArrayRead(da,localU,&u);CHKERRQ(ierr);
520*c4762a1bSJed Brown 
521*c4762a1bSJed Brown   /*
522*c4762a1bSJed Brown      Get local grid boundaries
523*c4762a1bSJed Brown   */
524*c4762a1bSJed Brown   ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
525*c4762a1bSJed Brown 
526*c4762a1bSJed Brown   stencil[0].k = 0;
527*c4762a1bSJed Brown   stencil[1].k = 0;
528*c4762a1bSJed Brown   stencil[2].k = 0;
529*c4762a1bSJed Brown   stencil[3].k = 0;
530*c4762a1bSJed Brown   stencil[4].k = 0;
531*c4762a1bSJed Brown   stencil[5].k = 0;
532*c4762a1bSJed Brown   rowstencil.k = 0;
533*c4762a1bSJed Brown   /*
534*c4762a1bSJed Brown      Compute function over the locally owned part of the grid
535*c4762a1bSJed Brown   */
536*c4762a1bSJed Brown   for (j=ys; j<ys+ym; j++) {
537*c4762a1bSJed Brown 
538*c4762a1bSJed Brown     stencil[0].j = j-1;
539*c4762a1bSJed Brown     stencil[1].j = j+1;
540*c4762a1bSJed Brown     stencil[2].j = j;
541*c4762a1bSJed Brown     stencil[3].j = j;
542*c4762a1bSJed Brown     stencil[4].j = j;
543*c4762a1bSJed Brown     stencil[5].j = j;
544*c4762a1bSJed Brown     rowstencil.k = 0; rowstencil.j = j;
545*c4762a1bSJed Brown     for (i=xs; i<xs+xm; i++) {
546*c4762a1bSJed Brown       uc = u[j][i].u;
547*c4762a1bSJed Brown       vc = u[j][i].v;
548*c4762a1bSJed Brown 
549*c4762a1bSJed Brown       /*      uxx       = (-2.0*uc + u[j][i-1].u + u[j][i+1].u)*sx;
550*c4762a1bSJed Brown       uyy       = (-2.0*uc + u[j-1][i].u + u[j+1][i].u)*sy;
551*c4762a1bSJed Brown 
552*c4762a1bSJed Brown       vxx       = (-2.0*vc + u[j][i-1].v + u[j][i+1].v)*sx;
553*c4762a1bSJed Brown       vyy       = (-2.0*vc + u[j-1][i].v + u[j+1][i].v)*sy;
554*c4762a1bSJed Brown        f[j][i].u = appctx->D1*(uxx + uyy) - uc*vc*vc + appctx->gamma*(1.0 - uc);*/
555*c4762a1bSJed Brown 
556*c4762a1bSJed Brown       stencil[0].i = i; stencil[0].c = 0; entries[0] = -appctx->D1*sy;
557*c4762a1bSJed Brown       stencil[1].i = i; stencil[1].c = 0; entries[1] = -appctx->D1*sy;
558*c4762a1bSJed Brown       stencil[2].i = i-1; stencil[2].c = 0; entries[2] = -appctx->D1*sx;
559*c4762a1bSJed Brown       stencil[3].i = i+1; stencil[3].c = 0; entries[3] = -appctx->D1*sx;
560*c4762a1bSJed Brown       stencil[4].i = i; stencil[4].c = 0; entries[4] = 2.0*appctx->D1*(sx + sy) + vc*vc + appctx->gamma + a;
561*c4762a1bSJed Brown       stencil[5].i = i; stencil[5].c = 1; entries[5] = 2.0*uc*vc;
562*c4762a1bSJed Brown       rowstencil.i = i; rowstencil.c = 0;
563*c4762a1bSJed Brown 
564*c4762a1bSJed Brown       ierr = MatSetValuesStencil(A,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr);
565*c4762a1bSJed Brown       if (appctx->aijpc) {
566*c4762a1bSJed Brown         ierr = MatSetValuesStencil(BB,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr);
567*c4762a1bSJed Brown       }
568*c4762a1bSJed Brown       stencil[0].c = 1; entries[0] = -appctx->D2*sy;
569*c4762a1bSJed Brown       stencil[1].c = 1; entries[1] = -appctx->D2*sy;
570*c4762a1bSJed Brown       stencil[2].c = 1; entries[2] = -appctx->D2*sx;
571*c4762a1bSJed Brown       stencil[3].c = 1; entries[3] = -appctx->D2*sx;
572*c4762a1bSJed Brown       stencil[4].c = 1; entries[4] = 2.0*appctx->D2*(sx + sy) - 2.0*uc*vc + appctx->gamma + appctx->kappa + a;
573*c4762a1bSJed Brown       stencil[5].c = 0; entries[5] = -vc*vc;
574*c4762a1bSJed Brown       rowstencil.c = 1;
575*c4762a1bSJed Brown 
576*c4762a1bSJed Brown       ierr = MatSetValuesStencil(A,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr);
577*c4762a1bSJed Brown       if (appctx->aijpc) {
578*c4762a1bSJed Brown         ierr = MatSetValuesStencil(BB,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr);
579*c4762a1bSJed Brown       }
580*c4762a1bSJed Brown       /* f[j][i].v = appctx->D2*(vxx + vyy) + uc*vc*vc - (appctx->gamma + appctx->kappa)*vc; */
581*c4762a1bSJed Brown     }
582*c4762a1bSJed Brown   }
583*c4762a1bSJed Brown 
584*c4762a1bSJed Brown   /*
585*c4762a1bSJed Brown      Restore vectors
586*c4762a1bSJed Brown   */
587*c4762a1bSJed Brown   ierr = PetscLogFlops(19*xm*ym);CHKERRQ(ierr);
588*c4762a1bSJed Brown   ierr = DMDAVecRestoreArrayRead(da,localU,&u);CHKERRQ(ierr);
589*c4762a1bSJed Brown   ierr = DMRestoreLocalVector(da,&localU);CHKERRQ(ierr);
590*c4762a1bSJed Brown   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
591*c4762a1bSJed Brown   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
592*c4762a1bSJed Brown   ierr = MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
593*c4762a1bSJed Brown   if (appctx->aijpc) {
594*c4762a1bSJed Brown     ierr = MatAssemblyBegin(BB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
595*c4762a1bSJed Brown     ierr = MatAssemblyEnd(BB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
596*c4762a1bSJed Brown     ierr = MatSetOption(BB,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
597*c4762a1bSJed Brown   }
598*c4762a1bSJed Brown   PetscFunctionReturn(0);
599*c4762a1bSJed Brown }
600*c4762a1bSJed Brown 
601*c4762a1bSJed Brown 
602*c4762a1bSJed Brown /*TEST
603*c4762a1bSJed Brown 
604*c4762a1bSJed Brown    build:
605*c4762a1bSJed Brown       requires: !complex !single
606*c4762a1bSJed Brown 
607*c4762a1bSJed Brown    test:
608*c4762a1bSJed Brown       args: -ts_max_steps 10 -ts_monitor -ts_adjoint_monitor -da_grid_x 20 -da_grid_y 20
609*c4762a1bSJed Brown       output_file: output/ex5adj_1.out
610*c4762a1bSJed Brown 
611*c4762a1bSJed Brown    test:
612*c4762a1bSJed Brown       suffix: 2
613*c4762a1bSJed Brown       nsize: 2
614*c4762a1bSJed Brown       args: -ts_max_steps 10 -ts_dt 10 -ts_monitor -ts_adjoint_monitor -ksp_monitor_short -da_grid_x 20 -da_grid_y 20 -ts_trajectory_dirname Test-dir -ts_trajectory_file_template test-%06D.cp
615*c4762a1bSJed Brown 
616*c4762a1bSJed Brown    test:
617*c4762a1bSJed Brown       suffix: 3
618*c4762a1bSJed Brown       nsize: 2
619*c4762a1bSJed Brown       args: -ts_max_steps 10 -ts_dt 10 -ts_adjoint_monitor_draw_sensi
620*c4762a1bSJed Brown 
621*c4762a1bSJed Brown    test:
622*c4762a1bSJed Brown       suffix: 4
623*c4762a1bSJed Brown       nsize: 2
624*c4762a1bSJed Brown       args: -ts_max_steps 10 -ts_dt 10 -ts_monitor -ts_adjoint_monitor -ksp_monitor_short -da_grid_x 20 -da_grid_y 20 -snes_fd_color
625*c4762a1bSJed Brown       output_file: output/ex5adj_2.out
626*c4762a1bSJed Brown 
627*c4762a1bSJed Brown    test:
628*c4762a1bSJed Brown       suffix: 5
629*c4762a1bSJed Brown       nsize: 2
630*c4762a1bSJed Brown       args: -ts_max_steps 10 -implicitform 0 -ts_type rk -ts_rk_type 4 -ts_monitor -ts_adjoint_monitor -da_grid_x 20 -da_grid_y 20 -snes_fd_color
631*c4762a1bSJed Brown       output_file: output/ex5adj_1.out
632*c4762a1bSJed Brown 
633*c4762a1bSJed Brown    test:
634*c4762a1bSJed Brown       suffix: knl
635*c4762a1bSJed Brown       args: -ts_max_steps 10 -ts_monitor -ts_adjoint_monitor -ts_trajectory_type memory -ts_trajectory_solution_only 0 -malloc_hbw -ts_trajectory_use_dram 1
636*c4762a1bSJed Brown       output_file: output/ex5adj_3.out
637*c4762a1bSJed Brown       requires: knl
638*c4762a1bSJed Brown 
639*c4762a1bSJed Brown    test:
640*c4762a1bSJed Brown       suffix: sell
641*c4762a1bSJed Brown       nsize: 4
642*c4762a1bSJed Brown       args: -forwardonly -ts_max_steps 10 -ts_monitor -snes_monitor_short -dm_mat_type sell -pc_type none
643*c4762a1bSJed Brown       output_file: output/ex5adj_sell_1.out
644*c4762a1bSJed Brown 
645*c4762a1bSJed Brown    test:
646*c4762a1bSJed Brown       suffix: aijsell
647*c4762a1bSJed Brown       nsize: 4
648*c4762a1bSJed Brown       args: -forwardonly -ts_max_steps 10 -ts_monitor -snes_monitor_short -dm_mat_type aijsell -pc_type none
649*c4762a1bSJed Brown       output_file: output/ex5adj_sell_1.out
650*c4762a1bSJed Brown 
651*c4762a1bSJed Brown    test:
652*c4762a1bSJed Brown       suffix: sell2
653*c4762a1bSJed Brown       nsize: 4
654*c4762a1bSJed Brown       args: -forwardonly -ts_max_steps 10 -ts_monitor -snes_monitor_short -dm_mat_type sell -pc_type mg -pc_mg_levels 2 -mg_coarse_pc_type sor
655*c4762a1bSJed Brown       output_file: output/ex5adj_sell_2.out
656*c4762a1bSJed Brown 
657*c4762a1bSJed Brown    test:
658*c4762a1bSJed Brown       suffix: aijsell2
659*c4762a1bSJed Brown       nsize: 4
660*c4762a1bSJed Brown       args: -forwardonly -ts_max_steps 10 -ts_monitor -snes_monitor_short -dm_mat_type aijsell -pc_type mg -pc_mg_levels 2 -mg_coarse_pc_type sor
661*c4762a1bSJed Brown       output_file: output/ex5adj_sell_2.out
662*c4762a1bSJed Brown 
663*c4762a1bSJed Brown    test:
664*c4762a1bSJed Brown       suffix: sell3
665*c4762a1bSJed Brown       nsize: 4
666*c4762a1bSJed Brown       args: -forwardonly -ts_max_steps 10 -ts_monitor -snes_monitor_short -dm_mat_type sell -pc_type mg -pc_mg_levels 2 -mg_coarse_pc_type bjacobi -mg_levels_pc_type bjacobi
667*c4762a1bSJed Brown       output_file: output/ex5adj_sell_3.out
668*c4762a1bSJed Brown 
669*c4762a1bSJed Brown    test:
670*c4762a1bSJed Brown       suffix: sell4
671*c4762a1bSJed Brown       nsize: 4
672*c4762a1bSJed Brown       args: -forwardonly -implicitform -ts_max_steps 10 -ts_monitor -snes_monitor_short -dm_mat_type sell -pc_type mg -pc_mg_levels 2 -mg_coarse_pc_type bjacobi -mg_levels_pc_type bjacobi
673*c4762a1bSJed Brown       output_file: output/ex5adj_sell_4.out
674*c4762a1bSJed Brown 
675*c4762a1bSJed Brown    test:
676*c4762a1bSJed Brown       suffix: sell5
677*c4762a1bSJed Brown       nsize: 4
678*c4762a1bSJed Brown       args: -forwardonly -ts_max_steps 10 -ts_monitor -snes_monitor_short -dm_mat_type sell -aijpc
679*c4762a1bSJed Brown       output_file: output/ex5adj_sell_5.out
680*c4762a1bSJed Brown 
681*c4762a1bSJed Brown    test:
682*c4762a1bSJed Brown       suffix: aijsell5
683*c4762a1bSJed Brown       nsize: 4
684*c4762a1bSJed Brown       args: -forwardonly -ts_max_steps 10 -ts_monitor -snes_monitor_short -dm_mat_type aijsell
685*c4762a1bSJed Brown       output_file: output/ex5adj_sell_5.out
686*c4762a1bSJed Brown 
687*c4762a1bSJed Brown    test:
688*c4762a1bSJed Brown       suffix: sell6
689*c4762a1bSJed Brown       args: -ts_max_steps 10 -ts_monitor -ts_adjoint_monitor -ts_trajectory_type memory -ts_trajectory_solution_only 0 -dm_mat_type sell -pc_type jacobi
690*c4762a1bSJed Brown       output_file: output/ex5adj_sell_6.out
691*c4762a1bSJed Brown 
692*c4762a1bSJed Brown TEST*/
693