xref: /petsc/src/snes/tests/ex69.c (revision dd4005766979d6c32c7873f45a6074c17defa719)
1c4762a1bSJed Brown 
2c4762a1bSJed Brown static char help[] = "Tests recovery from domain errors in MatMult() and PCApply()\n\n";
3c4762a1bSJed Brown 
4c4762a1bSJed Brown /*
5c4762a1bSJed Brown       See src/ksp/ksp/tutorials/ex19.c from which this was copied
6c4762a1bSJed Brown */
7c4762a1bSJed Brown 
8c4762a1bSJed Brown #include <petscsnes.h>
9c4762a1bSJed Brown #include <petscdm.h>
10c4762a1bSJed Brown #include <petscdmda.h>
11c4762a1bSJed Brown 
12c4762a1bSJed Brown /*
13c4762a1bSJed Brown    User-defined routines and data structures
14c4762a1bSJed Brown */
15c4762a1bSJed Brown typedef struct {
16c4762a1bSJed Brown   PetscScalar u,v,omega,temp;
17c4762a1bSJed Brown } Field;
18c4762a1bSJed Brown 
19c4762a1bSJed Brown PetscErrorCode FormFunctionLocal(DMDALocalInfo*,Field**,Field**,void*);
20c4762a1bSJed Brown 
21c4762a1bSJed Brown typedef struct {
22c4762a1bSJed Brown   PetscReal   lidvelocity,prandtl,grashof;  /* physical parameters */
23c4762a1bSJed Brown   PetscBool   draw_contours;                /* flag - 1 indicates drawing contours */
24c4762a1bSJed Brown   PetscBool   errorindomain;
25c4762a1bSJed Brown   PetscBool   errorindomainmf;
26c4762a1bSJed Brown   SNES        snes;
27c4762a1bSJed Brown } AppCtx;
28c4762a1bSJed Brown 
29c4762a1bSJed Brown typedef struct {
30c4762a1bSJed Brown   Mat Jmf;
31c4762a1bSJed Brown } MatShellCtx;
32c4762a1bSJed Brown 
33c4762a1bSJed Brown extern PetscErrorCode FormInitialGuess(AppCtx*,DM,Vec);
34c4762a1bSJed Brown extern PetscErrorCode MatMult_MyShell(Mat,Vec,Vec);
35c4762a1bSJed Brown extern PetscErrorCode MatAssemblyEnd_MyShell(Mat,MatAssemblyType);
36c4762a1bSJed Brown extern PetscErrorCode PCApply_MyShell(PC,Vec,Vec);
37c4762a1bSJed Brown extern PetscErrorCode SNESComputeJacobian_MyShell(SNES,Vec,Mat,Mat,void*);
38c4762a1bSJed Brown 
39c4762a1bSJed Brown int main(int argc,char **argv)
40c4762a1bSJed Brown {
41c4762a1bSJed Brown   AppCtx         user;                /* user-defined work context */
42c4762a1bSJed Brown   PetscInt       mx,my;
43c4762a1bSJed Brown   PetscErrorCode ierr;
44c4762a1bSJed Brown   MPI_Comm       comm;
45c4762a1bSJed Brown   DM             da;
46c4762a1bSJed Brown   Vec            x;
47c4762a1bSJed Brown   Mat            J = NULL,Jmf = NULL;
48c4762a1bSJed Brown   MatShellCtx    matshellctx;
49c4762a1bSJed Brown   PetscInt       mlocal,nlocal;
50c4762a1bSJed Brown   PC             pc;
51c4762a1bSJed Brown   KSP            ksp;
52c4762a1bSJed Brown   PetscBool      errorinmatmult = PETSC_FALSE,errorinpcapply = PETSC_FALSE,errorinpcsetup = PETSC_FALSE;
53c4762a1bSJed Brown 
54c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
55c4762a1bSJed Brown   ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_matmult",&errorinmatmult,NULL);CHKERRQ(ierr);
56c4762a1bSJed Brown   ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_pcapply",&errorinpcapply,NULL);CHKERRQ(ierr);
57c4762a1bSJed Brown   ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_pcsetup",&errorinpcsetup,NULL);CHKERRQ(ierr);
58c4762a1bSJed Brown   user.errorindomain = PETSC_FALSE;
59c4762a1bSJed Brown   ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_domain",&user.errorindomain,NULL);CHKERRQ(ierr);
60c4762a1bSJed Brown   user.errorindomainmf = PETSC_FALSE;
61c4762a1bSJed Brown   ierr = PetscOptionsGetBool(NULL,NULL,"-error_in_domainmf",&user.errorindomainmf,NULL);CHKERRQ(ierr);
62c4762a1bSJed Brown 
63c4762a1bSJed Brown   comm = PETSC_COMM_WORLD;
64c4762a1bSJed Brown   ierr = SNESCreate(comm,&user.snes);CHKERRQ(ierr);
65c4762a1bSJed Brown 
66c4762a1bSJed Brown   /*
67c4762a1bSJed Brown       Create distributed array object to manage parallel grid and vectors
68c4762a1bSJed Brown       for principal unknowns (x) and governing residuals (f)
69c4762a1bSJed Brown   */
70c4762a1bSJed Brown   ierr = DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_STAR,4,4,PETSC_DECIDE,PETSC_DECIDE,4,1,0,0,&da);CHKERRQ(ierr);
71c4762a1bSJed Brown   ierr = DMSetFromOptions(da);CHKERRQ(ierr);
72c4762a1bSJed Brown   ierr = DMSetUp(da);CHKERRQ(ierr);
73c4762a1bSJed Brown   ierr = SNESSetDM(user.snes,da);CHKERRQ(ierr);
74c4762a1bSJed Brown 
75c4762a1bSJed Brown   ierr = DMDAGetInfo(da,0,&mx,&my,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,
76c4762a1bSJed Brown                      PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr);
77c4762a1bSJed Brown   /*
78c4762a1bSJed Brown      Problem parameters (velocity of lid, prandtl, and grashof numbers)
79c4762a1bSJed Brown   */
80c4762a1bSJed Brown   user.lidvelocity = 1.0/(mx*my);
81c4762a1bSJed Brown   user.prandtl     = 1.0;
82c4762a1bSJed Brown   user.grashof     = 1.0;
83c4762a1bSJed Brown 
84c4762a1bSJed Brown   ierr = PetscOptionsGetReal(NULL,NULL,"-lidvelocity",&user.lidvelocity,NULL);CHKERRQ(ierr);
85c4762a1bSJed Brown   ierr = PetscOptionsGetReal(NULL,NULL,"-prandtl",&user.prandtl,NULL);CHKERRQ(ierr);
86c4762a1bSJed Brown   ierr = PetscOptionsGetReal(NULL,NULL,"-grashof",&user.grashof,NULL);CHKERRQ(ierr);
87c4762a1bSJed Brown   ierr = PetscOptionsHasName(NULL,NULL,"-contours",&user.draw_contours);CHKERRQ(ierr);
88c4762a1bSJed Brown 
89c4762a1bSJed Brown   ierr = DMDASetFieldName(da,0,"x_velocity");CHKERRQ(ierr);
90c4762a1bSJed Brown   ierr = DMDASetFieldName(da,1,"y_velocity");CHKERRQ(ierr);
91c4762a1bSJed Brown   ierr = DMDASetFieldName(da,2,"Omega");CHKERRQ(ierr);
92c4762a1bSJed Brown   ierr = DMDASetFieldName(da,3,"temperature");CHKERRQ(ierr);
93c4762a1bSJed Brown 
94c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
95c4762a1bSJed Brown      Create user context, set problem data, create vector data structures.
96c4762a1bSJed Brown      Also, compute the initial guess.
97c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
98c4762a1bSJed Brown 
99c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
100c4762a1bSJed Brown      Create nonlinear solver context
101c4762a1bSJed Brown 
102c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
103c4762a1bSJed Brown   ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr);
104c4762a1bSJed Brown   ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES,(PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal,&user);CHKERRQ(ierr);
105c4762a1bSJed Brown 
106c4762a1bSJed Brown   if (errorinmatmult) {
107c4762a1bSJed Brown     ierr = MatCreateSNESMF(user.snes,&Jmf);CHKERRQ(ierr);
108c4762a1bSJed Brown     ierr = MatSetFromOptions(Jmf);CHKERRQ(ierr);
109c4762a1bSJed Brown     ierr = MatGetLocalSize(Jmf,&mlocal,&nlocal);CHKERRQ(ierr);
110c4762a1bSJed Brown     matshellctx.Jmf = Jmf;
111c4762a1bSJed Brown     ierr = MatCreateShell(PetscObjectComm((PetscObject)Jmf),mlocal,nlocal,PETSC_DECIDE,PETSC_DECIDE,&matshellctx,&J);CHKERRQ(ierr);
112c4762a1bSJed Brown     ierr = MatShellSetOperation(J,MATOP_MULT,(void (*)(void))MatMult_MyShell);CHKERRQ(ierr);
113c4762a1bSJed Brown     ierr = MatShellSetOperation(J,MATOP_ASSEMBLY_END,(void (*)(void))MatAssemblyEnd_MyShell);CHKERRQ(ierr);
114c4762a1bSJed Brown     ierr = SNESSetJacobian(user.snes,J,J,MatMFFDComputeJacobian,NULL);CHKERRQ(ierr);
115c4762a1bSJed Brown   }
116c4762a1bSJed Brown 
117c4762a1bSJed Brown   ierr = SNESSetFromOptions(user.snes);CHKERRQ(ierr);
118c4762a1bSJed Brown   ierr = PetscPrintf(comm,"lid velocity = %g, prandtl # = %g, grashof # = %g\n",(double)user.lidvelocity,(double)user.prandtl,(double)user.grashof);CHKERRQ(ierr);
119c4762a1bSJed Brown 
120c4762a1bSJed Brown   if (errorinpcapply) {
121c4762a1bSJed Brown     ierr = SNESGetKSP(user.snes,&ksp);CHKERRQ(ierr);
122c4762a1bSJed Brown     ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
123c4762a1bSJed Brown     ierr = PCSetType(pc,PCSHELL);CHKERRQ(ierr);
124c4762a1bSJed Brown     ierr = PCShellSetApply(pc,PCApply_MyShell);CHKERRQ(ierr);
125c4762a1bSJed Brown   }
126c4762a1bSJed Brown 
127c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
128c4762a1bSJed Brown      Solve the nonlinear system
129c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
130c4762a1bSJed Brown   ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr);
131c4762a1bSJed Brown   ierr = FormInitialGuess(&user,da,x);CHKERRQ(ierr);
132c4762a1bSJed Brown 
133c4762a1bSJed Brown   if (errorinpcsetup) {
134c4762a1bSJed Brown     ierr = SNESSetUp(user.snes);CHKERRQ(ierr);
135c4762a1bSJed Brown     ierr = SNESSetJacobian(user.snes,NULL,NULL,SNESComputeJacobian_MyShell,NULL);CHKERRQ(ierr);
136c4762a1bSJed Brown   }
137c4762a1bSJed Brown   ierr = SNESSolve(user.snes,NULL,x);CHKERRQ(ierr);
138c4762a1bSJed Brown 
139c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
140c4762a1bSJed Brown      Free work space.  All PETSc objects should be destroyed when they
141c4762a1bSJed Brown      are no longer needed.
142c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
143c4762a1bSJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr);
144c4762a1bSJed Brown   ierr = MatDestroy(&Jmf);CHKERRQ(ierr);
145c4762a1bSJed Brown   ierr = VecDestroy(&x);CHKERRQ(ierr);
146c4762a1bSJed Brown   ierr = DMDestroy(&da);CHKERRQ(ierr);
147c4762a1bSJed Brown   ierr = SNESDestroy(&user.snes);CHKERRQ(ierr);
148c4762a1bSJed Brown   ierr = PetscFinalize();
149c4762a1bSJed Brown   return ierr;
150c4762a1bSJed Brown }
151c4762a1bSJed Brown 
152c4762a1bSJed Brown /* ------------------------------------------------------------------- */
153c4762a1bSJed Brown 
154c4762a1bSJed Brown /*
155c4762a1bSJed Brown    FormInitialGuess - Forms initial approximation.
156c4762a1bSJed Brown 
157c4762a1bSJed Brown    Input Parameters:
158c4762a1bSJed Brown    user - user-defined application context
159c4762a1bSJed Brown    X - vector
160c4762a1bSJed Brown 
161c4762a1bSJed Brown    Output Parameter:
162c4762a1bSJed Brown    X - vector
163c4762a1bSJed Brown */
164c4762a1bSJed Brown PetscErrorCode FormInitialGuess(AppCtx *user,DM da,Vec X)
165c4762a1bSJed Brown {
166c4762a1bSJed Brown   PetscInt       i,j,mx,xs,ys,xm,ym;
167c4762a1bSJed Brown   PetscErrorCode ierr;
168c4762a1bSJed Brown   PetscReal      grashof,dx;
169c4762a1bSJed Brown   Field          **x;
170c4762a1bSJed Brown 
171c4762a1bSJed Brown   PetscFunctionBeginUser;
172c4762a1bSJed Brown   grashof = user->grashof;
173c4762a1bSJed Brown 
174c4762a1bSJed Brown   ierr = DMDAGetInfo(da,0,&mx,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
175c4762a1bSJed Brown   dx   = 1.0/(mx-1);
176c4762a1bSJed Brown 
177c4762a1bSJed Brown   /*
178c4762a1bSJed Brown      Get local grid boundaries (for 2-dimensional DMDA):
179c4762a1bSJed Brown        xs, ys   - starting grid indices (no ghost points)
180c4762a1bSJed Brown        xm, ym   - widths of local grid (no ghost points)
181c4762a1bSJed Brown   */
182c4762a1bSJed Brown   ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
183c4762a1bSJed Brown 
184c4762a1bSJed Brown   /*
185c4762a1bSJed Brown      Get a pointer to vector data.
186c4762a1bSJed Brown        - For default PETSc vectors, VecGetArray() returns a pointer to
187c4762a1bSJed Brown          the data array.  Otherwise, the routine is implementation dependent.
188c4762a1bSJed Brown        - You MUST call VecRestoreArray() when you no longer need access to
189c4762a1bSJed Brown          the array.
190c4762a1bSJed Brown   */
191c4762a1bSJed Brown   ierr = DMDAVecGetArray(da,X,&x);CHKERRQ(ierr);
192c4762a1bSJed Brown 
193c4762a1bSJed Brown   /*
194c4762a1bSJed Brown      Compute initial guess over the locally owned part of the grid
195c4762a1bSJed Brown      Initial condition is motionless fluid and equilibrium temperature
196c4762a1bSJed Brown   */
197c4762a1bSJed Brown   for (j=ys; j<ys+ym; j++) {
198c4762a1bSJed Brown     for (i=xs; i<xs+xm; i++) {
199c4762a1bSJed Brown       x[j][i].u     = 0.0;
200c4762a1bSJed Brown       x[j][i].v     = 0.0;
201c4762a1bSJed Brown       x[j][i].omega = 0.0;
202c4762a1bSJed Brown       x[j][i].temp  = (grashof>0)*i*dx;
203c4762a1bSJed Brown     }
204c4762a1bSJed Brown   }
205c4762a1bSJed Brown 
206c4762a1bSJed Brown   /*
207c4762a1bSJed Brown      Restore vector
208c4762a1bSJed Brown   */
209c4762a1bSJed Brown   ierr = DMDAVecRestoreArray(da,X,&x);CHKERRQ(ierr);
210c4762a1bSJed Brown   PetscFunctionReturn(0);
211c4762a1bSJed Brown }
212c4762a1bSJed Brown 
213c4762a1bSJed Brown PetscErrorCode FormFunctionLocal(DMDALocalInfo *info,Field **x,Field **f,void *ptr)
214c4762a1bSJed Brown {
215c4762a1bSJed Brown   AppCtx          *user = (AppCtx*)ptr;
216c4762a1bSJed Brown   PetscErrorCode  ierr;
217c4762a1bSJed Brown   PetscInt        xints,xinte,yints,yinte,i,j;
218c4762a1bSJed Brown   PetscReal       hx,hy,dhx,dhy,hxdhy,hydhx;
219c4762a1bSJed Brown   PetscReal       grashof,prandtl,lid;
220c4762a1bSJed Brown   PetscScalar     u,uxx,uyy,vx,vy,avx,avy,vxp,vxm,vyp,vym;
221c4762a1bSJed Brown   static PetscInt fail = 0;
222c4762a1bSJed Brown 
223c4762a1bSJed Brown   PetscFunctionBeginUser;
224c4762a1bSJed Brown   if ((fail++ > 7 && user->errorindomainmf) || (fail++ > 36 && user->errorindomain)) {
225c4762a1bSJed Brown     PetscMPIInt rank;
226ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)user->snes),&rank);CHKERRMPI(ierr);
227*dd400576SPatrick Sanan     if (rank == 0) {
228c4762a1bSJed Brown       ierr = SNESSetFunctionDomainError(user->snes);CHKERRQ(ierr);
229c4762a1bSJed Brown     }
230c4762a1bSJed Brown   }
231c4762a1bSJed Brown   grashof = user->grashof;
232c4762a1bSJed Brown   prandtl = user->prandtl;
233c4762a1bSJed Brown   lid     = user->lidvelocity;
234c4762a1bSJed Brown 
235c4762a1bSJed Brown   /*
236c4762a1bSJed Brown      Define mesh intervals ratios for uniform grid.
237c4762a1bSJed Brown 
238c4762a1bSJed Brown      Note: FD formulae below are normalized by multiplying through by
239c4762a1bSJed Brown      local volume element (i.e. hx*hy) to obtain coefficients O(1) in two dimensions.
240c4762a1bSJed Brown 
241c4762a1bSJed Brown   */
242c4762a1bSJed Brown   dhx   = (PetscReal)(info->mx-1);  dhy = (PetscReal)(info->my-1);
243c4762a1bSJed Brown   hx    = 1.0/dhx;                   hy = 1.0/dhy;
244c4762a1bSJed Brown   hxdhy = hx*dhy;                 hydhx = hy*dhx;
245c4762a1bSJed Brown 
246c4762a1bSJed Brown   xints = info->xs; xinte = info->xs+info->xm; yints = info->ys; yinte = info->ys+info->ym;
247c4762a1bSJed Brown 
248c4762a1bSJed Brown   /* Test whether we are on the bottom edge of the global array */
249c4762a1bSJed Brown   if (yints == 0) {
250c4762a1bSJed Brown     j     = 0;
251c4762a1bSJed Brown     yints = yints + 1;
252c4762a1bSJed Brown     /* bottom edge */
253c4762a1bSJed Brown     for (i=info->xs; i<info->xs+info->xm; i++) {
254c4762a1bSJed Brown       f[j][i].u     = x[j][i].u;
255c4762a1bSJed Brown       f[j][i].v     = x[j][i].v;
256c4762a1bSJed Brown       f[j][i].omega = x[j][i].omega + (x[j+1][i].u - x[j][i].u)*dhy;
257c4762a1bSJed Brown       f[j][i].temp  = x[j][i].temp-x[j+1][i].temp;
258c4762a1bSJed Brown     }
259c4762a1bSJed Brown   }
260c4762a1bSJed Brown 
261c4762a1bSJed Brown   /* Test whether we are on the top edge of the global array */
262c4762a1bSJed Brown   if (yinte == info->my) {
263c4762a1bSJed Brown     j     = info->my - 1;
264c4762a1bSJed Brown     yinte = yinte - 1;
265c4762a1bSJed Brown     /* top edge */
266c4762a1bSJed Brown     for (i=info->xs; i<info->xs+info->xm; i++) {
267c4762a1bSJed Brown       f[j][i].u     = x[j][i].u - lid;
268c4762a1bSJed Brown       f[j][i].v     = x[j][i].v;
269c4762a1bSJed Brown       f[j][i].omega = x[j][i].omega + (x[j][i].u - x[j-1][i].u)*dhy;
270c4762a1bSJed Brown       f[j][i].temp  = x[j][i].temp-x[j-1][i].temp;
271c4762a1bSJed Brown     }
272c4762a1bSJed Brown   }
273c4762a1bSJed Brown 
274c4762a1bSJed Brown   /* Test whether we are on the left edge of the global array */
275c4762a1bSJed Brown   if (xints == 0) {
276c4762a1bSJed Brown     i     = 0;
277c4762a1bSJed Brown     xints = xints + 1;
278c4762a1bSJed Brown     /* left edge */
279c4762a1bSJed Brown     for (j=info->ys; j<info->ys+info->ym; j++) {
280c4762a1bSJed Brown       f[j][i].u     = x[j][i].u;
281c4762a1bSJed Brown       f[j][i].v     = x[j][i].v;
282c4762a1bSJed Brown       f[j][i].omega = x[j][i].omega - (x[j][i+1].v - x[j][i].v)*dhx;
283c4762a1bSJed Brown       f[j][i].temp  = x[j][i].temp;
284c4762a1bSJed Brown     }
285c4762a1bSJed Brown   }
286c4762a1bSJed Brown 
287c4762a1bSJed Brown   /* Test whether we are on the right edge of the global array */
288c4762a1bSJed Brown   if (xinte == info->mx) {
289c4762a1bSJed Brown     i     = info->mx - 1;
290c4762a1bSJed Brown     xinte = xinte - 1;
291c4762a1bSJed Brown     /* right edge */
292c4762a1bSJed Brown     for (j=info->ys; j<info->ys+info->ym; j++) {
293c4762a1bSJed Brown       f[j][i].u     = x[j][i].u;
294c4762a1bSJed Brown       f[j][i].v     = x[j][i].v;
295c4762a1bSJed Brown       f[j][i].omega = x[j][i].omega - (x[j][i].v - x[j][i-1].v)*dhx;
296c4762a1bSJed Brown       f[j][i].temp  = x[j][i].temp - (PetscReal)(grashof>0);
297c4762a1bSJed Brown     }
298c4762a1bSJed Brown   }
299c4762a1bSJed Brown 
300c4762a1bSJed Brown   /* Compute over the interior points */
301c4762a1bSJed Brown   for (j=yints; j<yinte; j++) {
302c4762a1bSJed Brown     for (i=xints; i<xinte; i++) {
303c4762a1bSJed Brown 
304c4762a1bSJed Brown       /*
305c4762a1bSJed Brown        convective coefficients for upwinding
306c4762a1bSJed Brown       */
307c4762a1bSJed Brown       vx  = x[j][i].u; avx = PetscAbsScalar(vx);
308c4762a1bSJed Brown       vxp = .5*(vx+avx); vxm = .5*(vx-avx);
309c4762a1bSJed Brown       vy  = x[j][i].v; avy = PetscAbsScalar(vy);
310c4762a1bSJed Brown       vyp = .5*(vy+avy); vym = .5*(vy-avy);
311c4762a1bSJed Brown 
312c4762a1bSJed Brown       /* U velocity */
313c4762a1bSJed Brown       u         = x[j][i].u;
314c4762a1bSJed Brown       uxx       = (2.0*u - x[j][i-1].u - x[j][i+1].u)*hydhx;
315c4762a1bSJed Brown       uyy       = (2.0*u - x[j-1][i].u - x[j+1][i].u)*hxdhy;
316c4762a1bSJed Brown       f[j][i].u = uxx + uyy - .5*(x[j+1][i].omega-x[j-1][i].omega)*hx;
317c4762a1bSJed Brown 
318c4762a1bSJed Brown       /* V velocity */
319c4762a1bSJed Brown       u         = x[j][i].v;
320c4762a1bSJed Brown       uxx       = (2.0*u - x[j][i-1].v - x[j][i+1].v)*hydhx;
321c4762a1bSJed Brown       uyy       = (2.0*u - x[j-1][i].v - x[j+1][i].v)*hxdhy;
322c4762a1bSJed Brown       f[j][i].v = uxx + uyy + .5*(x[j][i+1].omega-x[j][i-1].omega)*hy;
323c4762a1bSJed Brown 
324c4762a1bSJed Brown       /* Omega */
325c4762a1bSJed Brown       u             = x[j][i].omega;
326c4762a1bSJed Brown       uxx           = (2.0*u - x[j][i-1].omega - x[j][i+1].omega)*hydhx;
327c4762a1bSJed Brown       uyy           = (2.0*u - x[j-1][i].omega - x[j+1][i].omega)*hxdhy;
328c4762a1bSJed Brown       f[j][i].omega = uxx + uyy + (vxp*(u - x[j][i-1].omega) + vxm*(x[j][i+1].omega - u))*hy +
329c4762a1bSJed Brown                       (vyp*(u - x[j-1][i].omega) + vym*(x[j+1][i].omega - u))*hx -
330c4762a1bSJed Brown                       .5*grashof*(x[j][i+1].temp - x[j][i-1].temp)*hy;
331c4762a1bSJed Brown 
332c4762a1bSJed Brown       /* Temperature */
333c4762a1bSJed Brown       u            = x[j][i].temp;
334c4762a1bSJed Brown       uxx          = (2.0*u - x[j][i-1].temp - x[j][i+1].temp)*hydhx;
335c4762a1bSJed Brown       uyy          = (2.0*u - x[j-1][i].temp - x[j+1][i].temp)*hxdhy;
336c4762a1bSJed Brown       f[j][i].temp =  uxx + uyy  + prandtl*((vxp*(u - x[j][i-1].temp) + vxm*(x[j][i+1].temp - u))*hy +
337c4762a1bSJed Brown                                             (vyp*(u - x[j-1][i].temp) + vym*(x[j+1][i].temp - u))*hx);
338c4762a1bSJed Brown     }
339c4762a1bSJed Brown   }
340c4762a1bSJed Brown 
341c4762a1bSJed Brown   /*
342c4762a1bSJed Brown      Flop count (multiply-adds are counted as 2 operations)
343c4762a1bSJed Brown   */
344c4762a1bSJed Brown   ierr = PetscLogFlops(84.0*info->ym*info->xm);CHKERRQ(ierr);
345c4762a1bSJed Brown   PetscFunctionReturn(0);
346c4762a1bSJed Brown }
347c4762a1bSJed Brown 
348c4762a1bSJed Brown PetscErrorCode MatMult_MyShell(Mat A,Vec x,Vec y)
349c4762a1bSJed Brown {
350c4762a1bSJed Brown   PetscErrorCode  ierr;
351c4762a1bSJed Brown   MatShellCtx     *matshellctx;
352c4762a1bSJed Brown   static PetscInt fail = 0;
353c4762a1bSJed Brown 
354c4762a1bSJed Brown   PetscFunctionBegin;
355c4762a1bSJed Brown   ierr = MatShellGetContext(A,&matshellctx);CHKERRQ(ierr);
356c4762a1bSJed Brown   ierr = MatMult(matshellctx->Jmf,x,y);CHKERRQ(ierr);
357c4762a1bSJed Brown   if (fail++ > 5) {
358c4762a1bSJed Brown     PetscMPIInt rank;
359ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRMPI(ierr);
360*dd400576SPatrick Sanan     if (rank == 0) {ierr = VecSetInf(y);CHKERRQ(ierr);}
361c4762a1bSJed Brown   }
362c4762a1bSJed Brown   PetscFunctionReturn(0);
363c4762a1bSJed Brown }
364c4762a1bSJed Brown 
365c4762a1bSJed Brown PetscErrorCode MatAssemblyEnd_MyShell(Mat A,MatAssemblyType tp)
366c4762a1bSJed Brown {
367c4762a1bSJed Brown   PetscErrorCode ierr;
368c4762a1bSJed Brown   MatShellCtx    *matshellctx;
369c4762a1bSJed Brown 
370c4762a1bSJed Brown   PetscFunctionBegin;
371c4762a1bSJed Brown   ierr = MatShellGetContext(A,&matshellctx);CHKERRQ(ierr);
372c4762a1bSJed Brown   ierr = MatAssemblyEnd(matshellctx->Jmf,tp);CHKERRQ(ierr);
373c4762a1bSJed Brown   PetscFunctionReturn(0);
374c4762a1bSJed Brown }
375c4762a1bSJed Brown 
376c4762a1bSJed Brown PetscErrorCode PCApply_MyShell(PC pc,Vec x,Vec y)
377c4762a1bSJed Brown {
378c4762a1bSJed Brown   PetscErrorCode ierr;
379c4762a1bSJed Brown   static PetscInt fail = 0;
380c4762a1bSJed Brown 
381c4762a1bSJed Brown   PetscFunctionBegin;
382c4762a1bSJed Brown   ierr = VecCopy(x,y);CHKERRQ(ierr);
383c4762a1bSJed Brown   if (fail++ > 3) {
384c4762a1bSJed Brown     PetscMPIInt rank;
385ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRMPI(ierr);
386*dd400576SPatrick Sanan     if (rank == 0) {ierr = VecSetInf(y);CHKERRQ(ierr);}
387c4762a1bSJed Brown   }
388c4762a1bSJed Brown   PetscFunctionReturn(0);
389c4762a1bSJed Brown }
390c4762a1bSJed Brown 
391c4762a1bSJed Brown PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES,Vec,Mat,Mat,void*);
392c4762a1bSJed Brown 
393c4762a1bSJed Brown PetscErrorCode SNESComputeJacobian_MyShell(SNES snes,Vec X,Mat A,Mat B,void *ctx)
394c4762a1bSJed Brown {
395c4762a1bSJed Brown   static PetscInt fail = 0;
396c4762a1bSJed Brown   PetscErrorCode  ierr;
397c4762a1bSJed Brown 
398c4762a1bSJed Brown   PetscFunctionBegin;
399c4762a1bSJed Brown   ierr = SNESComputeJacobian_DMDA(snes,X,A,B,ctx);CHKERRQ(ierr);
400c4762a1bSJed Brown   if (fail++ > 0) {
401c4762a1bSJed Brown     ierr = MatZeroEntries(A);CHKERRQ(ierr);
402c4762a1bSJed Brown   }
403c4762a1bSJed Brown   PetscFunctionReturn(0);
404c4762a1bSJed Brown }
405c4762a1bSJed Brown 
406c4762a1bSJed Brown /*TEST
407c4762a1bSJed Brown 
408c4762a1bSJed Brown    test:
409c4762a1bSJed Brown       args: -snes_converged_reason -ksp_converged_reason
410c4762a1bSJed Brown 
411c4762a1bSJed Brown    test:
412c4762a1bSJed Brown       suffix: 2
413c4762a1bSJed Brown       args: -snes_converged_reason -ksp_converged_reason -error_in_matmult
414c4762a1bSJed Brown 
415c4762a1bSJed Brown    test:
416c4762a1bSJed Brown       suffix: 3
417c4762a1bSJed Brown       args: -snes_converged_reason -ksp_converged_reason -error_in_pcapply
418c4762a1bSJed Brown 
419c4762a1bSJed Brown    test:
420c4762a1bSJed Brown       suffix: 4
421c4762a1bSJed Brown       args: -snes_converged_reason -ksp_converged_reason -error_in_pcsetup
422c4762a1bSJed Brown 
423c4762a1bSJed Brown    test:
424c4762a1bSJed Brown       suffix: 5
425c4762a1bSJed Brown       args: -snes_converged_reason -ksp_converged_reason -error_in_pcsetup -pc_type bjacobi
426c4762a1bSJed Brown 
427c4762a1bSJed Brown    test:
428c4762a1bSJed Brown       suffix: 5_fieldsplit
429c4762a1bSJed Brown       args: -snes_converged_reason -ksp_converged_reason -error_in_pcsetup -pc_type fieldsplit
430c4762a1bSJed Brown       output_file: output/ex69_5.out
431c4762a1bSJed Brown 
432c4762a1bSJed Brown    test:
433c4762a1bSJed Brown       suffix: 6
434c4762a1bSJed Brown       args: -snes_converged_reason -ksp_converged_reason -error_in_domainmf -snes_mf -pc_type none
435c4762a1bSJed Brown 
436c4762a1bSJed Brown    test:
437c4762a1bSJed Brown       suffix: 7
438c4762a1bSJed Brown       args: -snes_converged_reason -ksp_converged_reason -error_in_domain
439c4762a1bSJed Brown 
440c4762a1bSJed Brown    test:
441c4762a1bSJed Brown       suffix: 8
442c4762a1bSJed Brown       args: -snes_converged_reason -ksp_converged_reason -error_in_domain -snes_mf -pc_type none
443c4762a1bSJed Brown 
444c4762a1bSJed Brown TEST*/
445