xref: /petsc/src/snes/tutorials/ex19.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1*c4762a1bSJed Brown 
2*c4762a1bSJed Brown static char help[] = "Nonlinear driven cavity with multigrid in 2d.\n \
3*c4762a1bSJed Brown   \n\
4*c4762a1bSJed Brown The 2D driven cavity problem is solved in a velocity-vorticity formulation.\n\
5*c4762a1bSJed Brown The flow can be driven with the lid or with bouyancy or both:\n\
6*c4762a1bSJed Brown   -lidvelocity &ltlid&gt, where &ltlid&gt = dimensionless velocity of lid\n\
7*c4762a1bSJed Brown   -grashof &ltgr&gt, where &ltgr&gt = dimensionless temperature gradent\n\
8*c4762a1bSJed Brown   -prandtl &ltpr&gt, where &ltpr&gt = dimensionless thermal/momentum diffusity ratio\n\
9*c4762a1bSJed Brown  -contours : draw contour plots of solution\n\n";
10*c4762a1bSJed Brown /* in HTML, '&lt' = '<' and '&gt' = '>' */
11*c4762a1bSJed Brown 
12*c4762a1bSJed Brown /*
13*c4762a1bSJed Brown       See src/ksp/ksp/tutorials/ex45.c
14*c4762a1bSJed Brown */
15*c4762a1bSJed Brown 
16*c4762a1bSJed Brown /*T
17*c4762a1bSJed Brown    Concepts: SNES^solving a system of nonlinear equations (parallel multicomponent example);
18*c4762a1bSJed Brown    Concepts: DMDA^using distributed arrays;
19*c4762a1bSJed Brown    Concepts: multicomponent
20*c4762a1bSJed Brown    Processors: n
21*c4762a1bSJed Brown T*/
22*c4762a1bSJed Brown 
23*c4762a1bSJed Brown 
24*c4762a1bSJed Brown /*F-----------------------------------------------------------------------
25*c4762a1bSJed Brown 
26*c4762a1bSJed Brown     We thank David E. Keyes for contributing the driven cavity discretization within this example code.
27*c4762a1bSJed Brown 
28*c4762a1bSJed Brown     This problem is modeled by the partial differential equation system
29*c4762a1bSJed Brown 
30*c4762a1bSJed Brown \begin{eqnarray}
31*c4762a1bSJed Brown         - \triangle U - \nabla_y \Omega & = & 0  \\
32*c4762a1bSJed Brown         - \triangle V + \nabla_x\Omega & = & 0  \\
33*c4762a1bSJed Brown         - \triangle \Omega + \nabla \cdot ([U*\Omega,V*\Omega]) - GR* \nabla_x T & = & 0  \\
34*c4762a1bSJed Brown         - \triangle T + PR* \nabla \cdot ([U*T,V*T]) & = & 0
35*c4762a1bSJed Brown \end{eqnarray}
36*c4762a1bSJed Brown 
37*c4762a1bSJed Brown     in the unit square, which is uniformly discretized in each of x and y in this simple encoding.
38*c4762a1bSJed Brown 
39*c4762a1bSJed Brown     No-slip, rigid-wall Dirichlet conditions are used for $ [U,V]$.
40*c4762a1bSJed Brown     Dirichlet conditions are used for Omega, based on the definition of
41*c4762a1bSJed Brown     vorticity: $ \Omega = - \nabla_y U + \nabla_x V$, where along each
42*c4762a1bSJed Brown     constant coordinate boundary, the tangential derivative is zero.
43*c4762a1bSJed Brown     Dirichlet conditions are used for T on the left and right walls,
44*c4762a1bSJed Brown     and insulation homogeneous Neumann conditions are used for T on
45*c4762a1bSJed Brown     the top and bottom walls.
46*c4762a1bSJed Brown 
47*c4762a1bSJed Brown     A finite difference approximation with the usual 5-point stencil
48*c4762a1bSJed Brown     is used to discretize the boundary value problem to obtain a
49*c4762a1bSJed Brown     nonlinear system of equations.  Upwinding is used for the divergence
50*c4762a1bSJed Brown     (convective) terms and central for the gradient (source) terms.
51*c4762a1bSJed Brown 
52*c4762a1bSJed Brown     The Jacobian can be either
53*c4762a1bSJed Brown       * formed via finite differencing using coloring (the default), or
54*c4762a1bSJed Brown       * applied matrix-free via the option -snes_mf
55*c4762a1bSJed Brown         (for larger grid problems this variant may not converge
56*c4762a1bSJed Brown         without a preconditioner due to ill-conditioning).
57*c4762a1bSJed Brown 
58*c4762a1bSJed Brown   ------------------------------------------------------------------------F*/
59*c4762a1bSJed Brown 
60*c4762a1bSJed Brown /*
61*c4762a1bSJed Brown    Include "petscdmda.h" so that we can use distributed arrays (DMDAs).
62*c4762a1bSJed Brown    Include "petscsnes.h" so that we can use SNES solvers.  Note that this
63*c4762a1bSJed Brown    file automatically includes:
64*c4762a1bSJed Brown      petscsys.h       - base PETSc routines   petscvec.h - vectors
65*c4762a1bSJed Brown      petscmat.h - matrices
66*c4762a1bSJed Brown      petscis.h     - index sets            petscksp.h - Krylov subspace methods
67*c4762a1bSJed Brown      petscviewer.h - viewers               petscpc.h  - preconditioners
68*c4762a1bSJed Brown      petscksp.h   - linear solvers
69*c4762a1bSJed Brown */
70*c4762a1bSJed Brown #if defined(PETSC_APPLE_FRAMEWORK)
71*c4762a1bSJed Brown #import <PETSc/petscsnes.h>
72*c4762a1bSJed Brown #import <PETSc/petscdmda.h>
73*c4762a1bSJed Brown #else
74*c4762a1bSJed Brown #include <petscsnes.h>
75*c4762a1bSJed Brown #include <petscdm.h>
76*c4762a1bSJed Brown #include <petscdmda.h>
77*c4762a1bSJed Brown #endif
78*c4762a1bSJed Brown 
79*c4762a1bSJed Brown /*
80*c4762a1bSJed Brown    User-defined routines and data structures
81*c4762a1bSJed Brown */
82*c4762a1bSJed Brown typedef struct {
83*c4762a1bSJed Brown   PetscScalar u,v,omega,temp;
84*c4762a1bSJed Brown } Field;
85*c4762a1bSJed Brown 
86*c4762a1bSJed Brown PetscErrorCode FormFunctionLocal(DMDALocalInfo*,Field**,Field**,void*);
87*c4762a1bSJed Brown 
88*c4762a1bSJed Brown typedef struct {
89*c4762a1bSJed Brown   PetscReal   lidvelocity,prandtl,grashof;  /* physical parameters */
90*c4762a1bSJed Brown   PetscBool   draw_contours;                /* flag - 1 indicates drawing contours */
91*c4762a1bSJed Brown } AppCtx;
92*c4762a1bSJed Brown 
93*c4762a1bSJed Brown extern PetscErrorCode FormInitialGuess(AppCtx*,DM,Vec);
94*c4762a1bSJed Brown extern PetscErrorCode NonlinearGS(SNES,Vec,Vec,void*);
95*c4762a1bSJed Brown 
96*c4762a1bSJed Brown int main(int argc,char **argv)
97*c4762a1bSJed Brown {
98*c4762a1bSJed Brown   AppCtx         user;                /* user-defined work context */
99*c4762a1bSJed Brown   PetscInt       mx,my,its;
100*c4762a1bSJed Brown   PetscErrorCode ierr;
101*c4762a1bSJed Brown   MPI_Comm       comm;
102*c4762a1bSJed Brown   SNES           snes;
103*c4762a1bSJed Brown   DM             da;
104*c4762a1bSJed Brown   Vec            x;
105*c4762a1bSJed Brown 
106*c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
107*c4762a1bSJed Brown 
108*c4762a1bSJed Brown   PetscFunctionBeginUser;
109*c4762a1bSJed Brown   comm = PETSC_COMM_WORLD;
110*c4762a1bSJed Brown   ierr = SNESCreate(comm,&snes);CHKERRQ(ierr);
111*c4762a1bSJed Brown 
112*c4762a1bSJed Brown   /*
113*c4762a1bSJed Brown       Create distributed array object to manage parallel grid and vectors
114*c4762a1bSJed Brown       for principal unknowns (x) and governing residuals (f)
115*c4762a1bSJed Brown   */
116*c4762a1bSJed 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);
117*c4762a1bSJed Brown   ierr = DMSetFromOptions(da);CHKERRQ(ierr);
118*c4762a1bSJed Brown   ierr = DMSetUp(da);CHKERRQ(ierr);
119*c4762a1bSJed Brown   ierr = SNESSetDM(snes,(DM)da);CHKERRQ(ierr);
120*c4762a1bSJed Brown   ierr = SNESSetNGS(snes, NonlinearGS, (void*)&user);CHKERRQ(ierr);
121*c4762a1bSJed Brown 
122*c4762a1bSJed Brown   ierr = DMDAGetInfo(da,0,&mx,&my,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr);
123*c4762a1bSJed Brown   /*
124*c4762a1bSJed Brown      Problem parameters (velocity of lid, prandtl, and grashof numbers)
125*c4762a1bSJed Brown   */
126*c4762a1bSJed Brown   user.lidvelocity = 1.0/(mx*my);
127*c4762a1bSJed Brown   user.prandtl     = 1.0;
128*c4762a1bSJed Brown   user.grashof     = 1.0;
129*c4762a1bSJed Brown 
130*c4762a1bSJed Brown   ierr = PetscOptionsGetReal(NULL,NULL,"-lidvelocity",&user.lidvelocity,NULL);CHKERRQ(ierr);
131*c4762a1bSJed Brown   ierr = PetscOptionsGetReal(NULL,NULL,"-prandtl",&user.prandtl,NULL);CHKERRQ(ierr);
132*c4762a1bSJed Brown   ierr = PetscOptionsGetReal(NULL,NULL,"-grashof",&user.grashof,NULL);CHKERRQ(ierr);
133*c4762a1bSJed Brown   ierr = PetscOptionsHasName(NULL,NULL,"-contours",&user.draw_contours);CHKERRQ(ierr);
134*c4762a1bSJed Brown 
135*c4762a1bSJed Brown   ierr = DMDASetFieldName(da,0,"x_velocity");CHKERRQ(ierr);
136*c4762a1bSJed Brown   ierr = DMDASetFieldName(da,1,"y_velocity");CHKERRQ(ierr);
137*c4762a1bSJed Brown   ierr = DMDASetFieldName(da,2,"Omega");CHKERRQ(ierr);
138*c4762a1bSJed Brown   ierr = DMDASetFieldName(da,3,"temperature");CHKERRQ(ierr);
139*c4762a1bSJed Brown 
140*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
141*c4762a1bSJed Brown      Create user context, set problem data, create vector data structures.
142*c4762a1bSJed Brown      Also, compute the initial guess.
143*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
144*c4762a1bSJed Brown 
145*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
146*c4762a1bSJed Brown      Create nonlinear solver context
147*c4762a1bSJed Brown 
148*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
149*c4762a1bSJed Brown   ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr);
150*c4762a1bSJed Brown   ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES,(PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal,&user);CHKERRQ(ierr);
151*c4762a1bSJed Brown   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
152*c4762a1bSJed Brown   ierr = PetscPrintf(comm,"lid velocity = %g, prandtl # = %g, grashof # = %g\n",(double)user.lidvelocity,(double)user.prandtl,(double)user.grashof);CHKERRQ(ierr);
153*c4762a1bSJed Brown 
154*c4762a1bSJed Brown 
155*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
156*c4762a1bSJed Brown      Solve the nonlinear system
157*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
158*c4762a1bSJed Brown   ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr);
159*c4762a1bSJed Brown   ierr = FormInitialGuess(&user,da,x);CHKERRQ(ierr);
160*c4762a1bSJed Brown 
161*c4762a1bSJed Brown   ierr = SNESSolve(snes,NULL,x);CHKERRQ(ierr);
162*c4762a1bSJed Brown 
163*c4762a1bSJed Brown   ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr);
164*c4762a1bSJed Brown   ierr = PetscPrintf(comm,"Number of SNES iterations = %D\n", its);CHKERRQ(ierr);
165*c4762a1bSJed Brown 
166*c4762a1bSJed Brown   /*
167*c4762a1bSJed Brown      Visualize solution
168*c4762a1bSJed Brown   */
169*c4762a1bSJed Brown   if (user.draw_contours) {
170*c4762a1bSJed Brown     ierr = VecView(x,PETSC_VIEWER_DRAW_WORLD);CHKERRQ(ierr);
171*c4762a1bSJed Brown   }
172*c4762a1bSJed Brown 
173*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
174*c4762a1bSJed Brown      Free work space.  All PETSc objects should be destroyed when they
175*c4762a1bSJed Brown      are no longer needed.
176*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
177*c4762a1bSJed Brown   ierr = VecDestroy(&x);CHKERRQ(ierr);
178*c4762a1bSJed Brown   ierr = DMDestroy(&da);CHKERRQ(ierr);
179*c4762a1bSJed Brown   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
180*c4762a1bSJed Brown   ierr = PetscFinalize();
181*c4762a1bSJed Brown   return ierr;
182*c4762a1bSJed Brown }
183*c4762a1bSJed Brown 
184*c4762a1bSJed Brown /* ------------------------------------------------------------------- */
185*c4762a1bSJed Brown 
186*c4762a1bSJed Brown /*
187*c4762a1bSJed Brown    FormInitialGuess - Forms initial approximation.
188*c4762a1bSJed Brown 
189*c4762a1bSJed Brown    Input Parameters:
190*c4762a1bSJed Brown    user - user-defined application context
191*c4762a1bSJed Brown    X - vector
192*c4762a1bSJed Brown 
193*c4762a1bSJed Brown    Output Parameter:
194*c4762a1bSJed Brown    X - vector
195*c4762a1bSJed Brown */
196*c4762a1bSJed Brown PetscErrorCode FormInitialGuess(AppCtx *user,DM da,Vec X)
197*c4762a1bSJed Brown {
198*c4762a1bSJed Brown   PetscInt       i,j,mx,xs,ys,xm,ym;
199*c4762a1bSJed Brown   PetscErrorCode ierr;
200*c4762a1bSJed Brown   PetscReal      grashof,dx;
201*c4762a1bSJed Brown   Field          **x;
202*c4762a1bSJed Brown 
203*c4762a1bSJed Brown   PetscFunctionBeginUser;
204*c4762a1bSJed Brown   grashof = user->grashof;
205*c4762a1bSJed Brown 
206*c4762a1bSJed Brown   ierr = DMDAGetInfo(da,0,&mx,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
207*c4762a1bSJed Brown   dx   = 1.0/(mx-1);
208*c4762a1bSJed Brown 
209*c4762a1bSJed Brown   /*
210*c4762a1bSJed Brown      Get local grid boundaries (for 2-dimensional DMDA):
211*c4762a1bSJed Brown        xs, ys   - starting grid indices (no ghost points)
212*c4762a1bSJed Brown        xm, ym   - widths of local grid (no ghost points)
213*c4762a1bSJed Brown   */
214*c4762a1bSJed Brown   ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr);
215*c4762a1bSJed Brown 
216*c4762a1bSJed Brown   /*
217*c4762a1bSJed Brown      Get a pointer to vector data.
218*c4762a1bSJed Brown        - For default PETSc vectors, VecGetArray() returns a pointer to
219*c4762a1bSJed Brown          the data array.  Otherwise, the routine is implementation dependent.
220*c4762a1bSJed Brown        - You MUST call VecRestoreArray() when you no longer need access to
221*c4762a1bSJed Brown          the array.
222*c4762a1bSJed Brown   */
223*c4762a1bSJed Brown   ierr = DMDAVecGetArrayWrite(da,X,&x);CHKERRQ(ierr);
224*c4762a1bSJed Brown 
225*c4762a1bSJed Brown   /*
226*c4762a1bSJed Brown      Compute initial guess over the locally owned part of the grid
227*c4762a1bSJed Brown      Initial condition is motionless fluid and equilibrium temperature
228*c4762a1bSJed Brown   */
229*c4762a1bSJed Brown   for (j=ys; j<ys+ym; j++) {
230*c4762a1bSJed Brown     for (i=xs; i<xs+xm; i++) {
231*c4762a1bSJed Brown       x[j][i].u     = 0.0;
232*c4762a1bSJed Brown       x[j][i].v     = 0.0;
233*c4762a1bSJed Brown       x[j][i].omega = 0.0;
234*c4762a1bSJed Brown       x[j][i].temp  = (grashof>0)*i*dx;
235*c4762a1bSJed Brown     }
236*c4762a1bSJed Brown   }
237*c4762a1bSJed Brown 
238*c4762a1bSJed Brown   /*
239*c4762a1bSJed Brown      Restore vector
240*c4762a1bSJed Brown   */
241*c4762a1bSJed Brown   ierr = DMDAVecRestoreArrayWrite(da,X,&x);CHKERRQ(ierr);
242*c4762a1bSJed Brown   PetscFunctionReturn(0);
243*c4762a1bSJed Brown }
244*c4762a1bSJed Brown 
245*c4762a1bSJed Brown PetscErrorCode FormFunctionLocal(DMDALocalInfo *info,Field **x,Field **f,void *ptr)
246*c4762a1bSJed Brown {
247*c4762a1bSJed Brown   AppCtx         *user = (AppCtx*)ptr;
248*c4762a1bSJed Brown   PetscErrorCode ierr;
249*c4762a1bSJed Brown   PetscInt       xints,xinte,yints,yinte,i,j;
250*c4762a1bSJed Brown   PetscReal      hx,hy,dhx,dhy,hxdhy,hydhx;
251*c4762a1bSJed Brown   PetscReal      grashof,prandtl,lid;
252*c4762a1bSJed Brown   PetscScalar    u,uxx,uyy,vx,vy,avx,avy,vxp,vxm,vyp,vym;
253*c4762a1bSJed Brown 
254*c4762a1bSJed Brown   PetscFunctionBeginUser;
255*c4762a1bSJed Brown   grashof = user->grashof;
256*c4762a1bSJed Brown   prandtl = user->prandtl;
257*c4762a1bSJed Brown   lid     = user->lidvelocity;
258*c4762a1bSJed Brown 
259*c4762a1bSJed Brown   /*
260*c4762a1bSJed Brown      Define mesh intervals ratios for uniform grid.
261*c4762a1bSJed Brown 
262*c4762a1bSJed Brown      Note: FD formulae below are normalized by multiplying through by
263*c4762a1bSJed Brown      local volume element (i.e. hx*hy) to obtain coefficients O(1) in two dimensions.
264*c4762a1bSJed Brown 
265*c4762a1bSJed Brown 
266*c4762a1bSJed Brown   */
267*c4762a1bSJed Brown   dhx   = (PetscReal)(info->mx-1);  dhy = (PetscReal)(info->my-1);
268*c4762a1bSJed Brown   hx    = 1.0/dhx;                   hy = 1.0/dhy;
269*c4762a1bSJed Brown   hxdhy = hx*dhy;                 hydhx = hy*dhx;
270*c4762a1bSJed Brown 
271*c4762a1bSJed Brown   xints = info->xs; xinte = info->xs+info->xm; yints = info->ys; yinte = info->ys+info->ym;
272*c4762a1bSJed Brown 
273*c4762a1bSJed Brown   /* Test whether we are on the bottom edge of the global array */
274*c4762a1bSJed Brown   if (yints == 0) {
275*c4762a1bSJed Brown     j     = 0;
276*c4762a1bSJed Brown     yints = yints + 1;
277*c4762a1bSJed Brown     /* bottom edge */
278*c4762a1bSJed Brown     for (i=info->xs; i<info->xs+info->xm; i++) {
279*c4762a1bSJed Brown       f[j][i].u     = x[j][i].u;
280*c4762a1bSJed Brown       f[j][i].v     = x[j][i].v;
281*c4762a1bSJed Brown       f[j][i].omega = x[j][i].omega + (x[j+1][i].u - x[j][i].u)*dhy;
282*c4762a1bSJed Brown       f[j][i].temp  = x[j][i].temp-x[j+1][i].temp;
283*c4762a1bSJed Brown     }
284*c4762a1bSJed Brown   }
285*c4762a1bSJed Brown 
286*c4762a1bSJed Brown   /* Test whether we are on the top edge of the global array */
287*c4762a1bSJed Brown   if (yinte == info->my) {
288*c4762a1bSJed Brown     j     = info->my - 1;
289*c4762a1bSJed Brown     yinte = yinte - 1;
290*c4762a1bSJed Brown     /* top edge */
291*c4762a1bSJed Brown     for (i=info->xs; i<info->xs+info->xm; i++) {
292*c4762a1bSJed Brown       f[j][i].u     = x[j][i].u - lid;
293*c4762a1bSJed Brown       f[j][i].v     = x[j][i].v;
294*c4762a1bSJed Brown       f[j][i].omega = x[j][i].omega + (x[j][i].u - x[j-1][i].u)*dhy;
295*c4762a1bSJed Brown       f[j][i].temp  = x[j][i].temp-x[j-1][i].temp;
296*c4762a1bSJed Brown     }
297*c4762a1bSJed Brown   }
298*c4762a1bSJed Brown 
299*c4762a1bSJed Brown   /* Test whether we are on the left edge of the global array */
300*c4762a1bSJed Brown   if (xints == 0) {
301*c4762a1bSJed Brown     i     = 0;
302*c4762a1bSJed Brown     xints = xints + 1;
303*c4762a1bSJed Brown     /* left edge */
304*c4762a1bSJed Brown     for (j=info->ys; j<info->ys+info->ym; j++) {
305*c4762a1bSJed Brown       f[j][i].u     = x[j][i].u;
306*c4762a1bSJed Brown       f[j][i].v     = x[j][i].v;
307*c4762a1bSJed Brown       f[j][i].omega = x[j][i].omega - (x[j][i+1].v - x[j][i].v)*dhx;
308*c4762a1bSJed Brown       f[j][i].temp  = x[j][i].temp;
309*c4762a1bSJed Brown     }
310*c4762a1bSJed Brown   }
311*c4762a1bSJed Brown 
312*c4762a1bSJed Brown   /* Test whether we are on the right edge of the global array */
313*c4762a1bSJed Brown   if (xinte == info->mx) {
314*c4762a1bSJed Brown     i     = info->mx - 1;
315*c4762a1bSJed Brown     xinte = xinte - 1;
316*c4762a1bSJed Brown     /* right edge */
317*c4762a1bSJed Brown     for (j=info->ys; j<info->ys+info->ym; j++) {
318*c4762a1bSJed Brown       f[j][i].u     = x[j][i].u;
319*c4762a1bSJed Brown       f[j][i].v     = x[j][i].v;
320*c4762a1bSJed Brown       f[j][i].omega = x[j][i].omega - (x[j][i].v - x[j][i-1].v)*dhx;
321*c4762a1bSJed Brown       f[j][i].temp  = x[j][i].temp - (PetscReal)(grashof>0);
322*c4762a1bSJed Brown     }
323*c4762a1bSJed Brown   }
324*c4762a1bSJed Brown 
325*c4762a1bSJed Brown   /* Compute over the interior points */
326*c4762a1bSJed Brown   for (j=yints; j<yinte; j++) {
327*c4762a1bSJed Brown     for (i=xints; i<xinte; i++) {
328*c4762a1bSJed Brown 
329*c4762a1bSJed Brown       /*
330*c4762a1bSJed Brown        convective coefficients for upwinding
331*c4762a1bSJed Brown       */
332*c4762a1bSJed Brown       vx  = x[j][i].u; avx = PetscAbsScalar(vx);
333*c4762a1bSJed Brown       vxp = .5*(vx+avx); vxm = .5*(vx-avx);
334*c4762a1bSJed Brown       vy  = x[j][i].v; avy = PetscAbsScalar(vy);
335*c4762a1bSJed Brown       vyp = .5*(vy+avy); vym = .5*(vy-avy);
336*c4762a1bSJed Brown 
337*c4762a1bSJed Brown       /* U velocity */
338*c4762a1bSJed Brown       u         = x[j][i].u;
339*c4762a1bSJed Brown       uxx       = (2.0*u - x[j][i-1].u - x[j][i+1].u)*hydhx;
340*c4762a1bSJed Brown       uyy       = (2.0*u - x[j-1][i].u - x[j+1][i].u)*hxdhy;
341*c4762a1bSJed Brown       f[j][i].u = uxx + uyy - .5*(x[j+1][i].omega-x[j-1][i].omega)*hx;
342*c4762a1bSJed Brown 
343*c4762a1bSJed Brown       /* V velocity */
344*c4762a1bSJed Brown       u         = x[j][i].v;
345*c4762a1bSJed Brown       uxx       = (2.0*u - x[j][i-1].v - x[j][i+1].v)*hydhx;
346*c4762a1bSJed Brown       uyy       = (2.0*u - x[j-1][i].v - x[j+1][i].v)*hxdhy;
347*c4762a1bSJed Brown       f[j][i].v = uxx + uyy + .5*(x[j][i+1].omega-x[j][i-1].omega)*hy;
348*c4762a1bSJed Brown 
349*c4762a1bSJed Brown       /* Omega */
350*c4762a1bSJed Brown       u             = x[j][i].omega;
351*c4762a1bSJed Brown       uxx           = (2.0*u - x[j][i-1].omega - x[j][i+1].omega)*hydhx;
352*c4762a1bSJed Brown       uyy           = (2.0*u - x[j-1][i].omega - x[j+1][i].omega)*hxdhy;
353*c4762a1bSJed Brown       f[j][i].omega = uxx + uyy + (vxp*(u - x[j][i-1].omega) + vxm*(x[j][i+1].omega - u))*hy +
354*c4762a1bSJed Brown                       (vyp*(u - x[j-1][i].omega) + vym*(x[j+1][i].omega - u))*hx -
355*c4762a1bSJed Brown                       .5*grashof*(x[j][i+1].temp - x[j][i-1].temp)*hy;
356*c4762a1bSJed Brown 
357*c4762a1bSJed Brown       /* Temperature */
358*c4762a1bSJed Brown       u            = x[j][i].temp;
359*c4762a1bSJed Brown       uxx          = (2.0*u - x[j][i-1].temp - x[j][i+1].temp)*hydhx;
360*c4762a1bSJed Brown       uyy          = (2.0*u - x[j-1][i].temp - x[j+1][i].temp)*hxdhy;
361*c4762a1bSJed Brown       f[j][i].temp =  uxx + uyy  + prandtl*((vxp*(u - x[j][i-1].temp) + vxm*(x[j][i+1].temp - u))*hy +
362*c4762a1bSJed Brown                                             (vyp*(u - x[j-1][i].temp) + vym*(x[j+1][i].temp - u))*hx);
363*c4762a1bSJed Brown     }
364*c4762a1bSJed Brown   }
365*c4762a1bSJed Brown 
366*c4762a1bSJed Brown   /*
367*c4762a1bSJed Brown      Flop count (multiply-adds are counted as 2 operations)
368*c4762a1bSJed Brown   */
369*c4762a1bSJed Brown   ierr = PetscLogFlops(84.0*info->ym*info->xm);CHKERRQ(ierr);
370*c4762a1bSJed Brown   PetscFunctionReturn(0);
371*c4762a1bSJed Brown }
372*c4762a1bSJed Brown 
373*c4762a1bSJed Brown /*
374*c4762a1bSJed Brown     Performs sweeps of point block nonlinear Gauss-Seidel on all the local grid points
375*c4762a1bSJed Brown */
376*c4762a1bSJed Brown PetscErrorCode NonlinearGS(SNES snes, Vec X, Vec B, void *ctx)
377*c4762a1bSJed Brown {
378*c4762a1bSJed Brown   DMDALocalInfo  info;
379*c4762a1bSJed Brown   Field          **x,**b;
380*c4762a1bSJed Brown   PetscErrorCode ierr;
381*c4762a1bSJed Brown   Vec            localX, localB;
382*c4762a1bSJed Brown   DM             da;
383*c4762a1bSJed Brown   PetscInt       xints,xinte,yints,yinte,i,j,k,l;
384*c4762a1bSJed Brown   PetscInt       max_its,tot_its;
385*c4762a1bSJed Brown   PetscInt       sweeps;
386*c4762a1bSJed Brown   PetscReal      rtol,atol,stol;
387*c4762a1bSJed Brown   PetscReal      hx,hy,dhx,dhy,hxdhy,hydhx;
388*c4762a1bSJed Brown   PetscReal      grashof,prandtl,lid;
389*c4762a1bSJed Brown   PetscScalar    u,uxx,uyy,vx,vy,avx,avy,vxp,vxm,vyp,vym;
390*c4762a1bSJed Brown   PetscScalar    fu, fv, fomega, ftemp;
391*c4762a1bSJed Brown   PetscScalar    dfudu;
392*c4762a1bSJed Brown   PetscScalar    dfvdv;
393*c4762a1bSJed Brown   PetscScalar    dfodu, dfodv, dfodo;
394*c4762a1bSJed Brown   PetscScalar    dftdu, dftdv, dftdt;
395*c4762a1bSJed Brown   PetscScalar    yu=0, yv=0, yo=0, yt=0;
396*c4762a1bSJed Brown   PetscScalar    bjiu, bjiv, bjiomega, bjitemp;
397*c4762a1bSJed Brown   PetscBool      ptconverged;
398*c4762a1bSJed Brown   PetscReal      pfnorm,pfnorm0,pynorm,pxnorm;
399*c4762a1bSJed Brown   AppCtx         *user = (AppCtx*)ctx;
400*c4762a1bSJed Brown 
401*c4762a1bSJed Brown   PetscFunctionBeginUser;
402*c4762a1bSJed Brown   grashof = user->grashof;
403*c4762a1bSJed Brown   prandtl = user->prandtl;
404*c4762a1bSJed Brown   lid     = user->lidvelocity;
405*c4762a1bSJed Brown   tot_its = 0;
406*c4762a1bSJed Brown   ierr    = SNESNGSGetTolerances(snes,&rtol,&atol,&stol,&max_its);CHKERRQ(ierr);
407*c4762a1bSJed Brown   ierr    = SNESNGSGetSweeps(snes,&sweeps);CHKERRQ(ierr);
408*c4762a1bSJed Brown   ierr    = SNESGetDM(snes,(DM*)&da);CHKERRQ(ierr);
409*c4762a1bSJed Brown   ierr    = DMGetLocalVector(da,&localX);CHKERRQ(ierr);
410*c4762a1bSJed Brown   if (B) {
411*c4762a1bSJed Brown     ierr = DMGetLocalVector(da,&localB);CHKERRQ(ierr);
412*c4762a1bSJed Brown   }
413*c4762a1bSJed Brown   /*
414*c4762a1bSJed Brown      Scatter ghost points to local vector, using the 2-step process
415*c4762a1bSJed Brown         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
416*c4762a1bSJed Brown   */
417*c4762a1bSJed Brown   ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
418*c4762a1bSJed Brown   ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
419*c4762a1bSJed Brown   if (B) {
420*c4762a1bSJed Brown     ierr = DMGlobalToLocalBegin(da,B,INSERT_VALUES,localB);CHKERRQ(ierr);
421*c4762a1bSJed Brown     ierr = DMGlobalToLocalEnd(da,B,INSERT_VALUES,localB);CHKERRQ(ierr);
422*c4762a1bSJed Brown   }
423*c4762a1bSJed Brown   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
424*c4762a1bSJed Brown   ierr = DMDAVecGetArrayWrite(da,localX,&x);CHKERRQ(ierr);
425*c4762a1bSJed Brown   if (B) {
426*c4762a1bSJed Brown     ierr = DMDAVecGetArrayRead(da,localB,&b);CHKERRQ(ierr);
427*c4762a1bSJed Brown   }
428*c4762a1bSJed Brown   /* looks like a combination of the formfunction / formjacobian routines */
429*c4762a1bSJed Brown   dhx   = (PetscReal)(info.mx-1);dhy   = (PetscReal)(info.my-1);
430*c4762a1bSJed Brown   hx    = 1.0/dhx;               hy    = 1.0/dhy;
431*c4762a1bSJed Brown   hxdhy = hx*dhy;                hydhx = hy*dhx;
432*c4762a1bSJed Brown 
433*c4762a1bSJed Brown   xints = info.xs; xinte = info.xs+info.xm; yints = info.ys; yinte = info.ys+info.ym;
434*c4762a1bSJed Brown 
435*c4762a1bSJed Brown   /* Set the boundary conditions on the momentum equations */
436*c4762a1bSJed Brown   /* Test whether we are on the bottom edge of the global array */
437*c4762a1bSJed Brown   if (yints == 0) {
438*c4762a1bSJed Brown     j     = 0;
439*c4762a1bSJed Brown     /* bottom edge */
440*c4762a1bSJed Brown     for (i=info.xs; i<info.xs+info.xm; i++) {
441*c4762a1bSJed Brown 
442*c4762a1bSJed Brown       if (B) {
443*c4762a1bSJed Brown         bjiu = b[j][i].u;
444*c4762a1bSJed Brown         bjiv = b[j][i].v;
445*c4762a1bSJed Brown       } else {
446*c4762a1bSJed Brown         bjiu = 0.0;
447*c4762a1bSJed Brown         bjiv = 0.0;
448*c4762a1bSJed Brown       }
449*c4762a1bSJed Brown       x[j][i].u = 0.0 + bjiu;
450*c4762a1bSJed Brown       x[j][i].v = 0.0 + bjiv;
451*c4762a1bSJed Brown     }
452*c4762a1bSJed Brown   }
453*c4762a1bSJed Brown 
454*c4762a1bSJed Brown   /* Test whether we are on the top edge of the global array */
455*c4762a1bSJed Brown   if (yinte == info.my) {
456*c4762a1bSJed Brown     j     = info.my - 1;
457*c4762a1bSJed Brown     /* top edge */
458*c4762a1bSJed Brown     for (i=info.xs; i<info.xs+info.xm; i++) {
459*c4762a1bSJed Brown       if (B) {
460*c4762a1bSJed Brown         bjiu = b[j][i].u;
461*c4762a1bSJed Brown         bjiv = b[j][i].v;
462*c4762a1bSJed Brown       } else {
463*c4762a1bSJed Brown         bjiu = 0.0;
464*c4762a1bSJed Brown         bjiv = 0.0;
465*c4762a1bSJed Brown       }
466*c4762a1bSJed Brown       x[j][i].u = lid + bjiu;
467*c4762a1bSJed Brown       x[j][i].v = bjiv;
468*c4762a1bSJed Brown     }
469*c4762a1bSJed Brown   }
470*c4762a1bSJed Brown 
471*c4762a1bSJed Brown   /* Test whether we are on the left edge of the global array */
472*c4762a1bSJed Brown   if (xints == 0) {
473*c4762a1bSJed Brown     i     = 0;
474*c4762a1bSJed Brown     /* left edge */
475*c4762a1bSJed Brown     for (j=info.ys; j<info.ys+info.ym; j++) {
476*c4762a1bSJed Brown       if (B) {
477*c4762a1bSJed Brown         bjiu = b[j][i].u;
478*c4762a1bSJed Brown         bjiv = b[j][i].v;
479*c4762a1bSJed Brown       } else {
480*c4762a1bSJed Brown         bjiu = 0.0;
481*c4762a1bSJed Brown         bjiv = 0.0;
482*c4762a1bSJed Brown       }
483*c4762a1bSJed Brown       x[j][i].u = 0.0 + bjiu;
484*c4762a1bSJed Brown       x[j][i].v = 0.0 + bjiv;
485*c4762a1bSJed Brown     }
486*c4762a1bSJed Brown   }
487*c4762a1bSJed Brown 
488*c4762a1bSJed Brown   /* Test whether we are on the right edge of the global array */
489*c4762a1bSJed Brown   if (xinte == info.mx) {
490*c4762a1bSJed Brown     i     = info.mx - 1;
491*c4762a1bSJed Brown     /* right edge */
492*c4762a1bSJed Brown     for (j=info.ys; j<info.ys+info.ym; j++) {
493*c4762a1bSJed Brown       if (B) {
494*c4762a1bSJed Brown         bjiu = b[j][i].u;
495*c4762a1bSJed Brown         bjiv = b[j][i].v;
496*c4762a1bSJed Brown       } else {
497*c4762a1bSJed Brown         bjiu = 0.0;
498*c4762a1bSJed Brown         bjiv = 0.0;
499*c4762a1bSJed Brown       }
500*c4762a1bSJed Brown       x[j][i].u = 0.0 + bjiu;
501*c4762a1bSJed Brown       x[j][i].v = 0.0 + bjiv;
502*c4762a1bSJed Brown     }
503*c4762a1bSJed Brown   }
504*c4762a1bSJed Brown 
505*c4762a1bSJed Brown   for (k=0; k < sweeps; k++) {
506*c4762a1bSJed Brown     for (j=info.ys; j<info.ys + info.ym; j++) {
507*c4762a1bSJed Brown       for (i=info.xs; i<info.xs + info.xm; i++) {
508*c4762a1bSJed Brown         ptconverged = PETSC_FALSE;
509*c4762a1bSJed Brown         pfnorm0     = 0.0;
510*c4762a1bSJed Brown         fu          = 0.0;
511*c4762a1bSJed Brown         fv          = 0.0;
512*c4762a1bSJed Brown         fomega      = 0.0;
513*c4762a1bSJed Brown         ftemp       = 0.0;
514*c4762a1bSJed Brown         /*  Run Newton's method on a single grid point */
515*c4762a1bSJed Brown         for (l = 0; l < max_its && !ptconverged; l++) {
516*c4762a1bSJed Brown           if (B) {
517*c4762a1bSJed Brown             bjiu     = b[j][i].u;
518*c4762a1bSJed Brown             bjiv     = b[j][i].v;
519*c4762a1bSJed Brown             bjiomega = b[j][i].omega;
520*c4762a1bSJed Brown             bjitemp  = b[j][i].temp;
521*c4762a1bSJed Brown           } else {
522*c4762a1bSJed Brown             bjiu     = 0.0;
523*c4762a1bSJed Brown             bjiv     = 0.0;
524*c4762a1bSJed Brown             bjiomega = 0.0;
525*c4762a1bSJed Brown             bjitemp  = 0.0;
526*c4762a1bSJed Brown           }
527*c4762a1bSJed Brown 
528*c4762a1bSJed Brown           if (i != 0 && i != info.mx - 1 && j != 0 && j != info.my-1) {
529*c4762a1bSJed Brown             /* U velocity */
530*c4762a1bSJed Brown             u     = x[j][i].u;
531*c4762a1bSJed Brown             uxx   = (2.0*u - x[j][i-1].u - x[j][i+1].u)*hydhx;
532*c4762a1bSJed Brown             uyy   = (2.0*u - x[j-1][i].u - x[j+1][i].u)*hxdhy;
533*c4762a1bSJed Brown             fu    = uxx + uyy - .5*(x[j+1][i].omega-x[j-1][i].omega)*hx - bjiu;
534*c4762a1bSJed Brown             dfudu = 2.0*(hydhx + hxdhy);
535*c4762a1bSJed Brown             /* V velocity */
536*c4762a1bSJed Brown             u     = x[j][i].v;
537*c4762a1bSJed Brown             uxx   = (2.0*u - x[j][i-1].v - x[j][i+1].v)*hydhx;
538*c4762a1bSJed Brown             uyy   = (2.0*u - x[j-1][i].v - x[j+1][i].v)*hxdhy;
539*c4762a1bSJed Brown             fv    = uxx + uyy + .5*(x[j][i+1].omega-x[j][i-1].omega)*hy - bjiv;
540*c4762a1bSJed Brown             dfvdv = 2.0*(hydhx + hxdhy);
541*c4762a1bSJed Brown             /*
542*c4762a1bSJed Brown              convective coefficients for upwinding
543*c4762a1bSJed Brown              */
544*c4762a1bSJed Brown             vx  = x[j][i].u; avx = PetscAbsScalar(vx);
545*c4762a1bSJed Brown             vxp = .5*(vx+avx); vxm = .5*(vx-avx);
546*c4762a1bSJed Brown             vy  = x[j][i].v; avy = PetscAbsScalar(vy);
547*c4762a1bSJed Brown             vyp = .5*(vy+avy); vym = .5*(vy-avy);
548*c4762a1bSJed Brown             /* Omega */
549*c4762a1bSJed Brown             u      = x[j][i].omega;
550*c4762a1bSJed Brown             uxx    = (2.0*u - x[j][i-1].omega - x[j][i+1].omega)*hydhx;
551*c4762a1bSJed Brown             uyy    = (2.0*u - x[j-1][i].omega - x[j+1][i].omega)*hxdhy;
552*c4762a1bSJed Brown             fomega = uxx + uyy +  (vxp*(u - x[j][i-1].omega) + vxm*(x[j][i+1].omega - u))*hy +
553*c4762a1bSJed Brown                      (vyp*(u - x[j-1][i].omega) + vym*(x[j+1][i].omega - u))*hx -
554*c4762a1bSJed Brown                      .5*grashof*(x[j][i+1].temp - x[j][i-1].temp)*hy - bjiomega;
555*c4762a1bSJed Brown             /* convective coefficient derivatives */
556*c4762a1bSJed Brown             dfodo = 2.0*(hydhx + hxdhy) + ((vxp - vxm)*hy + (vyp - vym)*hx);
557*c4762a1bSJed Brown             if (PetscRealPart(vx) > 0.0) dfodu = (u - x[j][i-1].omega)*hy;
558*c4762a1bSJed Brown             else dfodu = (x[j][i+1].omega - u)*hy;
559*c4762a1bSJed Brown 
560*c4762a1bSJed Brown             if (PetscRealPart(vy) > 0.0) dfodv = (u - x[j-1][i].omega)*hx;
561*c4762a1bSJed Brown             else dfodv = (x[j+1][i].omega - u)*hx;
562*c4762a1bSJed Brown 
563*c4762a1bSJed Brown             /* Temperature */
564*c4762a1bSJed Brown             u     = x[j][i].temp;
565*c4762a1bSJed Brown             uxx   = (2.0*u - x[j][i-1].temp - x[j][i+1].temp)*hydhx;
566*c4762a1bSJed Brown             uyy   = (2.0*u - x[j-1][i].temp - x[j+1][i].temp)*hxdhy;
567*c4762a1bSJed Brown             ftemp =  uxx + uyy  + prandtl*((vxp*(u - x[j][i-1].temp) + vxm*(x[j][i+1].temp - u))*hy + (vyp*(u - x[j-1][i].temp) + vym*(x[j+1][i].temp - u))*hx) - bjitemp;
568*c4762a1bSJed Brown             dftdt = 2.0*(hydhx + hxdhy) + prandtl*((vxp - vxm)*hy + (vyp - vym)*hx);
569*c4762a1bSJed Brown             if (PetscRealPart(vx) > 0.0) dftdu = prandtl*(u - x[j][i-1].temp)*hy;
570*c4762a1bSJed Brown             else dftdu = prandtl*(x[j][i+1].temp - u)*hy;
571*c4762a1bSJed Brown 
572*c4762a1bSJed Brown             if (PetscRealPart(vy) > 0.0) dftdv = prandtl*(u - x[j-1][i].temp)*hx;
573*c4762a1bSJed Brown             else dftdv = prandtl*(x[j+1][i].temp - u)*hx;
574*c4762a1bSJed Brown 
575*c4762a1bSJed Brown             /* invert the system:
576*c4762a1bSJed Brown              [ dfu / du     0        0        0    ][yu] = [fu]
577*c4762a1bSJed Brown              [     0    dfv / dv     0        0    ][yv]   [fv]
578*c4762a1bSJed Brown              [ dfo / du dfo / dv dfo / do     0    ][yo]   [fo]
579*c4762a1bSJed Brown              [ dft / du dft / dv     0    dft / dt ][yt]   [ft]
580*c4762a1bSJed Brown              by simple back-substitution
581*c4762a1bSJed Brown            */
582*c4762a1bSJed Brown             yu = fu / dfudu;
583*c4762a1bSJed Brown             yv = fv / dfvdv;
584*c4762a1bSJed Brown             yo = (fomega - (dfodu*yu + dfodv*yv)) / dfodo;
585*c4762a1bSJed Brown             yt = (ftemp - (dftdu*yu + dftdv*yv)) / dftdt;
586*c4762a1bSJed Brown 
587*c4762a1bSJed Brown             x[j][i].u     = x[j][i].u - yu;
588*c4762a1bSJed Brown             x[j][i].v     = x[j][i].v - yv;
589*c4762a1bSJed Brown             x[j][i].temp  = x[j][i].temp - yt;
590*c4762a1bSJed Brown             x[j][i].omega = x[j][i].omega - yo;
591*c4762a1bSJed Brown           }
592*c4762a1bSJed Brown           if (i == 0) {
593*c4762a1bSJed Brown             fomega        = x[j][i].omega - (x[j][i+1].v - x[j][i].v)*dhx - bjiomega;
594*c4762a1bSJed Brown             ftemp         = x[j][i].temp - bjitemp;
595*c4762a1bSJed Brown             yo            = fomega;
596*c4762a1bSJed Brown             yt            = ftemp;
597*c4762a1bSJed Brown             x[j][i].omega = x[j][i].omega - fomega;
598*c4762a1bSJed Brown             x[j][i].temp  = x[j][i].temp - ftemp;
599*c4762a1bSJed Brown           }
600*c4762a1bSJed Brown           if (i == info.mx - 1) {
601*c4762a1bSJed Brown             fomega        = x[j][i].omega - (x[j][i].v - x[j][i-1].v)*dhx - bjiomega;
602*c4762a1bSJed Brown             ftemp         = x[j][i].temp - (PetscReal)(grashof>0) - bjitemp;
603*c4762a1bSJed Brown             yo            = fomega;
604*c4762a1bSJed Brown             yt            = ftemp;
605*c4762a1bSJed Brown             x[j][i].omega = x[j][i].omega - fomega;
606*c4762a1bSJed Brown             x[j][i].temp  = x[j][i].temp - ftemp;
607*c4762a1bSJed Brown           }
608*c4762a1bSJed Brown           if (j == 0) {
609*c4762a1bSJed Brown             fomega        = x[j][i].omega + (x[j+1][i].u - x[j][i].u)*dhy - bjiomega;
610*c4762a1bSJed Brown             ftemp         = x[j][i].temp-x[j+1][i].temp - bjitemp;
611*c4762a1bSJed Brown             yo            = fomega;
612*c4762a1bSJed Brown             yt            = ftemp;
613*c4762a1bSJed Brown             x[j][i].omega = x[j][i].omega - fomega;
614*c4762a1bSJed Brown             x[j][i].temp  = x[j][i].temp - ftemp;
615*c4762a1bSJed Brown           }
616*c4762a1bSJed Brown           if (j == info.my - 1) {
617*c4762a1bSJed Brown             fomega        = x[j][i].omega + (x[j][i].u - x[j-1][i].u)*dhy - bjiomega;
618*c4762a1bSJed Brown             ftemp         = x[j][i].temp-x[j-1][i].temp - bjitemp;
619*c4762a1bSJed Brown             yo            = fomega;
620*c4762a1bSJed Brown             yt            = ftemp;
621*c4762a1bSJed Brown             x[j][i].omega = x[j][i].omega - fomega;
622*c4762a1bSJed Brown             x[j][i].temp  = x[j][i].temp - ftemp;
623*c4762a1bSJed Brown           }
624*c4762a1bSJed Brown           tot_its++;
625*c4762a1bSJed Brown           pfnorm = PetscRealPart(fu*fu + fv*fv + fomega*fomega + ftemp*ftemp);
626*c4762a1bSJed Brown           pfnorm = PetscSqrtReal(pfnorm);
627*c4762a1bSJed Brown           pynorm = PetscRealPart(yu*yu + yv*yv + yo*yo + yt*yt);
628*c4762a1bSJed Brown           pynorm = PetscSqrtReal(pynorm);
629*c4762a1bSJed Brown           pxnorm = PetscRealPart(x[j][i].u*x[j][i].u + x[j][i].v*x[j][i].v + x[j][i].omega*x[j][i].omega + x[j][i].temp*x[j][i].temp);
630*c4762a1bSJed Brown           pxnorm = PetscSqrtReal(pxnorm);
631*c4762a1bSJed Brown           if (l == 0) pfnorm0 = pfnorm;
632*c4762a1bSJed Brown           if (rtol*pfnorm0 >pfnorm || atol > pfnorm || pxnorm*stol > pynorm) ptconverged = PETSC_TRUE;
633*c4762a1bSJed Brown         }
634*c4762a1bSJed Brown       }
635*c4762a1bSJed Brown     }
636*c4762a1bSJed Brown   }
637*c4762a1bSJed Brown   ierr = DMDAVecRestoreArrayWrite(da,localX,&x);CHKERRQ(ierr);
638*c4762a1bSJed Brown   if (B) {
639*c4762a1bSJed Brown     ierr = DMDAVecRestoreArrayRead(da,localB,&b);CHKERRQ(ierr);
640*c4762a1bSJed Brown   }
641*c4762a1bSJed Brown   ierr = DMLocalToGlobalBegin(da,localX,INSERT_VALUES,X);CHKERRQ(ierr);
642*c4762a1bSJed Brown   ierr = DMLocalToGlobalEnd(da,localX,INSERT_VALUES,X);CHKERRQ(ierr);
643*c4762a1bSJed Brown   ierr = PetscLogFlops(tot_its*(84.0 + 41.0 + 26.0));CHKERRQ(ierr);
644*c4762a1bSJed Brown   ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr);
645*c4762a1bSJed Brown   if (B) {
646*c4762a1bSJed Brown     ierr = DMRestoreLocalVector(da,&localB);CHKERRQ(ierr);
647*c4762a1bSJed Brown   }
648*c4762a1bSJed Brown   PetscFunctionReturn(0);
649*c4762a1bSJed Brown }
650*c4762a1bSJed Brown 
651*c4762a1bSJed Brown 
652*c4762a1bSJed Brown /*TEST
653*c4762a1bSJed Brown 
654*c4762a1bSJed Brown    test:
655*c4762a1bSJed Brown       nsize: 2
656*c4762a1bSJed Brown       args: -da_refine 3 -snes_monitor_short -pc_type mg -ksp_type fgmres -pc_mg_type full
657*c4762a1bSJed Brown       requires: !single
658*c4762a1bSJed Brown 
659*c4762a1bSJed Brown    test:
660*c4762a1bSJed Brown       suffix: 10
661*c4762a1bSJed Brown       nsize: 3
662*c4762a1bSJed Brown       args: -snes_monitor_short -ksp_monitor_short -pc_type fieldsplit -pc_fieldsplit_type symmetric_multiplicative -snes_view -da_refine 1 -ksp_type fgmres
663*c4762a1bSJed Brown       requires: !single
664*c4762a1bSJed Brown 
665*c4762a1bSJed Brown    test:
666*c4762a1bSJed Brown       suffix: 11
667*c4762a1bSJed Brown       nsize: 4
668*c4762a1bSJed Brown       requires: pastix
669*c4762a1bSJed Brown       args: -snes_monitor_short -pc_type redundant -dm_mat_type mpiaij -redundant_pc_factor_mat_solver_type pastix -pc_redundant_number 2 -da_refine 4 -ksp_type fgmres
670*c4762a1bSJed Brown 
671*c4762a1bSJed Brown    test:
672*c4762a1bSJed Brown       suffix: 12
673*c4762a1bSJed Brown       nsize: 12
674*c4762a1bSJed Brown       requires: pastix
675*c4762a1bSJed Brown       args: -snes_monitor_short -pc_type redundant -dm_mat_type mpiaij -redundant_pc_factor_mat_solver_type pastix -pc_redundant_number 5 -da_refine 4 -ksp_type fgmres
676*c4762a1bSJed Brown 
677*c4762a1bSJed Brown    test:
678*c4762a1bSJed Brown       suffix: 13
679*c4762a1bSJed Brown       nsize: 3
680*c4762a1bSJed Brown       args: -snes_monitor_short -ksp_monitor_short -pc_type fieldsplit -pc_fieldsplit_type multiplicative -snes_view -da_refine 1 -ksp_type fgmres -snes_mf_operator
681*c4762a1bSJed Brown       requires: !single
682*c4762a1bSJed Brown 
683*c4762a1bSJed Brown    test:
684*c4762a1bSJed Brown       suffix: 14
685*c4762a1bSJed Brown       nsize: 4
686*c4762a1bSJed Brown       args: -snes_monitor_short -pc_type mg -dm_mat_type baij -mg_coarse_pc_type bjacobi -da_refine 3 -ksp_type fgmres
687*c4762a1bSJed Brown       requires: !single
688*c4762a1bSJed Brown 
689*c4762a1bSJed Brown    test:
690*c4762a1bSJed Brown       suffix: 14_ds
691*c4762a1bSJed Brown       nsize: 4
692*c4762a1bSJed Brown       args: -snes_converged_reason -pc_type mg -dm_mat_type baij -mg_coarse_pc_type bjacobi -da_refine 3 -ksp_type fgmres -mat_fd_type ds
693*c4762a1bSJed Brown       output_file: output/ex19_2.out
694*c4762a1bSJed Brown       requires: !single
695*c4762a1bSJed Brown 
696*c4762a1bSJed Brown    test:
697*c4762a1bSJed Brown       suffix: 17
698*c4762a1bSJed Brown       args: -snes_monitor_short -ksp_pc_side right
699*c4762a1bSJed Brown       requires: !single
700*c4762a1bSJed Brown 
701*c4762a1bSJed Brown    test:
702*c4762a1bSJed Brown       suffix: 18
703*c4762a1bSJed Brown       args: -ksp_monitor_snes_lg -ksp_pc_side right
704*c4762a1bSJed Brown       requires: x !single
705*c4762a1bSJed Brown 
706*c4762a1bSJed Brown    test:
707*c4762a1bSJed Brown       suffix: 2
708*c4762a1bSJed Brown       nsize: 4
709*c4762a1bSJed Brown       args: -da_refine 3 -snes_converged_reason -pc_type mg -mat_fd_type ds
710*c4762a1bSJed Brown       requires: !single
711*c4762a1bSJed Brown 
712*c4762a1bSJed Brown    test:
713*c4762a1bSJed Brown       suffix: 2_bcols1
714*c4762a1bSJed Brown       nsize: 4
715*c4762a1bSJed Brown       args: -da_refine 3 -snes_converged_reason -pc_type mg -mat_fd_type ds -mat_fd_coloring_bcols
716*c4762a1bSJed Brown       output_file: output/ex19_2.out
717*c4762a1bSJed Brown       requires: !single
718*c4762a1bSJed Brown 
719*c4762a1bSJed Brown    test:
720*c4762a1bSJed Brown       suffix: 3
721*c4762a1bSJed Brown       nsize: 4
722*c4762a1bSJed Brown       requires: mumps
723*c4762a1bSJed Brown       args: -da_refine 3 -snes_monitor_short -pc_type redundant -dm_mat_type mpiaij -redundant_ksp_type preonly -redundant_pc_factor_mat_solver_type mumps -pc_redundant_number 2
724*c4762a1bSJed Brown 
725*c4762a1bSJed Brown    test:
726*c4762a1bSJed Brown       suffix: 4
727*c4762a1bSJed Brown       nsize: 12
728*c4762a1bSJed Brown       requires: mumps
729*c4762a1bSJed Brown       args: -da_refine 3 -snes_monitor_short -pc_type redundant -dm_mat_type mpiaij -redundant_ksp_type preonly -redundant_pc_factor_mat_solver_type mumps -pc_redundant_number 5
730*c4762a1bSJed Brown       output_file: output/ex19_3.out
731*c4762a1bSJed Brown 
732*c4762a1bSJed Brown    test:
733*c4762a1bSJed Brown       suffix: 6
734*c4762a1bSJed Brown       args: -snes_monitor_short -ksp_monitor_short -pc_type fieldsplit -snes_view -ksp_type fgmres -da_refine 1
735*c4762a1bSJed Brown       requires: !single
736*c4762a1bSJed Brown 
737*c4762a1bSJed Brown    test:
738*c4762a1bSJed Brown       suffix: 7
739*c4762a1bSJed Brown       nsize: 3
740*c4762a1bSJed Brown       args: -snes_monitor_short -ksp_monitor_short -pc_type fieldsplit -snes_view -da_refine 1 -ksp_type fgmres
741*c4762a1bSJed Brown 
742*c4762a1bSJed Brown       requires: !single
743*c4762a1bSJed Brown    test:
744*c4762a1bSJed Brown       suffix: 8
745*c4762a1bSJed Brown       args: -snes_monitor_short -ksp_monitor_short -pc_type fieldsplit -pc_fieldsplit_block_size 2 -pc_fieldsplit_0_fields 0,1 -pc_fieldsplit_1_fields 0,1 -pc_fieldsplit_type multiplicative -snes_view -fieldsplit_pc_type lu -da_refine 1 -ksp_type fgmres
746*c4762a1bSJed Brown       requires: !single
747*c4762a1bSJed Brown 
748*c4762a1bSJed Brown    test:
749*c4762a1bSJed Brown       suffix: 9
750*c4762a1bSJed Brown       nsize: 3
751*c4762a1bSJed Brown       args: -snes_monitor_short -ksp_monitor_short -pc_type fieldsplit -pc_fieldsplit_type multiplicative -snes_view -da_refine 1 -ksp_type fgmres
752*c4762a1bSJed Brown       requires: !single
753*c4762a1bSJed Brown 
754*c4762a1bSJed Brown    test:
755*c4762a1bSJed Brown       suffix: aspin
756*c4762a1bSJed Brown       nsize: 4
757*c4762a1bSJed Brown       args: -da_refine 3 -da_overlap 2 -snes_monitor_short -snes_type aspin -grashof 4e4 -lidvelocity 100 -ksp_monitor_short
758*c4762a1bSJed Brown       requires: !single
759*c4762a1bSJed Brown 
760*c4762a1bSJed Brown    test:
761*c4762a1bSJed Brown       suffix: bcgsl
762*c4762a1bSJed Brown       nsize: 2
763*c4762a1bSJed Brown       args: -ksp_type bcgsl -ksp_monitor_short -da_refine 2 -ksp_bcgsl_ell 3 -snes_view
764*c4762a1bSJed Brown       requires: !single
765*c4762a1bSJed Brown 
766*c4762a1bSJed Brown    test:
767*c4762a1bSJed Brown       suffix: bcols1
768*c4762a1bSJed Brown       nsize: 2
769*c4762a1bSJed Brown       args: -da_refine 3 -snes_monitor_short -pc_type mg -ksp_type fgmres -pc_mg_type full -mat_fd_coloring_bcols 1
770*c4762a1bSJed Brown       output_file: output/ex19_1.out
771*c4762a1bSJed Brown       requires: !single
772*c4762a1bSJed Brown 
773*c4762a1bSJed Brown    test:
774*c4762a1bSJed Brown       suffix: bjacobi
775*c4762a1bSJed Brown       nsize: 4
776*c4762a1bSJed Brown       args: -da_refine 4 -ksp_type fgmres -pc_type bjacobi -pc_bjacobi_blocks 2 -sub_ksp_type gmres -sub_ksp_max_it 2 -sub_pc_type bjacobi -sub_sub_ksp_type preonly -sub_sub_pc_type ilu -snes_monitor_short
777*c4762a1bSJed Brown       requires: !single
778*c4762a1bSJed Brown 
779*c4762a1bSJed Brown    test:
780*c4762a1bSJed Brown       suffix: cgne
781*c4762a1bSJed Brown       args: -da_refine 2 -pc_type lu -ksp_type cgne -ksp_monitor_short -ksp_converged_reason -ksp_view -ksp_norm_type unpreconditioned
782*c4762a1bSJed Brown       filter: grep -v HERMITIAN
783*c4762a1bSJed Brown       requires: !single
784*c4762a1bSJed Brown 
785*c4762a1bSJed Brown    test:
786*c4762a1bSJed Brown       suffix: cgs
787*c4762a1bSJed Brown       args: -da_refine 1 -ksp_monitor_short -ksp_type cgs
788*c4762a1bSJed Brown       requires: !single
789*c4762a1bSJed Brown 
790*c4762a1bSJed Brown    test:
791*c4762a1bSJed Brown       suffix: composite_fieldsplit
792*c4762a1bSJed Brown       args: -ksp_type fgmres -pc_type composite -pc_composite_type MULTIPLICATIVE -pc_composite_pcs fieldsplit,none -sub_0_pc_fieldsplit_block_size 4 -sub_0_pc_fieldsplit_type additive -sub_0_pc_fieldsplit_0_fields 0,1,2 -sub_0_pc_fieldsplit_1_fields 3 -snes_monitor_short -ksp_monitor_short
793*c4762a1bSJed Brown       requires: !single
794*c4762a1bSJed Brown 
795*c4762a1bSJed Brown    test:
796*c4762a1bSJed Brown       suffix: composite_fieldsplit_bjacobi
797*c4762a1bSJed Brown       args: -ksp_type fgmres -pc_type composite -pc_composite_type MULTIPLICATIVE -pc_composite_pcs fieldsplit,bjacobi -sub_0_pc_fieldsplit_block_size 4 -sub_0_pc_fieldsplit_type additive -sub_0_pc_fieldsplit_0_fields 0,1,2 -sub_0_pc_fieldsplit_1_fields 3 -sub_1_pc_bjacobi_blocks 16 -sub_1_sub_pc_type lu -snes_monitor_short -ksp_monitor_short
798*c4762a1bSJed Brown       requires: !single
799*c4762a1bSJed Brown 
800*c4762a1bSJed Brown    test:
801*c4762a1bSJed Brown       suffix: composite_fieldsplit_bjacobi_2
802*c4762a1bSJed Brown       nsize: 4
803*c4762a1bSJed Brown       args: -ksp_type fgmres -pc_type composite -pc_composite_type MULTIPLICATIVE -pc_composite_pcs fieldsplit,bjacobi -sub_0_pc_fieldsplit_block_size 4 -sub_0_pc_fieldsplit_type additive -sub_0_pc_fieldsplit_0_fields 0,1,2 -sub_0_pc_fieldsplit_1_fields 3 -sub_1_pc_bjacobi_blocks 16 -sub_1_sub_pc_type lu -snes_monitor_short -ksp_monitor_short
804*c4762a1bSJed Brown       requires: !single
805*c4762a1bSJed Brown 
806*c4762a1bSJed Brown    test:
807*c4762a1bSJed Brown       suffix: composite_gs_newton
808*c4762a1bSJed Brown       nsize: 2
809*c4762a1bSJed Brown       args: -da_refine 3 -grashof 4e4 -lidvelocity 100 -snes_monitor_short -snes_type composite -snes_composite_type additiveoptimal -snes_composite_sneses ngs,newtonls -sub_0_snes_max_it 20 -sub_1_pc_type mg
810*c4762a1bSJed Brown       requires: !single
811*c4762a1bSJed Brown 
812*c4762a1bSJed Brown    test:
813*c4762a1bSJed Brown       suffix: cuda
814*c4762a1bSJed Brown       requires: cuda !single
815*c4762a1bSJed Brown       args: -dm_vec_type cuda -dm_mat_type aijcusparse -pc_type none -ksp_type fgmres -snes_monitor_short -snes_rtol 1.e-5
816*c4762a1bSJed Brown 
817*c4762a1bSJed Brown    test:
818*c4762a1bSJed Brown       suffix: draw
819*c4762a1bSJed Brown       args: -pc_type fieldsplit -snes_view draw -fieldsplit_x_velocity_pc_type mg -fieldsplit_x_velocity_pc_mg_galerkin pmat -fieldsplit_x_velocity_pc_mg_levels 2 -da_refine 1 -fieldsplit_x_velocity_mg_coarse_pc_type svd
820*c4762a1bSJed Brown       requires: x !single
821*c4762a1bSJed Brown 
822*c4762a1bSJed Brown    test:
823*c4762a1bSJed Brown       suffix: drawports
824*c4762a1bSJed Brown       args: -snes_monitor_solution draw::draw_ports -da_refine 1
825*c4762a1bSJed Brown       output_file: output/ex19_draw.out
826*c4762a1bSJed Brown       requires: x !single
827*c4762a1bSJed Brown 
828*c4762a1bSJed Brown    test:
829*c4762a1bSJed Brown       suffix: fas
830*c4762a1bSJed Brown       args: -da_refine 4 -snes_monitor_short -snes_type fas -fas_levels_snes_type ngs -fas_levels_snes_ngs_sweeps 3 -fas_levels_snes_ngs_atol 0.0 -fas_levels_snes_ngs_stol 0.0 -grashof 4e4 -snes_fas_smoothup 6 -snes_fas_smoothdown 6 -lidvelocity 100
831*c4762a1bSJed Brown       requires: !single
832*c4762a1bSJed Brown 
833*c4762a1bSJed Brown    test:
834*c4762a1bSJed Brown       suffix: fas_full
835*c4762a1bSJed Brown       args: -da_refine 4 -snes_monitor_short -snes_type fas -snes_fas_type full -snes_fas_full_downsweep -fas_levels_snes_type ngs -fas_levels_snes_ngs_sweeps 3 -fas_levels_snes_ngs_atol 0.0 -fas_levels_snes_ngs_stol 0.0 -grashof 4e4 -snes_fas_smoothup 6 -snes_fas_smoothdown 6 -lidvelocity 100
836*c4762a1bSJed Brown       requires: !single
837*c4762a1bSJed Brown 
838*c4762a1bSJed Brown    test:
839*c4762a1bSJed Brown       suffix: fdcoloring_ds
840*c4762a1bSJed Brown       args: -da_refine 3 -snes_converged_reason -pc_type mg -mat_fd_type ds
841*c4762a1bSJed Brown       output_file: output/ex19_2.out
842*c4762a1bSJed Brown       requires: !single
843*c4762a1bSJed Brown 
844*c4762a1bSJed Brown    test:
845*c4762a1bSJed Brown       suffix: fdcoloring_ds_baij
846*c4762a1bSJed Brown       args: -da_refine 3 -snes_converged_reason -pc_type mg -mat_fd_type ds -dm_mat_type baij
847*c4762a1bSJed Brown       output_file: output/ex19_2.out
848*c4762a1bSJed Brown       requires: !single
849*c4762a1bSJed Brown 
850*c4762a1bSJed Brown    test:
851*c4762a1bSJed Brown       suffix: fdcoloring_ds_bcols1
852*c4762a1bSJed Brown       args: -da_refine 3 -snes_converged_reason -pc_type mg -mat_fd_type ds -mat_fd_coloring_bcols 1
853*c4762a1bSJed Brown       output_file: output/ex19_2.out
854*c4762a1bSJed Brown       requires: !single
855*c4762a1bSJed Brown 
856*c4762a1bSJed Brown    test:
857*c4762a1bSJed Brown       suffix: fdcoloring_wp
858*c4762a1bSJed Brown       args: -da_refine 3 -snes_monitor_short -pc_type mg
859*c4762a1bSJed Brown       requires: !single
860*c4762a1bSJed Brown 
861*c4762a1bSJed Brown    test:
862*c4762a1bSJed Brown       suffix: fdcoloring_wp_baij
863*c4762a1bSJed Brown       args: -da_refine 3 -snes_monitor_short -pc_type mg -dm_mat_type baij
864*c4762a1bSJed Brown       output_file: output/ex19_fdcoloring_wp.out
865*c4762a1bSJed Brown       requires: !single
866*c4762a1bSJed Brown 
867*c4762a1bSJed Brown    test:
868*c4762a1bSJed Brown       suffix: fdcoloring_wp_bcols1
869*c4762a1bSJed Brown       args: -da_refine 3 -snes_monitor_short -pc_type mg -mat_fd_coloring_bcols 1
870*c4762a1bSJed Brown       output_file: output/ex19_fdcoloring_wp.out
871*c4762a1bSJed Brown       requires: !single
872*c4762a1bSJed Brown 
873*c4762a1bSJed Brown    test:
874*c4762a1bSJed Brown       suffix: fieldsplit_2
875*c4762a1bSJed Brown       args: -ksp_type fgmres -pc_type fieldsplit -pc_fieldsplit_block_size 4 -pc_fieldsplit_type additive -pc_fieldsplit_0_fields 0,1,2 -pc_fieldsplit_1_fields 3 -snes_monitor_short -ksp_monitor_short
876*c4762a1bSJed Brown       requires: !single
877*c4762a1bSJed Brown 
878*c4762a1bSJed Brown    test:
879*c4762a1bSJed Brown       suffix: fieldsplit_3
880*c4762a1bSJed Brown       args: -ksp_type fgmres -pc_type fieldsplit -pc_fieldsplit_block_size 4 -pc_fieldsplit_type additive -pc_fieldsplit_0_fields 0,1,2 -pc_fieldsplit_1_fields 3 -fieldsplit_0_pc_type lu -fieldsplit_1_pc_type lu -snes_monitor_short -ksp_monitor_short
881*c4762a1bSJed Brown       requires: !single
882*c4762a1bSJed Brown 
883*c4762a1bSJed Brown    test:
884*c4762a1bSJed Brown       suffix: fieldsplit_4
885*c4762a1bSJed Brown       args: -ksp_type fgmres -pc_type fieldsplit -pc_fieldsplit_block_size 4 -pc_fieldsplit_type SCHUR -pc_fieldsplit_0_fields 0,1,2 -pc_fieldsplit_1_fields 3 -fieldsplit_0_pc_type lu -fieldsplit_1_pc_type lu -snes_monitor_short -ksp_monitor_short
886*c4762a1bSJed Brown       requires: !single
887*c4762a1bSJed Brown 
888*c4762a1bSJed Brown    # HYPRE PtAP broken with complex numbers
889*c4762a1bSJed Brown    test:
890*c4762a1bSJed Brown       suffix: fieldsplit_hypre
891*c4762a1bSJed Brown       nsize: 2
892*c4762a1bSJed Brown       requires: hypre mumps !complex
893*c4762a1bSJed Brown       args: -pc_type fieldsplit -pc_fieldsplit_block_size 4 -pc_fieldsplit_type SCHUR -pc_fieldsplit_0_fields 0,1,2 -pc_fieldsplit_1_fields 3 -fieldsplit_0_pc_type lu -fieldsplit_0_pc_factor_mat_solver_type mumps -fieldsplit_1_pc_type hypre -fieldsplit_1_pc_hypre_type boomeramg -snes_monitor_short -ksp_monitor_short
894*c4762a1bSJed Brown 
895*c4762a1bSJed Brown    test:
896*c4762a1bSJed Brown       suffix: fieldsplit_mumps
897*c4762a1bSJed Brown       nsize: 2
898*c4762a1bSJed Brown       requires: mumps
899*c4762a1bSJed Brown       args: -pc_type fieldsplit -pc_fieldsplit_block_size 4 -pc_fieldsplit_type SCHUR -pc_fieldsplit_0_fields 0,1,2 -pc_fieldsplit_1_fields 3 -fieldsplit_0_pc_type lu -fieldsplit_1_pc_type lu -snes_monitor_short -ksp_monitor_short -fieldsplit_0_pc_factor_mat_solver_type mumps -fieldsplit_1_pc_factor_mat_solver_type mumps
900*c4762a1bSJed Brown       output_file: output/ex19_fieldsplit_5.out
901*c4762a1bSJed Brown 
902*c4762a1bSJed Brown    test:
903*c4762a1bSJed Brown       suffix: greedy_coloring
904*c4762a1bSJed Brown       nsize: 2
905*c4762a1bSJed Brown       args: -da_refine 3 -snes_monitor_short -snes_fd_color -snes_fd_color_use_mat -mat_coloring_type greedy -mat_coloring_weight_type lf -mat_coloring_view> ex19_greedy_coloring.tmp 2>&1
906*c4762a1bSJed Brown       requires: !single
907*c4762a1bSJed Brown 
908*c4762a1bSJed Brown    # HYPRE PtAP broken with complex numbers
909*c4762a1bSJed Brown    test:
910*c4762a1bSJed Brown       suffix: hypre
911*c4762a1bSJed Brown       nsize: 2
912*c4762a1bSJed Brown       requires: hypre !complex
913*c4762a1bSJed Brown       args: -da_refine 3 -snes_monitor_short -pc_type hypre
914*c4762a1bSJed Brown 
915*c4762a1bSJed Brown    test:
916*c4762a1bSJed Brown       suffix: ibcgs
917*c4762a1bSJed Brown       nsize: 2
918*c4762a1bSJed Brown       args: -ksp_type ibcgs -ksp_monitor_short -da_refine 2 -snes_view
919*c4762a1bSJed Brown       requires: !complex !single
920*c4762a1bSJed Brown 
921*c4762a1bSJed Brown    test:
922*c4762a1bSJed Brown       suffix: kaczmarz
923*c4762a1bSJed Brown       nsize: 2
924*c4762a1bSJed Brown       args: -pc_type kaczmarz -ksp_monitor_short -snes_monitor_short -snes_view
925*c4762a1bSJed Brown       requires: !single
926*c4762a1bSJed Brown 
927*c4762a1bSJed Brown    test:
928*c4762a1bSJed Brown       suffix: klu
929*c4762a1bSJed Brown       requires: suitesparse
930*c4762a1bSJed Brown       args: -da_grid_x 20 -da_grid_y 20 -pc_type lu -pc_factor_mat_solver_type klu
931*c4762a1bSJed Brown       output_file: output/ex19_superlu.out
932*c4762a1bSJed Brown 
933*c4762a1bSJed Brown    test:
934*c4762a1bSJed Brown       suffix: klu_2
935*c4762a1bSJed Brown       requires: suitesparse
936*c4762a1bSJed Brown       args: -da_grid_x 20 -da_grid_y 20 -pc_type lu -pc_factor_mat_solver_type klu -mat_klu_ordering PETSC
937*c4762a1bSJed Brown       output_file: output/ex19_superlu.out
938*c4762a1bSJed Brown 
939*c4762a1bSJed Brown    test:
940*c4762a1bSJed Brown       suffix: klu_3
941*c4762a1bSJed Brown       requires: suitesparse
942*c4762a1bSJed Brown       args: -da_grid_x 20 -da_grid_y 20 -pc_type lu -pc_factor_mat_solver_type klu -mat_klu_use_btf 0
943*c4762a1bSJed Brown       output_file: output/ex19_superlu.out
944*c4762a1bSJed Brown 
945*c4762a1bSJed Brown    test:
946*c4762a1bSJed Brown       suffix: ml
947*c4762a1bSJed Brown       nsize: 2
948*c4762a1bSJed Brown       requires: ml
949*c4762a1bSJed Brown       args: -da_refine 3 -snes_monitor_short -pc_type ml
950*c4762a1bSJed Brown 
951*c4762a1bSJed Brown    test:
952*c4762a1bSJed Brown       suffix: ngmres_fas
953*c4762a1bSJed Brown       args: -da_refine 4 -snes_monitor_short -snes_type ngmres -npc_fas_levels_snes_type ngs -npc_fas_levels_snes_ngs_sweeps 3 -npc_fas_levels_snes_ngs_atol 0.0 -npc_fas_levels_snes_ngs_stol 0.0 -npc_snes_type fas -npc_fas_levels_snes_type ngs -npc_snes_max_it 1 -npc_snes_fas_smoothup 6 -npc_snes_fas_smoothdown 6 -lidvelocity 100 -grashof 4e4
954*c4762a1bSJed Brown       requires: !single
955*c4762a1bSJed Brown 
956*c4762a1bSJed Brown    test:
957*c4762a1bSJed Brown       suffix: ngmres_fas_gssecant
958*c4762a1bSJed Brown       args: -da_refine 3 -snes_monitor_short -snes_type ngmres -npc_snes_type fas -npc_fas_levels_snes_type ngs -npc_fas_levels_snes_max_it 6 -npc_fas_levels_snes_ngs_secant -npc_fas_levels_snes_ngs_max_it 1 -npc_fas_coarse_snes_max_it 1 -lidvelocity 100 -grashof 4e4
959*c4762a1bSJed Brown       requires: !single
960*c4762a1bSJed Brown 
961*c4762a1bSJed Brown    test:
962*c4762a1bSJed Brown       suffix: ngmres_fas_ms
963*c4762a1bSJed Brown       nsize: 2
964*c4762a1bSJed Brown       args: -snes_grid_sequence 2 -lidvelocity 200 -grashof 1e4 -snes_monitor_short -snes_view -snes_converged_reason -snes_type ngmres -npc_snes_type fas -npc_fas_coarse_snes_type newtonls -npc_fas_coarse_ksp_type preonly -npc_snes_max_it 1
965*c4762a1bSJed Brown       requires: !single
966*c4762a1bSJed Brown 
967*c4762a1bSJed Brown    test:
968*c4762a1bSJed Brown       suffix: ngmres_nasm
969*c4762a1bSJed Brown       nsize: 4
970*c4762a1bSJed Brown       args: -da_refine 4 -da_overlap 2 -snes_monitor_short -snes_type ngmres -snes_max_it 10 -npc_snes_type nasm -npc_snes_nasm_type basic -grashof 4e4 -lidvelocity 100
971*c4762a1bSJed Brown       requires: !single
972*c4762a1bSJed Brown 
973*c4762a1bSJed Brown    test:
974*c4762a1bSJed Brown       suffix: ngs
975*c4762a1bSJed Brown       args: -snes_type ngs -snes_view -snes_monitor -snes_rtol 1e-4
976*c4762a1bSJed Brown       requires: !single
977*c4762a1bSJed Brown 
978*c4762a1bSJed Brown    test:
979*c4762a1bSJed Brown       suffix: ngs_fd
980*c4762a1bSJed Brown       args: -snes_type ngs -snes_ngs_secant -snes_view -snes_monitor -snes_rtol 1e-4
981*c4762a1bSJed Brown       requires: !single
982*c4762a1bSJed Brown 
983*c4762a1bSJed Brown    test:
984*c4762a1bSJed Brown       suffix: parms
985*c4762a1bSJed Brown       nsize: 2
986*c4762a1bSJed Brown       requires: parms
987*c4762a1bSJed Brown       args: -pc_type parms -ksp_monitor_short -snes_view
988*c4762a1bSJed Brown 
989*c4762a1bSJed Brown    test:
990*c4762a1bSJed Brown       suffix: superlu
991*c4762a1bSJed Brown       requires: superlu
992*c4762a1bSJed Brown       args: -da_grid_x 20 -da_grid_y 20 -pc_type lu -pc_factor_mat_solver_type superlu
993*c4762a1bSJed Brown 
994*c4762a1bSJed Brown    test:
995*c4762a1bSJed Brown       suffix: superlu_sell
996*c4762a1bSJed Brown       requires: superlu
997*c4762a1bSJed Brown       args: -da_grid_x 20 -da_grid_y 20 -pc_type lu -pc_factor_mat_solver_type superlu -dm_mat_type sell -pc_factor_mat_ordering_type natural
998*c4762a1bSJed Brown       output_file: output/ex19_superlu.out
999*c4762a1bSJed Brown 
1000*c4762a1bSJed Brown    test:
1001*c4762a1bSJed Brown       suffix: superlu_dist
1002*c4762a1bSJed Brown       requires: superlu_dist
1003*c4762a1bSJed Brown       args: -da_grid_x 20 -da_grid_y 20 -pc_type lu -pc_factor_mat_solver_type superlu_dist
1004*c4762a1bSJed Brown       output_file: output/ex19_superlu.out
1005*c4762a1bSJed Brown 
1006*c4762a1bSJed Brown    test:
1007*c4762a1bSJed Brown       suffix: superlu_dist_2
1008*c4762a1bSJed Brown       nsize: 2
1009*c4762a1bSJed Brown       requires: superlu_dist
1010*c4762a1bSJed Brown       args: -da_grid_x 20 -da_grid_y 20 -pc_type lu -pc_factor_mat_solver_type superlu_dist
1011*c4762a1bSJed Brown       output_file: output/ex19_superlu.out
1012*c4762a1bSJed Brown 
1013*c4762a1bSJed Brown    test:
1014*c4762a1bSJed Brown       suffix: superlu_equil
1015*c4762a1bSJed Brown       requires: superlu
1016*c4762a1bSJed Brown       args: -da_grid_x 20 -da_grid_y 20 -{snes,ksp}_monitor_short -pc_type lu -pc_factor_mat_solver_type superlu -mat_superlu_equil
1017*c4762a1bSJed Brown 
1018*c4762a1bSJed Brown    test:
1019*c4762a1bSJed Brown       suffix: superlu_equil_sell
1020*c4762a1bSJed Brown       requires: superlu
1021*c4762a1bSJed Brown       args: -da_grid_x 20 -da_grid_y 20 -{snes,ksp}_monitor_short -pc_type lu -pc_factor_mat_solver_type superlu -mat_superlu_equil -dm_mat_type sell -pc_factor_mat_ordering_type natural
1022*c4762a1bSJed Brown       output_file: output/ex19_superlu_equil.out
1023*c4762a1bSJed Brown 
1024*c4762a1bSJed Brown    test:
1025*c4762a1bSJed Brown       suffix: tcqmr
1026*c4762a1bSJed Brown       args: -da_refine 1 -ksp_monitor_short -ksp_type tcqmr
1027*c4762a1bSJed Brown       requires: !single
1028*c4762a1bSJed Brown 
1029*c4762a1bSJed Brown    test:
1030*c4762a1bSJed Brown       suffix: tfqmr
1031*c4762a1bSJed Brown       args: -da_refine 1 -ksp_monitor_short -ksp_type tfqmr
1032*c4762a1bSJed Brown       requires: !single
1033*c4762a1bSJed Brown 
1034*c4762a1bSJed Brown    test:
1035*c4762a1bSJed Brown       suffix: umfpack
1036*c4762a1bSJed Brown       requires: suitesparse
1037*c4762a1bSJed Brown       args: -da_refine 2 -pc_type lu -pc_factor_mat_solver_type umfpack -snes_view -snes_monitor_short -ksp_monitor_short
1038*c4762a1bSJed Brown 
1039*c4762a1bSJed Brown    test:
1040*c4762a1bSJed Brown       suffix: tut_1
1041*c4762a1bSJed Brown       nsize: 4
1042*c4762a1bSJed Brown       requires: !single
1043*c4762a1bSJed Brown       args: -da_refine 5 -snes_monitor -ksp_monitor -snes_view
1044*c4762a1bSJed Brown 
1045*c4762a1bSJed Brown    test:
1046*c4762a1bSJed Brown       suffix: tut_2
1047*c4762a1bSJed Brown       nsize: 4
1048*c4762a1bSJed Brown       requires: !single
1049*c4762a1bSJed Brown       args: -da_refine 5 -snes_monitor -ksp_monitor -snes_view -pc_type mg
1050*c4762a1bSJed Brown 
1051*c4762a1bSJed Brown    # HYPRE PtAP broken with complex numbers
1052*c4762a1bSJed Brown    test:
1053*c4762a1bSJed Brown       suffix: tut_3
1054*c4762a1bSJed Brown       nsize: 4
1055*c4762a1bSJed Brown       requires: hypre !single !complex
1056*c4762a1bSJed Brown       args: -da_refine 5 -snes_monitor -ksp_monitor -snes_view -pc_type hypre
1057*c4762a1bSJed Brown 
1058*c4762a1bSJed Brown    test:
1059*c4762a1bSJed Brown       suffix: tut_8
1060*c4762a1bSJed Brown       nsize: 4
1061*c4762a1bSJed Brown       requires: ml !single
1062*c4762a1bSJed Brown       args: -da_refine 5 -snes_monitor -ksp_monitor -snes_view -pc_type ml
1063*c4762a1bSJed Brown 
1064*c4762a1bSJed Brown    test:
1065*c4762a1bSJed Brown       suffix: tut_4
1066*c4762a1bSJed Brown       nsize: 1
1067*c4762a1bSJed Brown       requires: !single
1068*c4762a1bSJed Brown       args: -da_refine 5 -log_view
1069*c4762a1bSJed Brown       filter: head -n 2
1070*c4762a1bSJed Brown       filter_output: head -n 2
1071*c4762a1bSJed Brown 
1072*c4762a1bSJed Brown    test:
1073*c4762a1bSJed Brown       suffix: tut_5
1074*c4762a1bSJed Brown       nsize: 1
1075*c4762a1bSJed Brown       requires: !single
1076*c4762a1bSJed Brown       args: -da_refine 5 -log_view -pc_type mg
1077*c4762a1bSJed Brown       filter: head -n 2
1078*c4762a1bSJed Brown       filter_output: head -n 2
1079*c4762a1bSJed Brown 
1080*c4762a1bSJed Brown    test:
1081*c4762a1bSJed Brown       suffix: tut_6
1082*c4762a1bSJed Brown       nsize: 4
1083*c4762a1bSJed Brown       requires: !single
1084*c4762a1bSJed Brown       args: -da_refine 5 -log_view
1085*c4762a1bSJed Brown       filter: head -n 2
1086*c4762a1bSJed Brown       filter_output: head -n 2
1087*c4762a1bSJed Brown 
1088*c4762a1bSJed Brown    test:
1089*c4762a1bSJed Brown       suffix: tut_7
1090*c4762a1bSJed Brown       nsize: 4
1091*c4762a1bSJed Brown       requires: !single
1092*c4762a1bSJed Brown       args: -da_refine 5 -log_view -pc_type mg
1093*c4762a1bSJed Brown       filter: head -n 2
1094*c4762a1bSJed Brown       filter_output: head -n 2
1095*c4762a1bSJed Brown 
1096*c4762a1bSJed Brown    test:
1097*c4762a1bSJed Brown       suffix: cuda_1
1098*c4762a1bSJed Brown       nsize: 1
1099*c4762a1bSJed Brown       requires: cuda
1100*c4762a1bSJed Brown       args: -snes_monitor -dm_mat_type seqaijcusparse -dm_vec_type seqcuda -pc_type gamg -ksp_monitor -mg_levels_ksp_max_it 3
1101*c4762a1bSJed Brown 
1102*c4762a1bSJed Brown 
1103*c4762a1bSJed Brown    test:
1104*c4762a1bSJed Brown       suffix: cuda_2
1105*c4762a1bSJed Brown       nsize: 3
1106*c4762a1bSJed Brown       requires: cuda !single
1107*c4762a1bSJed Brown       args: -snes_monitor -dm_mat_type mpiaijcusparse -dm_vec_type mpicuda -pc_type gamg -ksp_monitor  -mg_levels_ksp_max_it 3
1108*c4762a1bSJed Brown 
1109*c4762a1bSJed Brown    test:
1110*c4762a1bSJed Brown       suffix: seqbaijmkl
1111*c4762a1bSJed Brown       nsize: 1
1112*c4762a1bSJed Brown       requires: define(PETSC_HAVE_MKL_SPARSE_OPTIMIZE)
1113*c4762a1bSJed Brown       args: -dm_mat_type baij -snes_monitor -ksp_monitor -snes_view
1114*c4762a1bSJed Brown 
1115*c4762a1bSJed Brown    test:
1116*c4762a1bSJed Brown       suffix: mpibaijmkl
1117*c4762a1bSJed Brown       nsize: 2
1118*c4762a1bSJed Brown       requires:  define(PETSC_HAVE_MKL_SPARSE_OPTIMIZE)
1119*c4762a1bSJed Brown       args: -dm_mat_type baij -snes_monitor -ksp_monitor -snes_view
1120*c4762a1bSJed Brown 
1121*c4762a1bSJed Brown    test:
1122*c4762a1bSJed Brown      suffix: cpardiso
1123*c4762a1bSJed Brown      nsize: 4
1124*c4762a1bSJed Brown      requires: mkl_cpardiso
1125*c4762a1bSJed Brown      args: -pc_type lu -pc_factor_mat_solver_type mkl_cpardiso -ksp_monitor
1126*c4762a1bSJed Brown 
1127*c4762a1bSJed Brown    test:
1128*c4762a1bSJed Brown      suffix: logviewmemory
1129*c4762a1bSJed Brown      requires: define(PETSC_USE_LOG) !define(PETSC_HAVE_VALGRIND)
1130*c4762a1bSJed Brown      args: -log_view -log_view_memory -da_refine 4
1131*c4762a1bSJed Brown      filter: grep MatFDColorSetUp | wc -w | xargs  -I % sh -c "expr % \> 21"
1132*c4762a1bSJed Brown 
1133*c4762a1bSJed Brown TEST*/
1134