xref: /petsc/src/snes/tutorials/ex5.c (revision 16d037c043d071536f3bb767f544364e1976d58d)
1c4762a1bSJed Brown static char help[] = "Bratu nonlinear PDE in 2d.\n\
2c4762a1bSJed Brown We solve the  Bratu (SFI - solid fuel ignition) problem in a 2D rectangular\n\
3c4762a1bSJed Brown domain, using distributed arrays (DMDAs) to partition the parallel grid.\n\
4c4762a1bSJed Brown The command line options include:\n\
5c4762a1bSJed Brown   -par <parameter>, where <parameter> indicates the problem's nonlinearity\n\
6c4762a1bSJed Brown      problem SFI:  <parameter> = Bratu parameter (0 <= par <= 6.81)\n\n\
7c4762a1bSJed Brown   -m_par/n_par <parameter>, where <parameter> indicates an integer\n \
8c4762a1bSJed Brown       that MMS3 will be evaluated with 2^m_par, 2^n_par";
9c4762a1bSJed Brown 
10c4762a1bSJed Brown /* ------------------------------------------------------------------------
11c4762a1bSJed Brown 
12c4762a1bSJed Brown     Solid Fuel Ignition (SFI) problem.  This problem is modeled by
13c4762a1bSJed Brown     the partial differential equation
14c4762a1bSJed Brown 
15c4762a1bSJed Brown             -Laplacian u - lambda*exp(u) = 0,  0 < x,y < 1,
16c4762a1bSJed Brown 
17c4762a1bSJed Brown     with boundary conditions
18c4762a1bSJed Brown 
19c4762a1bSJed Brown              u = 0  for  x = 0, x = 1, y = 0, y = 1.
20c4762a1bSJed Brown 
21c4762a1bSJed Brown     A finite difference approximation with the usual 5-point stencil
22c4762a1bSJed Brown     is used to discretize the boundary value problem to obtain a nonlinear
23c4762a1bSJed Brown     system of equations.
24c4762a1bSJed Brown 
25c4762a1bSJed Brown       This example shows how geometric multigrid can be run transparently with a nonlinear solver so long
26c4762a1bSJed Brown       as SNESSetDM() is provided. Example usage
27c4762a1bSJed Brown 
28c4762a1bSJed Brown       ./ex5 -pc_type mg -ksp_monitor  -snes_view -pc_mg_levels 3 -pc_mg_galerkin pmat -da_grid_x 17 -da_grid_y 17
29c4762a1bSJed Brown              -mg_levels_ksp_monitor -snes_monitor -mg_levels_pc_type sor -pc_mg_type full
30c4762a1bSJed Brown 
31c4762a1bSJed Brown       or to run with grid sequencing on the nonlinear problem (note that you do not need to provide the number of
32c4762a1bSJed Brown          multigrid levels, it will be determined automatically based on the number of refinements done)
33c4762a1bSJed Brown 
34c4762a1bSJed Brown       ./ex5 -pc_type mg -ksp_monitor  -snes_view -pc_mg_galerkin pmat -snes_grid_sequence 3
35c4762a1bSJed Brown              -mg_levels_ksp_monitor -snes_monitor -mg_levels_pc_type sor -pc_mg_type full
36c4762a1bSJed Brown 
37c4762a1bSJed Brown   ------------------------------------------------------------------------- */
38c4762a1bSJed Brown 
39c4762a1bSJed Brown /*
40c4762a1bSJed Brown    Include "petscdmda.h" so that we can use distributed arrays (DMDAs).
41c4762a1bSJed Brown    Include "petscsnes.h" so that we can use SNES solvers.  Note that this
42c4762a1bSJed Brown */
43c4762a1bSJed Brown #include <petscdm.h>
44c4762a1bSJed Brown #include <petscdmda.h>
45c4762a1bSJed Brown #include <petscsnes.h>
46c4762a1bSJed Brown #include <petscmatlab.h>
47c4762a1bSJed Brown #include <petsc/private/snesimpl.h> /* For SNES_Solve event */
48c4762a1bSJed Brown 
49c4762a1bSJed Brown /*
50c4762a1bSJed Brown    User-defined application context - contains data needed by the
51c4762a1bSJed Brown    application-provided call-back routines, FormJacobianLocal() and
52c4762a1bSJed Brown    FormFunctionLocal().
53c4762a1bSJed Brown */
54c4762a1bSJed Brown typedef struct AppCtx AppCtx;
55c4762a1bSJed Brown struct AppCtx {
56c4762a1bSJed Brown   PetscReal param;          /* test problem parameter */
57c4762a1bSJed Brown   PetscInt  m,n;            /* MMS3 parameters */
58c4762a1bSJed Brown   PetscErrorCode (*mms_solution)(AppCtx*,const DMDACoor2d*,PetscScalar*);
59c4762a1bSJed Brown   PetscErrorCode (*mms_forcing)(AppCtx*,const DMDACoor2d*,PetscScalar*);
60c4762a1bSJed Brown };
61c4762a1bSJed Brown 
62227f9e03SJunchao Zhang /* ------------------------------------------------------------------- */
63c4762a1bSJed Brown /*
64227f9e03SJunchao Zhang    FormInitialGuess - Forms initial approximation.
65227f9e03SJunchao Zhang 
66227f9e03SJunchao Zhang    Input Parameters:
67227f9e03SJunchao Zhang    da - The DM
68227f9e03SJunchao Zhang    user - user-defined application context
69227f9e03SJunchao Zhang 
70227f9e03SJunchao Zhang    Output Parameter:
71227f9e03SJunchao Zhang    X - vector
72c4762a1bSJed Brown  */
73227f9e03SJunchao Zhang static PetscErrorCode FormInitialGuess(DM da,AppCtx *user,Vec X)
74227f9e03SJunchao Zhang {
75227f9e03SJunchao Zhang   PetscInt       i,j,Mx,My,xs,ys,xm,ym;
76227f9e03SJunchao Zhang   PetscReal      lambda,temp1,temp,hx,hy;
77227f9e03SJunchao Zhang   PetscScalar    **x;
78227f9e03SJunchao Zhang 
79227f9e03SJunchao Zhang   PetscFunctionBeginUser;
80227f9e03SJunchao Zhang   PetscCall(DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE));
81227f9e03SJunchao Zhang 
82227f9e03SJunchao Zhang   lambda = user->param;
83227f9e03SJunchao Zhang   hx     = 1.0/(PetscReal)(Mx-1);
84227f9e03SJunchao Zhang   hy     = 1.0/(PetscReal)(My-1);
85227f9e03SJunchao Zhang   temp1  = lambda/(lambda + 1.0);
86227f9e03SJunchao Zhang 
87227f9e03SJunchao Zhang   /*
88227f9e03SJunchao Zhang      Get a pointer to vector data.
89227f9e03SJunchao Zhang        - For default PETSc vectors, VecGetArray() returns a pointer to
90227f9e03SJunchao Zhang          the data array.  Otherwise, the routine is implementation dependent.
91227f9e03SJunchao Zhang        - You MUST call VecRestoreArray() when you no longer need access to
92227f9e03SJunchao Zhang          the array.
93227f9e03SJunchao Zhang   */
94227f9e03SJunchao Zhang   PetscCall(DMDAVecGetArray(da,X,&x));
95227f9e03SJunchao Zhang 
96227f9e03SJunchao Zhang   /*
97227f9e03SJunchao Zhang      Get local grid boundaries (for 2-dimensional DMDA):
98227f9e03SJunchao Zhang        xs, ys   - starting grid indices (no ghost points)
99227f9e03SJunchao Zhang        xm, ym   - widths of local grid (no ghost points)
100227f9e03SJunchao Zhang 
101227f9e03SJunchao Zhang   */
102227f9e03SJunchao Zhang   PetscCall(DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL));
103227f9e03SJunchao Zhang 
104227f9e03SJunchao Zhang   /*
105227f9e03SJunchao Zhang      Compute initial guess over the locally owned part of the grid
106227f9e03SJunchao Zhang   */
107227f9e03SJunchao Zhang   for (j=ys; j<ys+ym; j++) {
108227f9e03SJunchao Zhang     temp = (PetscReal)(PetscMin(j,My-j-1))*hy;
109227f9e03SJunchao Zhang     for (i=xs; i<xs+xm; i++) {
110227f9e03SJunchao Zhang       if (i == 0 || j == 0 || i == Mx-1 || j == My-1) {
111227f9e03SJunchao Zhang         /* boundary conditions are all zero Dirichlet */
112227f9e03SJunchao Zhang         x[j][i] = 0.0;
113227f9e03SJunchao Zhang       } else {
114227f9e03SJunchao Zhang         x[j][i] = temp1*PetscSqrtReal(PetscMin((PetscReal)(PetscMin(i,Mx-i-1))*hx,temp));
115227f9e03SJunchao Zhang       }
116227f9e03SJunchao Zhang     }
117227f9e03SJunchao Zhang   }
118227f9e03SJunchao Zhang 
119227f9e03SJunchao Zhang   /*
120227f9e03SJunchao Zhang      Restore vector
121227f9e03SJunchao Zhang   */
122227f9e03SJunchao Zhang   PetscCall(DMDAVecRestoreArray(da,X,&x));
123227f9e03SJunchao Zhang   PetscFunctionReturn(0);
124227f9e03SJunchao Zhang }
125227f9e03SJunchao Zhang 
126227f9e03SJunchao Zhang /*
127227f9e03SJunchao Zhang   FormExactSolution - Forms MMS solution
128227f9e03SJunchao Zhang 
129227f9e03SJunchao Zhang   Input Parameters:
130227f9e03SJunchao Zhang   da - The DM
131227f9e03SJunchao Zhang   user - user-defined application context
132227f9e03SJunchao Zhang 
133227f9e03SJunchao Zhang   Output Parameter:
134227f9e03SJunchao Zhang   X - vector
135227f9e03SJunchao Zhang  */
136227f9e03SJunchao Zhang static PetscErrorCode FormExactSolution(DM da, AppCtx *user, Vec U)
137227f9e03SJunchao Zhang {
138227f9e03SJunchao Zhang   DM             coordDA;
139227f9e03SJunchao Zhang   Vec            coordinates;
140227f9e03SJunchao Zhang   DMDACoor2d   **coords;
141227f9e03SJunchao Zhang   PetscScalar  **u;
142227f9e03SJunchao Zhang   PetscInt       xs, ys, xm, ym, i, j;
143227f9e03SJunchao Zhang 
144227f9e03SJunchao Zhang   PetscFunctionBeginUser;
145227f9e03SJunchao Zhang   PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &xm, &ym, NULL));
146227f9e03SJunchao Zhang   PetscCall(DMGetCoordinateDM(da, &coordDA));
147227f9e03SJunchao Zhang   PetscCall(DMGetCoordinates(da, &coordinates));
148227f9e03SJunchao Zhang   PetscCall(DMDAVecGetArray(coordDA, coordinates, &coords));
149227f9e03SJunchao Zhang   PetscCall(DMDAVecGetArray(da, U, &u));
150227f9e03SJunchao Zhang   for (j = ys; j < ys+ym; ++j) {
151227f9e03SJunchao Zhang     for (i = xs; i < xs+xm; ++i) {
152227f9e03SJunchao Zhang       user->mms_solution(user,&coords[j][i],&u[j][i]);
153227f9e03SJunchao Zhang     }
154227f9e03SJunchao Zhang   }
155227f9e03SJunchao Zhang   PetscCall(DMDAVecRestoreArray(da, U, &u));
156227f9e03SJunchao Zhang   PetscCall(DMDAVecRestoreArray(coordDA, coordinates, &coords));
157227f9e03SJunchao Zhang   PetscFunctionReturn(0);
158227f9e03SJunchao Zhang }
159227f9e03SJunchao Zhang 
160227f9e03SJunchao Zhang static PetscErrorCode ZeroBCSolution(AppCtx *user,const DMDACoor2d *c,PetscScalar *u)
161227f9e03SJunchao Zhang {
162227f9e03SJunchao Zhang   u[0] = 0.;
163227f9e03SJunchao Zhang   return 0;
164227f9e03SJunchao Zhang }
165227f9e03SJunchao Zhang 
166227f9e03SJunchao Zhang /* The functions below evaluate the MMS solution u(x,y) and associated forcing
167227f9e03SJunchao Zhang 
168227f9e03SJunchao Zhang      f(x,y) = -u_xx - u_yy - lambda exp(u)
169227f9e03SJunchao Zhang 
170227f9e03SJunchao Zhang   such that u(x,y) is an exact solution with f(x,y) as the right hand side forcing term.
171227f9e03SJunchao Zhang  */
172227f9e03SJunchao Zhang static PetscErrorCode MMSSolution1(AppCtx *user,const DMDACoor2d *c,PetscScalar *u)
173227f9e03SJunchao Zhang {
174227f9e03SJunchao Zhang   PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y);
175227f9e03SJunchao Zhang   u[0] = x*(1 - x)*y*(1 - y);
176227f9e03SJunchao Zhang   PetscLogFlops(5);
177227f9e03SJunchao Zhang   return 0;
178227f9e03SJunchao Zhang }
179227f9e03SJunchao Zhang static PetscErrorCode MMSForcing1(AppCtx *user,const DMDACoor2d *c,PetscScalar *f)
180227f9e03SJunchao Zhang {
181227f9e03SJunchao Zhang   PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y);
182227f9e03SJunchao Zhang   f[0] = 2*x*(1 - x) + 2*y*(1 - y) - user->param*PetscExpReal(x*(1 - x)*y*(1 - y));
183227f9e03SJunchao Zhang   return 0;
184227f9e03SJunchao Zhang }
185227f9e03SJunchao Zhang 
186227f9e03SJunchao Zhang static PetscErrorCode MMSSolution2(AppCtx *user,const DMDACoor2d *c,PetscScalar *u)
187227f9e03SJunchao Zhang {
188227f9e03SJunchao Zhang   PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y);
189227f9e03SJunchao Zhang   u[0] = PetscSinReal(PETSC_PI*x)*PetscSinReal(PETSC_PI*y);
190227f9e03SJunchao Zhang   PetscLogFlops(5);
191227f9e03SJunchao Zhang   return 0;
192227f9e03SJunchao Zhang }
193227f9e03SJunchao Zhang static PetscErrorCode MMSForcing2(AppCtx *user,const DMDACoor2d *c,PetscScalar *f)
194227f9e03SJunchao Zhang {
195227f9e03SJunchao Zhang   PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y);
196227f9e03SJunchao Zhang   f[0] = 2*PetscSqr(PETSC_PI)*PetscSinReal(PETSC_PI*x)*PetscSinReal(PETSC_PI*y) - user->param*PetscExpReal(PetscSinReal(PETSC_PI*x)*PetscSinReal(PETSC_PI*y));
197227f9e03SJunchao Zhang   return 0;
198227f9e03SJunchao Zhang }
199227f9e03SJunchao Zhang 
200227f9e03SJunchao Zhang static PetscErrorCode MMSSolution3(AppCtx *user,const DMDACoor2d *c,PetscScalar *u)
201227f9e03SJunchao Zhang {
202227f9e03SJunchao Zhang   PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y);
203227f9e03SJunchao Zhang   u[0] = PetscSinReal(user->m*PETSC_PI*x*(1-y))*PetscSinReal(user->n*PETSC_PI*y*(1-x));
204227f9e03SJunchao Zhang   PetscLogFlops(5);
205227f9e03SJunchao Zhang   return 0;
206227f9e03SJunchao Zhang }
207227f9e03SJunchao Zhang static PetscErrorCode MMSForcing3(AppCtx *user,const DMDACoor2d *c,PetscScalar *f)
208227f9e03SJunchao Zhang {
209227f9e03SJunchao Zhang   PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y);
210227f9e03SJunchao Zhang   PetscReal m = user->m, n = user->n, lambda = user->param;
211227f9e03SJunchao Zhang   f[0] = (-(PetscExpReal(PetscSinReal(m*PETSC_PI*x*(1 - y))*PetscSinReal(n*PETSC_PI*(1 - x)*y))*lambda)
212227f9e03SJunchao Zhang           + PetscSqr(PETSC_PI)*(-2*m*n*((-1 + x)*x + (-1 + y)*y)*PetscCosReal(m*PETSC_PI*x*(-1 + y))*PetscCosReal(n*PETSC_PI*(-1 + x)*y)
213227f9e03SJunchao Zhang                                 + (PetscSqr(m)*(PetscSqr(x) + PetscSqr(-1 + y)) + PetscSqr(n)*(PetscSqr(-1 + x) + PetscSqr(y)))
214227f9e03SJunchao Zhang                                 *PetscSinReal(m*PETSC_PI*x*(-1 + y))*PetscSinReal(n*PETSC_PI*(-1 + x)*y)));
215227f9e03SJunchao Zhang   return 0;
216227f9e03SJunchao Zhang }
217227f9e03SJunchao Zhang 
218227f9e03SJunchao Zhang static PetscErrorCode MMSSolution4(AppCtx *user,const DMDACoor2d *c,PetscScalar *u)
219227f9e03SJunchao Zhang {
220227f9e03SJunchao Zhang   const PetscReal Lx = 1.,Ly = 1.;
221227f9e03SJunchao Zhang   PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y);
222227f9e03SJunchao Zhang   u[0] = (PetscPowReal(x,4)-PetscSqr(Lx)*PetscSqr(x))*(PetscPowReal(y,4)-PetscSqr(Ly)*PetscSqr(y));
223227f9e03SJunchao Zhang   PetscLogFlops(9);
224227f9e03SJunchao Zhang   return 0;
225227f9e03SJunchao Zhang }
226227f9e03SJunchao Zhang static PetscErrorCode MMSForcing4(AppCtx *user,const DMDACoor2d *c,PetscScalar *f)
227227f9e03SJunchao Zhang {
228227f9e03SJunchao Zhang   const PetscReal Lx = 1.,Ly = 1.;
229227f9e03SJunchao Zhang   PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y);
230227f9e03SJunchao Zhang   f[0] = (2*PetscSqr(x)*(PetscSqr(x)-PetscSqr(Lx))*(PetscSqr(Ly)-6*PetscSqr(y))
231227f9e03SJunchao Zhang           + 2*PetscSqr(y)*(PetscSqr(Lx)-6*PetscSqr(x))*(PetscSqr(y)-PetscSqr(Ly))
232227f9e03SJunchao Zhang           - user->param*PetscExpReal((PetscPowReal(x,4)-PetscSqr(Lx)*PetscSqr(x))*(PetscPowReal(y,4)-PetscSqr(Ly)*PetscSqr(y))));
233227f9e03SJunchao Zhang   return 0;
234227f9e03SJunchao Zhang }
235227f9e03SJunchao Zhang 
236227f9e03SJunchao Zhang /* ------------------------------------------------------------------- */
237227f9e03SJunchao Zhang /*
238227f9e03SJunchao Zhang    FormFunctionLocal - Evaluates nonlinear function, F(x) on local process patch
239227f9e03SJunchao Zhang 
240227f9e03SJunchao Zhang  */
241227f9e03SJunchao Zhang static PetscErrorCode FormFunctionLocal(DMDALocalInfo *info,PetscScalar **x,PetscScalar **f,AppCtx *user)
242227f9e03SJunchao Zhang {
243227f9e03SJunchao Zhang   PetscInt       i,j;
244227f9e03SJunchao Zhang   PetscReal      lambda,hx,hy,hxdhy,hydhx;
245227f9e03SJunchao Zhang   PetscScalar    u,ue,uw,un,us,uxx,uyy,mms_solution,mms_forcing;
246227f9e03SJunchao Zhang   DMDACoor2d     c;
247227f9e03SJunchao Zhang 
248227f9e03SJunchao Zhang   PetscFunctionBeginUser;
249227f9e03SJunchao Zhang   lambda = user->param;
250227f9e03SJunchao Zhang   hx     = 1.0/(PetscReal)(info->mx-1);
251227f9e03SJunchao Zhang   hy     = 1.0/(PetscReal)(info->my-1);
252227f9e03SJunchao Zhang   hxdhy  = hx/hy;
253227f9e03SJunchao Zhang   hydhx  = hy/hx;
254227f9e03SJunchao Zhang   /*
255227f9e03SJunchao Zhang      Compute function over the locally owned part of the grid
256227f9e03SJunchao Zhang   */
257227f9e03SJunchao Zhang   for (j=info->ys; j<info->ys+info->ym; j++) {
258227f9e03SJunchao Zhang     for (i=info->xs; i<info->xs+info->xm; i++) {
259227f9e03SJunchao Zhang       if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) {
260227f9e03SJunchao Zhang         c.x = i*hx; c.y = j*hy;
261227f9e03SJunchao Zhang         PetscCall(user->mms_solution(user,&c,&mms_solution));
262227f9e03SJunchao Zhang         f[j][i] = 2.0*(hydhx+hxdhy)*(x[j][i] - mms_solution);
263227f9e03SJunchao Zhang       } else {
264227f9e03SJunchao Zhang         u  = x[j][i];
265227f9e03SJunchao Zhang         uw = x[j][i-1];
266227f9e03SJunchao Zhang         ue = x[j][i+1];
267227f9e03SJunchao Zhang         un = x[j-1][i];
268227f9e03SJunchao Zhang         us = x[j+1][i];
269227f9e03SJunchao Zhang 
270227f9e03SJunchao Zhang         /* Enforce boundary conditions at neighboring points -- setting these values causes the Jacobian to be symmetric. */
271227f9e03SJunchao Zhang         if (i-1 == 0) {c.x = (i-1)*hx; c.y = j*hy; PetscCall(user->mms_solution(user,&c,&uw));}
272227f9e03SJunchao Zhang         if (i+1 == info->mx-1) {c.x = (i+1)*hx; c.y = j*hy; PetscCall(user->mms_solution(user,&c,&ue));}
273227f9e03SJunchao Zhang         if (j-1 == 0) {c.x = i*hx; c.y = (j-1)*hy; PetscCall(user->mms_solution(user,&c,&un));}
274227f9e03SJunchao Zhang         if (j+1 == info->my-1) {c.x = i*hx; c.y = (j+1)*hy; PetscCall(user->mms_solution(user,&c,&us));}
275227f9e03SJunchao Zhang 
276227f9e03SJunchao Zhang         uxx     = (2.0*u - uw - ue)*hydhx;
277227f9e03SJunchao Zhang         uyy     = (2.0*u - un - us)*hxdhy;
278227f9e03SJunchao Zhang         mms_forcing = 0;
279227f9e03SJunchao Zhang         c.x = i*hx; c.y = j*hy;
280227f9e03SJunchao Zhang         if (user->mms_forcing) PetscCall(user->mms_forcing(user,&c,&mms_forcing));
281227f9e03SJunchao Zhang         f[j][i] = uxx + uyy - hx*hy*(lambda*PetscExpScalar(u) + mms_forcing);
282227f9e03SJunchao Zhang       }
283227f9e03SJunchao Zhang     }
284227f9e03SJunchao Zhang   }
285227f9e03SJunchao Zhang   PetscCall(PetscLogFlops(11.0*info->ym*info->xm));
286227f9e03SJunchao Zhang   PetscFunctionReturn(0);
287227f9e03SJunchao Zhang }
288227f9e03SJunchao Zhang 
289227f9e03SJunchao Zhang /* FormObjectiveLocal - Evaluates nonlinear function, F(x) on local process patch */
290227f9e03SJunchao Zhang static PetscErrorCode FormObjectiveLocal(DMDALocalInfo *info,PetscScalar **x,PetscReal *obj,AppCtx *user)
291227f9e03SJunchao Zhang {
292227f9e03SJunchao Zhang   PetscInt       i,j;
293227f9e03SJunchao Zhang   PetscReal      lambda,hx,hy,hxdhy,hydhx,sc,lobj=0;
294227f9e03SJunchao Zhang   PetscScalar    u,ue,uw,un,us,uxux,uyuy;
295227f9e03SJunchao Zhang   MPI_Comm       comm;
296227f9e03SJunchao Zhang 
297227f9e03SJunchao Zhang   PetscFunctionBeginUser;
298227f9e03SJunchao Zhang   *obj   = 0;
299227f9e03SJunchao Zhang   PetscCall(PetscObjectGetComm((PetscObject)info->da,&comm));
300227f9e03SJunchao Zhang   lambda = user->param;
301227f9e03SJunchao Zhang   hx     = 1.0/(PetscReal)(info->mx-1);
302227f9e03SJunchao Zhang   hy     = 1.0/(PetscReal)(info->my-1);
303227f9e03SJunchao Zhang   sc     = hx*hy*lambda;
304227f9e03SJunchao Zhang   hxdhy  = hx/hy;
305227f9e03SJunchao Zhang   hydhx  = hy/hx;
306227f9e03SJunchao Zhang   /*
307227f9e03SJunchao Zhang      Compute function over the locally owned part of the grid
308227f9e03SJunchao Zhang   */
309227f9e03SJunchao Zhang   for (j=info->ys; j<info->ys+info->ym; j++) {
310227f9e03SJunchao Zhang     for (i=info->xs; i<info->xs+info->xm; i++) {
311227f9e03SJunchao Zhang       if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) {
312227f9e03SJunchao Zhang         lobj += PetscRealPart((hydhx + hxdhy)*x[j][i]*x[j][i]);
313227f9e03SJunchao Zhang       } else {
314227f9e03SJunchao Zhang         u  = x[j][i];
315227f9e03SJunchao Zhang         uw = x[j][i-1];
316227f9e03SJunchao Zhang         ue = x[j][i+1];
317227f9e03SJunchao Zhang         un = x[j-1][i];
318227f9e03SJunchao Zhang         us = x[j+1][i];
319227f9e03SJunchao Zhang 
320227f9e03SJunchao Zhang         if (i-1 == 0) uw = 0.;
321227f9e03SJunchao Zhang         if (i+1 == info->mx-1) ue = 0.;
322227f9e03SJunchao Zhang         if (j-1 == 0) un = 0.;
323227f9e03SJunchao Zhang         if (j+1 == info->my-1) us = 0.;
324227f9e03SJunchao Zhang 
325227f9e03SJunchao Zhang         /* F[u] = 1/2\int_{\omega}\nabla^2u(x)*u(x)*dx */
326227f9e03SJunchao Zhang 
327227f9e03SJunchao Zhang         uxux = u*(2.*u - ue - uw)*hydhx;
328227f9e03SJunchao Zhang         uyuy = u*(2.*u - un - us)*hxdhy;
329227f9e03SJunchao Zhang 
330227f9e03SJunchao Zhang         lobj += PetscRealPart(0.5*(uxux + uyuy) - sc*PetscExpScalar(u));
331227f9e03SJunchao Zhang       }
332227f9e03SJunchao Zhang     }
333227f9e03SJunchao Zhang   }
334227f9e03SJunchao Zhang   PetscCall(PetscLogFlops(12.0*info->ym*info->xm));
335227f9e03SJunchao Zhang   PetscCallMPI(MPI_Allreduce(&lobj,obj,1,MPIU_REAL,MPIU_SUM,comm));
336227f9e03SJunchao Zhang   PetscFunctionReturn(0);
337227f9e03SJunchao Zhang }
338227f9e03SJunchao Zhang 
339227f9e03SJunchao Zhang /*
340227f9e03SJunchao Zhang    FormJacobianLocal - Evaluates Jacobian matrix on local process patch
341227f9e03SJunchao Zhang */
342227f9e03SJunchao Zhang static PetscErrorCode FormJacobianLocal(DMDALocalInfo *info,PetscScalar **x,Mat jac,Mat jacpre,AppCtx *user)
343227f9e03SJunchao Zhang {
344227f9e03SJunchao Zhang   PetscInt       i,j,k;
345227f9e03SJunchao Zhang   MatStencil     col[5],row;
346227f9e03SJunchao Zhang   PetscScalar    lambda,v[5],hx,hy,hxdhy,hydhx,sc;
347227f9e03SJunchao Zhang   DM             coordDA;
348227f9e03SJunchao Zhang   Vec            coordinates;
349227f9e03SJunchao Zhang   DMDACoor2d   **coords;
350227f9e03SJunchao Zhang 
351227f9e03SJunchao Zhang   PetscFunctionBeginUser;
352227f9e03SJunchao Zhang   lambda = user->param;
353227f9e03SJunchao Zhang   /* Extract coordinates */
354227f9e03SJunchao Zhang   PetscCall(DMGetCoordinateDM(info->da, &coordDA));
355227f9e03SJunchao Zhang   PetscCall(DMGetCoordinates(info->da, &coordinates));
356227f9e03SJunchao Zhang   PetscCall(DMDAVecGetArray(coordDA, coordinates, &coords));
357227f9e03SJunchao Zhang   hx     = info->xm > 1 ? PetscRealPart(coords[info->ys][info->xs+1].x) - PetscRealPart(coords[info->ys][info->xs].x) : 1.0;
358227f9e03SJunchao Zhang   hy     = info->ym > 1 ? PetscRealPart(coords[info->ys+1][info->xs].y) - PetscRealPart(coords[info->ys][info->xs].y) : 1.0;
359227f9e03SJunchao Zhang   PetscCall(DMDAVecRestoreArray(coordDA, coordinates, &coords));
360227f9e03SJunchao Zhang   hxdhy  = hx/hy;
361227f9e03SJunchao Zhang   hydhx  = hy/hx;
362227f9e03SJunchao Zhang   sc     = hx*hy*lambda;
363227f9e03SJunchao Zhang 
364227f9e03SJunchao Zhang   /*
365227f9e03SJunchao Zhang      Compute entries for the locally owned part of the Jacobian.
366227f9e03SJunchao Zhang       - Currently, all PETSc parallel matrix formats are partitioned by
367227f9e03SJunchao Zhang         contiguous chunks of rows across the processors.
368227f9e03SJunchao Zhang       - Each processor needs to insert only elements that it owns
369227f9e03SJunchao Zhang         locally (but any non-local elements will be sent to the
370227f9e03SJunchao Zhang         appropriate processor during matrix assembly).
371227f9e03SJunchao Zhang       - Here, we set all entries for a particular row at once.
372227f9e03SJunchao Zhang       - We can set matrix entries either using either
373227f9e03SJunchao Zhang         MatSetValuesLocal() or MatSetValues(), as discussed above.
374227f9e03SJunchao Zhang   */
375227f9e03SJunchao Zhang   for (j=info->ys; j<info->ys+info->ym; j++) {
376227f9e03SJunchao Zhang     for (i=info->xs; i<info->xs+info->xm; i++) {
377227f9e03SJunchao Zhang       row.j = j; row.i = i;
378227f9e03SJunchao Zhang       /* boundary points */
379227f9e03SJunchao Zhang       if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) {
380227f9e03SJunchao Zhang         v[0] =  2.0*(hydhx + hxdhy);
381227f9e03SJunchao Zhang         PetscCall(MatSetValuesStencil(jacpre,1,&row,1,&row,v,INSERT_VALUES));
382227f9e03SJunchao Zhang       } else {
383227f9e03SJunchao Zhang         k = 0;
384227f9e03SJunchao Zhang         /* interior grid points */
385227f9e03SJunchao Zhang         if (j-1 != 0) {
386227f9e03SJunchao Zhang           v[k]     = -hxdhy;
387227f9e03SJunchao Zhang           col[k].j = j - 1; col[k].i = i;
388227f9e03SJunchao Zhang           k++;
389227f9e03SJunchao Zhang         }
390227f9e03SJunchao Zhang         if (i-1 != 0) {
391227f9e03SJunchao Zhang           v[k]     = -hydhx;
392227f9e03SJunchao Zhang           col[k].j = j;     col[k].i = i-1;
393227f9e03SJunchao Zhang           k++;
394227f9e03SJunchao Zhang         }
395227f9e03SJunchao Zhang 
396227f9e03SJunchao Zhang         v[k] = 2.0*(hydhx + hxdhy) - sc*PetscExpScalar(x[j][i]); col[k].j = row.j; col[k].i = row.i; k++;
397227f9e03SJunchao Zhang 
398227f9e03SJunchao Zhang         if (i+1 != info->mx-1) {
399227f9e03SJunchao Zhang           v[k]     = -hydhx;
400227f9e03SJunchao Zhang           col[k].j = j;     col[k].i = i+1;
401227f9e03SJunchao Zhang           k++;
402227f9e03SJunchao Zhang         }
403227f9e03SJunchao Zhang         if (j+1 != info->mx-1) {
404227f9e03SJunchao Zhang           v[k]     = -hxdhy;
405227f9e03SJunchao Zhang           col[k].j = j + 1; col[k].i = i;
406227f9e03SJunchao Zhang           k++;
407227f9e03SJunchao Zhang         }
408227f9e03SJunchao Zhang         PetscCall(MatSetValuesStencil(jacpre,1,&row,k,col,v,INSERT_VALUES));
409227f9e03SJunchao Zhang       }
410227f9e03SJunchao Zhang     }
411227f9e03SJunchao Zhang   }
412227f9e03SJunchao Zhang 
413227f9e03SJunchao Zhang   /*
414227f9e03SJunchao Zhang      Assemble matrix, using the 2-step process:
415227f9e03SJunchao Zhang        MatAssemblyBegin(), MatAssemblyEnd().
416227f9e03SJunchao Zhang   */
417227f9e03SJunchao Zhang   PetscCall(MatAssemblyBegin(jacpre,MAT_FINAL_ASSEMBLY));
418227f9e03SJunchao Zhang   PetscCall(MatAssemblyEnd(jacpre,MAT_FINAL_ASSEMBLY));
419227f9e03SJunchao Zhang   /*
420227f9e03SJunchao Zhang      Tell the matrix we will never add a new nonzero location to the
421227f9e03SJunchao Zhang      matrix. If we do, it will generate an error.
422227f9e03SJunchao Zhang   */
423227f9e03SJunchao Zhang   PetscCall(MatSetOption(jac,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE));
424227f9e03SJunchao Zhang   PetscFunctionReturn(0);
425227f9e03SJunchao Zhang }
426227f9e03SJunchao Zhang 
427227f9e03SJunchao Zhang static PetscErrorCode FormFunctionMatlab(SNES snes,Vec X,Vec F,void *ptr)
428227f9e03SJunchao Zhang {
429227f9e03SJunchao Zhang #if PetscDefined(HAVE_MATLAB_ENGINE)
430227f9e03SJunchao Zhang   AppCtx         *user = (AppCtx*)ptr;
431227f9e03SJunchao Zhang   PetscInt       Mx,My;
432227f9e03SJunchao Zhang   PetscReal      lambda,hx,hy;
433227f9e03SJunchao Zhang   Vec            localX,localF;
434227f9e03SJunchao Zhang   MPI_Comm       comm;
435227f9e03SJunchao Zhang   DM             da;
436227f9e03SJunchao Zhang 
437227f9e03SJunchao Zhang   PetscFunctionBeginUser;
438227f9e03SJunchao Zhang   PetscCall(SNESGetDM(snes,&da));
439227f9e03SJunchao Zhang   PetscCall(DMGetLocalVector(da,&localX));
440227f9e03SJunchao Zhang   PetscCall(DMGetLocalVector(da,&localF));
441227f9e03SJunchao Zhang   PetscCall(PetscObjectSetName((PetscObject)localX,"localX"));
442227f9e03SJunchao Zhang   PetscCall(PetscObjectSetName((PetscObject)localF,"localF"));
443227f9e03SJunchao Zhang   PetscCall(DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE));
444227f9e03SJunchao Zhang 
445227f9e03SJunchao Zhang   lambda = user->param;
446227f9e03SJunchao Zhang   hx     = 1.0/(PetscReal)(Mx-1);
447227f9e03SJunchao Zhang   hy     = 1.0/(PetscReal)(My-1);
448227f9e03SJunchao Zhang 
449227f9e03SJunchao Zhang   PetscCall(PetscObjectGetComm((PetscObject)snes,&comm));
450227f9e03SJunchao Zhang   /*
451227f9e03SJunchao Zhang      Scatter ghost points to local vector,using the 2-step process
452227f9e03SJunchao Zhang         DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
453227f9e03SJunchao Zhang      By placing code between these two statements, computations can be
454227f9e03SJunchao Zhang      done while messages are in transition.
455227f9e03SJunchao Zhang   */
456227f9e03SJunchao Zhang   PetscCall(DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX));
457227f9e03SJunchao Zhang   PetscCall(DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX));
458227f9e03SJunchao Zhang   PetscCall(PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(comm),(PetscObject)localX));
459227f9e03SJunchao Zhang   PetscCall(PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(comm),"localF=ex5m(localX,%18.16e,%18.16e,%18.16e)",(double)hx,(double)hy,(double)lambda));
460227f9e03SJunchao Zhang   PetscCall(PetscMatlabEngineGet(PETSC_MATLAB_ENGINE_(comm),(PetscObject)localF));
461227f9e03SJunchao Zhang 
462227f9e03SJunchao Zhang   /*
463227f9e03SJunchao Zhang      Insert values into global vector
464227f9e03SJunchao Zhang   */
465227f9e03SJunchao Zhang   PetscCall(DMLocalToGlobalBegin(da,localF,INSERT_VALUES,F));
466227f9e03SJunchao Zhang   PetscCall(DMLocalToGlobalEnd(da,localF,INSERT_VALUES,F));
467227f9e03SJunchao Zhang   PetscCall(DMRestoreLocalVector(da,&localX));
468227f9e03SJunchao Zhang   PetscCall(DMRestoreLocalVector(da,&localF));
469227f9e03SJunchao Zhang   PetscFunctionReturn(0);
470227f9e03SJunchao Zhang #else
471227f9e03SJunchao Zhang     return 0;                     /* Never called */
472227f9e03SJunchao Zhang #endif
473227f9e03SJunchao Zhang }
474227f9e03SJunchao Zhang 
475227f9e03SJunchao Zhang /* ------------------------------------------------------------------- */
476227f9e03SJunchao Zhang /*
477227f9e03SJunchao Zhang       Applies some sweeps on nonlinear Gauss-Seidel on each process
478227f9e03SJunchao Zhang 
479227f9e03SJunchao Zhang  */
480227f9e03SJunchao Zhang static PetscErrorCode NonlinearGS(SNES snes,Vec X, Vec B, void *ctx)
481227f9e03SJunchao Zhang {
482227f9e03SJunchao Zhang   PetscInt       i,j,k,Mx,My,xs,ys,xm,ym,its,tot_its,sweeps,l;
483227f9e03SJunchao Zhang   PetscReal      lambda,hx,hy,hxdhy,hydhx,sc;
484227f9e03SJunchao Zhang   PetscScalar    **x,**b,bij,F,F0=0,J,u,un,us,ue,eu,uw,uxx,uyy,y;
485227f9e03SJunchao Zhang   PetscReal      atol,rtol,stol;
486227f9e03SJunchao Zhang   DM             da;
487227f9e03SJunchao Zhang   AppCtx         *user;
488227f9e03SJunchao Zhang   Vec            localX,localB;
489227f9e03SJunchao Zhang 
490227f9e03SJunchao Zhang   PetscFunctionBeginUser;
491227f9e03SJunchao Zhang   tot_its = 0;
492227f9e03SJunchao Zhang   PetscCall(SNESNGSGetSweeps(snes,&sweeps));
493227f9e03SJunchao Zhang   PetscCall(SNESNGSGetTolerances(snes,&atol,&rtol,&stol,&its));
494227f9e03SJunchao Zhang   PetscCall(SNESGetDM(snes,&da));
495227f9e03SJunchao Zhang   PetscCall(DMGetApplicationContext(da,&user));
496227f9e03SJunchao Zhang 
497227f9e03SJunchao Zhang   PetscCall(DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE));
498227f9e03SJunchao Zhang 
499227f9e03SJunchao Zhang   lambda = user->param;
500227f9e03SJunchao Zhang   hx     = 1.0/(PetscReal)(Mx-1);
501227f9e03SJunchao Zhang   hy     = 1.0/(PetscReal)(My-1);
502227f9e03SJunchao Zhang   sc     = hx*hy*lambda;
503227f9e03SJunchao Zhang   hxdhy  = hx/hy;
504227f9e03SJunchao Zhang   hydhx  = hy/hx;
505227f9e03SJunchao Zhang 
506227f9e03SJunchao Zhang   PetscCall(DMGetLocalVector(da,&localX));
507227f9e03SJunchao Zhang   if (B) {
508227f9e03SJunchao Zhang     PetscCall(DMGetLocalVector(da,&localB));
509227f9e03SJunchao Zhang   }
510227f9e03SJunchao Zhang   for (l=0; l<sweeps; l++) {
511227f9e03SJunchao Zhang 
512227f9e03SJunchao Zhang     PetscCall(DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX));
513227f9e03SJunchao Zhang     PetscCall(DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX));
514227f9e03SJunchao Zhang     if (B) {
515227f9e03SJunchao Zhang       PetscCall(DMGlobalToLocalBegin(da,B,INSERT_VALUES,localB));
516227f9e03SJunchao Zhang       PetscCall(DMGlobalToLocalEnd(da,B,INSERT_VALUES,localB));
517227f9e03SJunchao Zhang     }
518227f9e03SJunchao Zhang     /*
519227f9e03SJunchao Zhang      Get a pointer to vector data.
520227f9e03SJunchao Zhang      - For default PETSc vectors, VecGetArray() returns a pointer to
521227f9e03SJunchao Zhang      the data array.  Otherwise, the routine is implementation dependent.
522227f9e03SJunchao Zhang      - You MUST call VecRestoreArray() when you no longer need access to
523227f9e03SJunchao Zhang      the array.
524227f9e03SJunchao Zhang      */
525227f9e03SJunchao Zhang     PetscCall(DMDAVecGetArray(da,localX,&x));
526227f9e03SJunchao Zhang     if (B) PetscCall(DMDAVecGetArray(da,localB,&b));
527227f9e03SJunchao Zhang     /*
528227f9e03SJunchao Zhang      Get local grid boundaries (for 2-dimensional DMDA):
529227f9e03SJunchao Zhang      xs, ys   - starting grid indices (no ghost points)
530227f9e03SJunchao Zhang      xm, ym   - widths of local grid (no ghost points)
531227f9e03SJunchao Zhang      */
532227f9e03SJunchao Zhang     PetscCall(DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL));
533227f9e03SJunchao Zhang 
534227f9e03SJunchao Zhang     for (j=ys; j<ys+ym; j++) {
535227f9e03SJunchao Zhang       for (i=xs; i<xs+xm; i++) {
536227f9e03SJunchao Zhang         if (i == 0 || j == 0 || i == Mx-1 || j == My-1) {
537227f9e03SJunchao Zhang           /* boundary conditions are all zero Dirichlet */
538227f9e03SJunchao Zhang           x[j][i] = 0.0;
539227f9e03SJunchao Zhang         } else {
540227f9e03SJunchao Zhang           if (B) bij = b[j][i];
541227f9e03SJunchao Zhang           else   bij = 0.;
542227f9e03SJunchao Zhang 
543227f9e03SJunchao Zhang           u  = x[j][i];
544227f9e03SJunchao Zhang           un = x[j-1][i];
545227f9e03SJunchao Zhang           us = x[j+1][i];
546227f9e03SJunchao Zhang           ue = x[j][i-1];
547227f9e03SJunchao Zhang           uw = x[j][i+1];
548227f9e03SJunchao Zhang 
549227f9e03SJunchao Zhang           for (k=0; k<its; k++) {
550227f9e03SJunchao Zhang             eu  = PetscExpScalar(u);
551227f9e03SJunchao Zhang             uxx = (2.0*u - ue - uw)*hydhx;
552227f9e03SJunchao Zhang             uyy = (2.0*u - un - us)*hxdhy;
553227f9e03SJunchao Zhang             F   = uxx + uyy - sc*eu - bij;
554227f9e03SJunchao Zhang             if (k == 0) F0 = F;
555227f9e03SJunchao Zhang             J  = 2.0*(hydhx + hxdhy) - sc*eu;
556227f9e03SJunchao Zhang             y  = F/J;
557227f9e03SJunchao Zhang             u -= y;
558227f9e03SJunchao Zhang             tot_its++;
559227f9e03SJunchao Zhang 
560227f9e03SJunchao Zhang             if (atol > PetscAbsReal(PetscRealPart(F)) ||
561227f9e03SJunchao Zhang                 rtol*PetscAbsReal(PetscRealPart(F0)) > PetscAbsReal(PetscRealPart(F)) ||
562227f9e03SJunchao Zhang                 stol*PetscAbsReal(PetscRealPart(u)) > PetscAbsReal(PetscRealPart(y))) {
563227f9e03SJunchao Zhang               break;
564227f9e03SJunchao Zhang             }
565227f9e03SJunchao Zhang           }
566227f9e03SJunchao Zhang           x[j][i] = u;
567227f9e03SJunchao Zhang         }
568227f9e03SJunchao Zhang       }
569227f9e03SJunchao Zhang     }
570227f9e03SJunchao Zhang     /*
571227f9e03SJunchao Zhang      Restore vector
572227f9e03SJunchao Zhang      */
573227f9e03SJunchao Zhang     PetscCall(DMDAVecRestoreArray(da,localX,&x));
574227f9e03SJunchao Zhang     PetscCall(DMLocalToGlobalBegin(da,localX,INSERT_VALUES,X));
575227f9e03SJunchao Zhang     PetscCall(DMLocalToGlobalEnd(da,localX,INSERT_VALUES,X));
576227f9e03SJunchao Zhang   }
577227f9e03SJunchao Zhang   PetscCall(PetscLogFlops(tot_its*(21.0)));
578227f9e03SJunchao Zhang   PetscCall(DMRestoreLocalVector(da,&localX));
579227f9e03SJunchao Zhang   if (B) {
580227f9e03SJunchao Zhang     PetscCall(DMDAVecRestoreArray(da,localB,&b));
581227f9e03SJunchao Zhang     PetscCall(DMRestoreLocalVector(da,&localB));
582227f9e03SJunchao Zhang   }
583227f9e03SJunchao Zhang   PetscFunctionReturn(0);
584227f9e03SJunchao Zhang }
585c4762a1bSJed Brown 
586c4762a1bSJed Brown int main(int argc,char **argv)
587c4762a1bSJed Brown {
588c4762a1bSJed Brown   SNES           snes;                         /* nonlinear solver */
589c4762a1bSJed Brown   Vec            x;                            /* solution vector */
590c4762a1bSJed Brown   AppCtx         user;                         /* user-defined work context */
591c4762a1bSJed Brown   PetscInt       its;                          /* iterations for convergence */
592c4762a1bSJed Brown   PetscReal      bratu_lambda_max = 6.81;
593c4762a1bSJed Brown   PetscReal      bratu_lambda_min = 0.;
594*16d037c0SJunchao Zhang   PetscInt       MMS              = 1;
595*16d037c0SJunchao Zhang   PetscBool      flg              = PETSC_FALSE,setMMS;
596c4762a1bSJed Brown   DM             da;
597c4762a1bSJed Brown   Vec            r               = NULL;
598c4762a1bSJed Brown   KSP            ksp;
599c4762a1bSJed Brown   PetscInt       lits,slits;
600c4762a1bSJed Brown 
601c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
602c4762a1bSJed Brown      Initialize program
603c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
604c4762a1bSJed Brown 
6059566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc,&argv,(char*)0,help));
606c4762a1bSJed Brown 
607c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
608c4762a1bSJed Brown      Initialize problem parameters
609c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
610c4762a1bSJed Brown   user.param = 6.0;
6119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetReal(NULL,NULL,"-par",&user.param,NULL));
612e00437b9SBarry Smith   PetscCheck(user.param <= bratu_lambda_max && user.param >= bratu_lambda_min,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lambda, %g, is out of range, [%g, %g]", (double)user.param, (double)bratu_lambda_min, (double)bratu_lambda_max);
613*16d037c0SJunchao Zhang   PetscCall(PetscOptionsGetInt(NULL,NULL,"-mms",&MMS,&setMMS));
614c4762a1bSJed Brown   if (MMS == 3) {
615c4762a1bSJed Brown     PetscInt mPar = 2, nPar = 1;
6169566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetInt(NULL,NULL,"-m_par",&mPar,NULL));
6179566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetInt(NULL,NULL,"-n_par",&nPar,NULL));
618c4762a1bSJed Brown     user.m = PetscPowInt(2,mPar);
619c4762a1bSJed Brown     user.n = PetscPowInt(2,nPar);
620c4762a1bSJed Brown   }
621c4762a1bSJed Brown 
622c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
623c4762a1bSJed Brown      Create nonlinear solver context
624c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6259566063dSJacob Faibussowitsch   PetscCall(SNESCreate(PETSC_COMM_WORLD,&snes));
6269566063dSJacob Faibussowitsch   PetscCall(SNESSetCountersReset(snes,PETSC_FALSE));
6279566063dSJacob Faibussowitsch   PetscCall(SNESSetNGS(snes, NonlinearGS, NULL));
628c4762a1bSJed Brown 
629c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
630c4762a1bSJed Brown      Create distributed array (DMDA) to manage parallel grid and vectors
631c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6329566063dSJacob Faibussowitsch   PetscCall(DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE,DMDA_STENCIL_STAR,4,4,PETSC_DECIDE,PETSC_DECIDE,1,1,NULL,NULL,&da));
6339566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(da));
6349566063dSJacob Faibussowitsch   PetscCall(DMSetUp(da));
6359566063dSJacob Faibussowitsch   PetscCall(DMDASetUniformCoordinates(da, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0));
6369566063dSJacob Faibussowitsch   PetscCall(DMSetApplicationContext(da,&user));
6379566063dSJacob Faibussowitsch   PetscCall(SNESSetDM(snes,da));
638c4762a1bSJed Brown   /*  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
639c4762a1bSJed Brown      Extract global vectors from DMDA; then duplicate for remaining
640c4762a1bSJed Brown      vectors that are the same types
641c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6429566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(da,&x));
643c4762a1bSJed Brown 
644c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
645c4762a1bSJed Brown      Set local function evaluation routine
646c4762a1bSJed Brown   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
647c4762a1bSJed Brown   switch (MMS) {
648*16d037c0SJunchao Zhang   case 0: user.mms_solution = ZeroBCSolution; user.mms_forcing = NULL; break;
649c4762a1bSJed Brown   case 1: user.mms_solution = MMSSolution1; user.mms_forcing = MMSForcing1; break;
650c4762a1bSJed Brown   case 2: user.mms_solution = MMSSolution2; user.mms_forcing = MMSForcing2; break;
651c4762a1bSJed Brown   case 3: user.mms_solution = MMSSolution3; user.mms_forcing = MMSForcing3; break;
652c4762a1bSJed Brown   case 4: user.mms_solution = MMSSolution4; user.mms_forcing = MMSForcing4; break;
65363a3b9bcSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"Unknown MMS type %" PetscInt_FMT,MMS);
654c4762a1bSJed Brown   }
6559566063dSJacob Faibussowitsch   PetscCall(DMDASNESSetFunctionLocal(da,INSERT_VALUES,(DMDASNESFunction)FormFunctionLocal,&user));
6569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL,NULL,"-fd",&flg,NULL));
657c4762a1bSJed Brown   if (!flg) {
6589566063dSJacob Faibussowitsch     PetscCall(DMDASNESSetJacobianLocal(da,(DMDASNESJacobian)FormJacobianLocal,&user));
659c4762a1bSJed Brown   }
660c4762a1bSJed Brown 
6619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL,NULL,"-obj",&flg,NULL));
662c4762a1bSJed Brown   if (flg) {
6639566063dSJacob Faibussowitsch     PetscCall(DMDASNESSetObjectiveLocal(da,(DMDASNESObjective)FormObjectiveLocal,&user));
664c4762a1bSJed Brown   }
665c4762a1bSJed Brown 
6664e1ad211SJed Brown   if (PetscDefined(HAVE_MATLAB_ENGINE)) {
6674e1ad211SJed Brown     PetscBool matlab_function = PETSC_FALSE;
6689566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL,NULL,"-matlab_function",&matlab_function,0));
669c4762a1bSJed Brown     if (matlab_function) {
6709566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(x,&r));
6719566063dSJacob Faibussowitsch       PetscCall(SNESSetFunction(snes,r,FormFunctionMatlab,&user));
672c4762a1bSJed Brown     }
6734e1ad211SJed Brown   }
674c4762a1bSJed Brown 
675c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
676c4762a1bSJed Brown      Customize nonlinear solver; set runtime options
677c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6789566063dSJacob Faibussowitsch   PetscCall(SNESSetFromOptions(snes));
679c4762a1bSJed Brown 
6809566063dSJacob Faibussowitsch   PetscCall(FormInitialGuess(da,&user,x));
681c4762a1bSJed Brown 
682c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
683c4762a1bSJed Brown      Solve nonlinear system
684c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6859566063dSJacob Faibussowitsch   PetscCall(SNESSolve(snes,NULL,x));
6869566063dSJacob Faibussowitsch   PetscCall(SNESGetIterationNumber(snes,&its));
687c4762a1bSJed Brown 
6889566063dSJacob Faibussowitsch   PetscCall(SNESGetLinearSolveIterations(snes,&slits));
6899566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes,&ksp));
6909566063dSJacob Faibussowitsch   PetscCall(KSPGetTotalIterations(ksp,&lits));
69163a3b9bcSJacob Faibussowitsch   PetscCheck(lits == slits,PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Number of total linear iterations reported by SNES %" PetscInt_FMT " does not match reported by KSP %" PetscInt_FMT,slits,lits);
692c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
693c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
694c4762a1bSJed Brown 
695c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
696c4762a1bSJed Brown      If using MMS, check the l_2 error
697c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
698*16d037c0SJunchao Zhang   if (setMMS) {
699c4762a1bSJed Brown     Vec       e;
700c4762a1bSJed Brown     PetscReal errorl2, errorinf;
701c4762a1bSJed Brown     PetscInt  N;
702c4762a1bSJed Brown 
7039566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &e));
7049566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject) x, NULL, "-sol_view"));
7059566063dSJacob Faibussowitsch     PetscCall(FormExactSolution(da, &user, e));
7069566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject) e, NULL, "-exact_view"));
7079566063dSJacob Faibussowitsch     PetscCall(VecAXPY(e, -1.0, x));
7089566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject) e, NULL, "-error_view"));
7099566063dSJacob Faibussowitsch     PetscCall(VecNorm(e, NORM_2, &errorl2));
7109566063dSJacob Faibussowitsch     PetscCall(VecNorm(e, NORM_INFINITY, &errorinf));
7119566063dSJacob Faibussowitsch     PetscCall(VecGetSize(e, &N));
71263a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "N: %" PetscInt_FMT " error L2 %g inf %g\n", N, (double)(errorl2/PetscSqrtReal((PetscReal)N)), (double) errorinf));
7139566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&e));
7149566063dSJacob Faibussowitsch     PetscCall(PetscLogEventSetDof(SNES_Solve, 0, N));
7159566063dSJacob Faibussowitsch     PetscCall(PetscLogEventSetError(SNES_Solve, 0, errorl2/PetscSqrtReal(N)));
716c4762a1bSJed Brown   }
717c4762a1bSJed Brown 
718c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
719c4762a1bSJed Brown      Free work space.  All PETSc objects should be destroyed when they
720c4762a1bSJed Brown      are no longer needed.
721c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
7229566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&r));
7239566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
7249566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes));
7259566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&da));
7269566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
727b122ec5aSJacob Faibussowitsch   return 0;
728c4762a1bSJed Brown }
729c4762a1bSJed Brown 
730c4762a1bSJed Brown /*TEST
731c4762a1bSJed Brown 
732c4762a1bSJed Brown    test:
733c4762a1bSJed Brown      suffix: asm_0
734c4762a1bSJed Brown      requires: !single
735c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu
736c4762a1bSJed Brown 
737c4762a1bSJed Brown    test:
738c4762a1bSJed Brown      suffix: msm_0
739c4762a1bSJed Brown      requires: !single
740c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu
741c4762a1bSJed Brown 
742c4762a1bSJed Brown    test:
743c4762a1bSJed Brown      suffix: asm_1
744c4762a1bSJed Brown      requires: !single
745c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu -da_grid_x 8
746c4762a1bSJed Brown 
747c4762a1bSJed Brown    test:
748c4762a1bSJed Brown      suffix: msm_1
749c4762a1bSJed Brown      requires: !single
750c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu -da_grid_x 8
751c4762a1bSJed Brown 
752c4762a1bSJed Brown    test:
753c4762a1bSJed Brown      suffix: asm_2
754c4762a1bSJed Brown      requires: !single
755c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 3 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu -da_grid_x 8
756c4762a1bSJed Brown 
757c4762a1bSJed Brown    test:
758c4762a1bSJed Brown      suffix: msm_2
759c4762a1bSJed Brown      requires: !single
760c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 3 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu -da_grid_x 8
761c4762a1bSJed Brown 
762c4762a1bSJed Brown    test:
763c4762a1bSJed Brown      suffix: asm_3
764c4762a1bSJed Brown      requires: !single
765c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 4 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu -da_grid_x 8
766c4762a1bSJed Brown 
767c4762a1bSJed Brown    test:
768c4762a1bSJed Brown      suffix: msm_3
769c4762a1bSJed Brown      requires: !single
770c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 4 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu -da_grid_x 8
771c4762a1bSJed Brown 
772c4762a1bSJed Brown    test:
773c4762a1bSJed Brown      suffix: asm_4
774c4762a1bSJed Brown      requires: !single
775c4762a1bSJed Brown      nsize: 2
776c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu -da_grid_x 8
777c4762a1bSJed Brown 
778c4762a1bSJed Brown    test:
779c4762a1bSJed Brown      suffix: msm_4
780c4762a1bSJed Brown      requires: !single
781c4762a1bSJed Brown      nsize: 2
782c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu -da_grid_x 8
783c4762a1bSJed Brown 
784c4762a1bSJed Brown    test:
785c4762a1bSJed Brown      suffix: asm_5
786c4762a1bSJed Brown      requires: !single
787c4762a1bSJed Brown      nsize: 2
788c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 4 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu -da_grid_x 8
789c4762a1bSJed Brown 
790c4762a1bSJed Brown    test:
791c4762a1bSJed Brown      suffix: msm_5
792c4762a1bSJed Brown      requires: !single
793c4762a1bSJed Brown      nsize: 2
794c4762a1bSJed Brown      args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 4 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu -da_grid_x 8
795c4762a1bSJed Brown 
796c4762a1bSJed Brown    test:
797c4762a1bSJed Brown      args: -snes_rtol 1.e-5 -pc_type mg -ksp_monitor_short -snes_view -pc_mg_levels 3 -pc_mg_galerkin pmat -da_grid_x 17 -da_grid_y 17 -mg_levels_ksp_monitor_short -mg_levels_ksp_norm_type unpreconditioned -snes_monitor_short -mg_levels_ksp_chebyshev_esteig 0.5,1.1 -mg_levels_pc_type sor -pc_mg_type full
798c4762a1bSJed Brown      requires: !single
799c4762a1bSJed Brown 
800c4762a1bSJed Brown    test:
801c4762a1bSJed Brown      suffix: 2
802c4762a1bSJed Brown      args: -pc_type mg -ksp_converged_reason -snes_view -pc_mg_galerkin pmat -snes_grid_sequence 3 -mg_levels_ksp_norm_type unpreconditioned -snes_monitor_short -mg_levels_ksp_chebyshev_esteig 0.5,1.1 -mg_levels_pc_type sor -pc_mg_type full -ksp_atol -1.
803c4762a1bSJed Brown 
804c4762a1bSJed Brown    test:
805c4762a1bSJed Brown      suffix: 3
806c4762a1bSJed Brown      nsize: 2
807c4762a1bSJed Brown      args: -snes_grid_sequence 2 -snes_mf_operator -snes_converged_reason -snes_view -pc_type mg -snes_atol -1 -snes_rtol 1.e-2
808c4762a1bSJed Brown      filter: grep -v "otal number of function evaluations"
809c4762a1bSJed Brown 
810c4762a1bSJed Brown    test:
811c4762a1bSJed Brown      suffix: 4
812c4762a1bSJed Brown      nsize: 2
813c4762a1bSJed Brown      args: -snes_grid_sequence 2 -snes_monitor_short -ksp_converged_reason -snes_converged_reason -snes_view -pc_type mg -snes_atol -1 -ksp_atol -1
814c4762a1bSJed Brown 
815c4762a1bSJed Brown    test:
816c4762a1bSJed Brown      suffix: 5_anderson
817c4762a1bSJed Brown      args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type anderson
818c4762a1bSJed Brown 
819c4762a1bSJed Brown    test:
820c4762a1bSJed Brown      suffix: 5_aspin
821c4762a1bSJed Brown      nsize: 4
822c4762a1bSJed Brown      args: -snes_monitor_short -ksp_monitor_short -snes_converged_reason -da_refine 4 -da_overlap 3 -snes_type aspin -snes_view
823c4762a1bSJed Brown 
824c4762a1bSJed Brown    test:
825c4762a1bSJed Brown      suffix: 5_broyden
826c4762a1bSJed Brown      args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type qn -snes_qn_type broyden -snes_qn_m 10
827c4762a1bSJed Brown 
828c4762a1bSJed Brown    test:
829c4762a1bSJed Brown      suffix: 5_fas
830c4762a1bSJed Brown      args: -fas_coarse_snes_max_it 1 -fas_coarse_pc_type lu -fas_coarse_ksp_type preonly -snes_monitor_short -snes_type fas -fas_coarse_ksp_type richardson -da_refine 6
831c4762a1bSJed Brown      requires: !single
832c4762a1bSJed Brown 
833c4762a1bSJed Brown    test:
834c4762a1bSJed Brown      suffix: 5_fas_additive
835c4762a1bSJed Brown      args: -fas_coarse_snes_max_it 1 -fas_coarse_pc_type lu -fas_coarse_ksp_type preonly -snes_monitor_short -snes_type fas -fas_coarse_ksp_type richardson -da_refine 6 -snes_fas_type additive -snes_max_it 50
836c4762a1bSJed Brown 
837c4762a1bSJed Brown    test:
838c4762a1bSJed Brown      suffix: 5_fas_monitor
839c4762a1bSJed Brown      args: -da_refine 1 -snes_type fas -snes_fas_monitor
840c4762a1bSJed Brown      requires: !single
841c4762a1bSJed Brown 
842c4762a1bSJed Brown    test:
843c4762a1bSJed Brown      suffix: 5_ls
844c4762a1bSJed Brown      args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type newtonls
845c4762a1bSJed Brown 
846c4762a1bSJed Brown    test:
847c4762a1bSJed Brown      suffix: 5_ls_sell_sor
848c4762a1bSJed Brown      args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type newtonls -dm_mat_type sell -pc_type sor
849c4762a1bSJed Brown      output_file: output/ex5_5_ls.out
850c4762a1bSJed Brown 
851c4762a1bSJed Brown    test:
852c4762a1bSJed Brown      suffix: 5_nasm
853c4762a1bSJed Brown      nsize: 4
854c4762a1bSJed Brown      args: -snes_monitor_short -snes_converged_reason -da_refine 4 -da_overlap 3 -snes_type nasm -snes_nasm_type restrict -snes_max_it 10
855c4762a1bSJed Brown 
856c4762a1bSJed Brown    test:
857c4762a1bSJed Brown      suffix: 5_ncg
858c4762a1bSJed Brown      args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type ncg -snes_ncg_type fr
859c4762a1bSJed Brown 
860c4762a1bSJed Brown    test:
861c4762a1bSJed Brown      suffix: 5_newton_asm_dmda
862c4762a1bSJed Brown      nsize: 4
863c4762a1bSJed Brown      args: -snes_monitor_short -ksp_monitor_short -snes_converged_reason -da_refine 4 -da_overlap 3 -snes_type newtonls -pc_type asm -pc_asm_dm_subdomains -malloc_dump
864c4762a1bSJed Brown      requires: !single
865c4762a1bSJed Brown 
866c4762a1bSJed Brown    test:
867c4762a1bSJed Brown      suffix: 5_newton_gasm_dmda
868c4762a1bSJed Brown      nsize: 4
869c4762a1bSJed Brown      args: -snes_monitor_short -ksp_monitor_short -snes_converged_reason -da_refine 4 -da_overlap 3 -snes_type newtonls -pc_type gasm -malloc_dump
870c4762a1bSJed Brown      requires: !single
871c4762a1bSJed Brown 
872c4762a1bSJed Brown    test:
873c4762a1bSJed Brown      suffix: 5_ngmres
874c4762a1bSJed Brown      args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type ngmres -snes_ngmres_m 10
875c4762a1bSJed Brown 
876c4762a1bSJed Brown    test:
877c4762a1bSJed Brown      suffix: 5_ngmres_fas
878c4762a1bSJed Brown      args: -snes_rtol 1.e-4 -snes_type ngmres -npc_fas_coarse_snes_max_it 1 -npc_fas_coarse_snes_type newtonls -npc_fas_coarse_pc_type lu -npc_fas_coarse_ksp_type preonly -snes_ngmres_m 10 -snes_monitor_short -npc_snes_max_it 1 -npc_snes_type fas -npc_fas_coarse_ksp_type richardson -da_refine 6
879c4762a1bSJed Brown 
880c4762a1bSJed Brown    test:
881c4762a1bSJed Brown      suffix: 5_ngmres_ngs
882c4762a1bSJed Brown      args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type ngmres -npc_snes_type ngs -npc_snes_max_it 1
883c4762a1bSJed Brown 
884c4762a1bSJed Brown    test:
885c4762a1bSJed Brown      suffix: 5_ngmres_nrichardson
886c4762a1bSJed Brown      args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type ngmres -snes_ngmres_m 10 -npc_snes_type nrichardson -npc_snes_max_it 3
887c4762a1bSJed Brown      output_file: output/ex5_5_ngmres_richardson.out
888c4762a1bSJed Brown 
889c4762a1bSJed Brown    test:
890c4762a1bSJed Brown      suffix: 5_nrichardson
891c4762a1bSJed Brown      args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type nrichardson
892c4762a1bSJed Brown 
893c4762a1bSJed Brown    test:
894c4762a1bSJed Brown      suffix: 5_qn
895c4762a1bSJed Brown      args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type qn -snes_linesearch_type cp -snes_qn_m 10
896c4762a1bSJed Brown 
897c4762a1bSJed Brown    test:
898c4762a1bSJed Brown      suffix: 6
899c4762a1bSJed Brown      nsize: 4
900c4762a1bSJed Brown      args: -snes_converged_reason -ksp_converged_reason -da_grid_x 129 -da_grid_y 129 -pc_type mg -pc_mg_levels 8 -mg_levels_ksp_type chebyshev -mg_levels_ksp_chebyshev_esteig 0,0.5,0,1.1 -mg_levels_ksp_max_it 2
901c4762a1bSJed Brown 
902c4762a1bSJed Brown    test:
903c4762a1bSJed Brown      requires: complex !single
904c4762a1bSJed Brown      suffix: complex
905c4762a1bSJed Brown      args: -snes_mf_operator -mat_mffd_complex -snes_monitor
906c4762a1bSJed Brown 
907c4762a1bSJed Brown TEST*/
908