Actual source code: ex62.c

  1: static char help[] = "Stokes Problem discretized with finite elements,\n\
  2: using a parallel unstructured mesh (DMPLEX) to represent the domain.\n\n\n";

  4: /*
  5: For the isoviscous Stokes problem, which we discretize using the finite
  6: element method on an unstructured mesh, the weak form equations are

  8:   < \nabla v, \nabla u + {\nabla u}^T > - < \nabla\cdot v, p > - < v, f > = 0
  9:   < q, -\nabla\cdot u >                                                   = 0

 11: Viewing:

 13: To produce nice output, use

 15:   -dm_refine 3 -dm_view hdf5:sol1.h5 -error_vec_view hdf5:sol1.h5::append -snes_view_solution hdf5:sol1.h5::append -exact_vec_view hdf5:sol1.h5::append

 17: You can get a LaTeX view of the mesh, with point numbering using

 19:   -dm_view :mesh.tex:ascii_latex -dm_plex_view_scale 8.0

 21: The data layout can be viewed using

 23:   -dm_petscsection_view

 25: Lots of information about the FEM assembly can be printed using

 27:   -dm_plex_print_fem 3
 28: */

 30: #include <petscdmplex.h>
 31: #include <petscsnes.h>
 32: #include <petscds.h>
 33: #include <petscbag.h>

 35: // TODO: Plot residual by fields after each smoother iterate

 37: typedef enum {SOL_QUADRATIC, SOL_TRIG, SOL_UNKNOWN} SolType;
 38: const char *SolTypes[] = {"quadratic", "trig", "unknown", "SolType", "SOL_", 0};

 40: typedef struct {
 41:   PetscScalar mu; /* dynamic shear viscosity */
 42: } Parameter;

 44: typedef struct {
 45:   PetscBag bag; /* Problem parameters */
 46:   SolType  sol; /* MMS solution */
 47: } AppCtx;

 49: static void f1_u(PetscInt dim, PetscInt Nf, PetscInt NfAux,
 50:                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
 51:                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
 52:                  PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])
 53: {
 54:   const PetscReal mu = PetscRealPart(constants[0]);
 55:   const PetscInt  Nc = uOff[1]-uOff[0];
 56:   PetscInt        c, d;

 58:   for (c = 0; c < Nc; ++c) {
 59:     for (d = 0; d < dim; ++d) {
 60:       f1[c*dim+d] = mu * (u_x[c*dim+d] + u_x[d*dim+c]);
 61:     }
 62:     f1[c*dim+c] -= u[uOff[1]];
 63:   }
 64: }

 66: static void f0_p(PetscInt dim, PetscInt Nf, PetscInt NfAux,
 67:                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
 68:                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
 69:                  PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
 70: {
 71:   PetscInt d;
 72:   for (d = 0, f0[0] = 0.0; d < dim; ++d) f0[0] -= u_x[d*dim+d];
 73: }

 75: static void g1_pu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
 76:                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
 77:                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
 78:                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[])
 79: {
 80:   PetscInt d;
 81:   for (d = 0; d < dim; ++d) g1[d*dim+d] = -1.0; /* < q, -\nabla\cdot u > */
 82: }

 84: static void g2_up(PetscInt dim, PetscInt Nf, PetscInt NfAux,
 85:                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
 86:                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
 87:                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[])
 88: {
 89:   PetscInt d;
 90:   for (d = 0; d < dim; ++d) g2[d*dim+d] = -1.0; /* -< \nabla\cdot v, p > */
 91: }

 93: static void g3_uu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
 94:                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
 95:                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
 96:                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])
 97: {
 98:   const PetscReal mu = PetscRealPart(constants[0]);
 99:   const PetscInt  Nc = uOff[1]-uOff[0];
100:   PetscInt        c, d;

102:   for (c = 0; c < Nc; ++c) {
103:     for (d = 0; d < dim; ++d) {
104:       g3[((c*Nc+c)*dim+d)*dim+d] += mu; /* < \nabla v, \nabla u > */
105:       g3[((c*Nc+d)*dim+d)*dim+c] += mu; /* < \nabla v, {\nabla u}^T > */
106:     }
107:   }
108: }

110: static void g0_pp(PetscInt dim, PetscInt Nf, PetscInt NfAux,
111:                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
112:                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
113:                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
114: {
115:   const PetscReal mu = PetscRealPart(constants[0]);

117:   g0[0] = 1.0/mu;
118: }

120: /* Quadratic MMS Solution
121:    2D:

123:      u = x^2 + y^2
124:      v = 2 x^2 - 2xy
125:      p = x + y - 1
126:      f = <1 - 4 mu, 1 - 4 mu>

128:    so that

130:      e(u) = (grad u + grad u^T) = / 4x  4x \
131:                                   \ 4x -4x /
132:      div mu e(u) - \nabla p + f = mu <4, 4> - <1, 1> + <1 - 4 mu, 1 - 4 mu> = 0
133:      \nabla \cdot u             = 2x - 2x = 0

135:    3D:

137:      u = 2 x^2 + y^2 + z^2
138:      v = 2 x^2 - 2xy
139:      w = 2 x^2 - 2xz
140:      p = x + y + z - 3/2
141:      f = <1 - 8 mu, 1 - 4 mu, 1 - 4 mu>

143:    so that

145:      e(u) = (grad u + grad u^T) = / 8x  4x  4x \
146:                                   | 4x -4x  0  |
147:                                   \ 4x  0  -4x /
148:      div mu e(u) - \nabla p + f = mu <8, 4, 4> - <1, 1, 1> + <1 - 8 mu, 1 - 4 mu, 1 - 4 mu> = 0
149:      \nabla \cdot u             = 4x - 2x - 2x = 0
150: */
151: static PetscErrorCode quadratic_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
152: {
153:   PetscInt c;

155:   u[0] = (dim-1)*PetscSqr(x[0]);
156:   for (c = 1; c < Nc; ++c) {
157:     u[0] += PetscSqr(x[c]);
158:     u[c]  = 2.0*PetscSqr(x[0]) - 2.0*x[0]*x[c];
159:   }
160:   return 0;
161: }

163: static PetscErrorCode quadratic_p(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
164: {
165:   PetscInt d;

167:   u[0] = -0.5*dim;
168:   for (d = 0; d < dim; ++d) u[0] += x[d];
169:   return 0;
170: }

172: static void f0_quadratic_u(PetscInt dim, PetscInt Nf, PetscInt NfAux,
173:                            const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
174:                            const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
175:                            PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
176: {
177:   const PetscReal mu = PetscRealPart(constants[0]);
178:   PetscInt        d;

180:   f0[0] = (dim-1)*4.0*mu - 1.0;
181:   for (d = 1; d < dim; ++d) f0[d] = 4.0*mu - 1.0;
182: }

184: /* Trigonometric MMS Solution
185:    2D:

187:      u = sin(pi x) + sin(pi y)
188:      v = -pi cos(pi x) y
189:      p = sin(2 pi x) + sin(2 pi y)
190:      f = <2pi cos(2 pi x) + mu pi^2 sin(pi x) + mu pi^2 sin(pi y), 2pi cos(2 pi y) - mu pi^3 cos(pi x) y>

192:    so that

194:      e(u) = (grad u + grad u^T) = /        2pi cos(pi x)             pi cos(pi y) + pi^2 sin(pi x) y \
195:                                   \ pi cos(pi y) + pi^2 sin(pi x) y          -2pi cos(pi x)          /
196:      div mu e(u) - \nabla p + f = mu <-pi^2 sin(pi x) - pi^2 sin(pi y), pi^3 cos(pi x) y> - <2pi cos(2 pi x), 2pi cos(2 pi y)> + <f_x, f_y> = 0
197:      \nabla \cdot u             = pi cos(pi x) - pi cos(pi x) = 0

199:    3D:

201:      u = 2 sin(pi x) + sin(pi y) + sin(pi z)
202:      v = -pi cos(pi x) y
203:      w = -pi cos(pi x) z
204:      p = sin(2 pi x) + sin(2 pi y) + sin(2 pi z)
205:      f = <2pi cos(2 pi x) + mu 2pi^2 sin(pi x) + mu pi^2 sin(pi y) + mu pi^2 sin(pi z), 2pi cos(2 pi y) - mu pi^3 cos(pi x) y, 2pi cos(2 pi z) - mu pi^3 cos(pi x) z>

207:    so that

209:      e(u) = (grad u + grad u^T) = /        4pi cos(pi x)             pi cos(pi y) + pi^2 sin(pi x) y  pi cos(pi z) + pi^2 sin(pi x) z \
210:                                   | pi cos(pi y) + pi^2 sin(pi x) y          -2pi cos(pi x)                        0                  |
211:                                   \ pi cos(pi z) + pi^2 sin(pi x) z               0                         -2pi cos(pi x)            /
212:      div mu e(u) - \nabla p + f = mu <-2pi^2 sin(pi x) - pi^2 sin(pi y) - pi^2 sin(pi z), pi^3 cos(pi x) y, pi^3 cos(pi x) z> - <2pi cos(2 pi x), 2pi cos(2 pi y), 2pi cos(2 pi z)> + <f_x, f_y, f_z> = 0
213:      \nabla \cdot u             = 2 pi cos(pi x) - pi cos(pi x) - pi cos(pi x) = 0
214: */
215: static PetscErrorCode trig_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
216: {
217:   PetscInt c;

219:   u[0] = (dim-1)*PetscSinReal(PETSC_PI*x[0]);
220:   for (c = 1; c < Nc; ++c) {
221:     u[0] += PetscSinReal(PETSC_PI*x[c]);
222:     u[c]  = -PETSC_PI*PetscCosReal(PETSC_PI*x[0]) * x[c];
223:   }
224:   return 0;
225: }

227: static PetscErrorCode trig_p(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
228: {
229:   PetscInt d;

231:   for (d = 0, u[0] = 0.0; d < dim; ++d) u[0] += PetscSinReal(2.0*PETSC_PI*x[d]);
232:   return 0;
233: }

235: static void f0_trig_u(PetscInt dim, PetscInt Nf, PetscInt NfAux,
236:                       const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
237:                       const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
238:                       PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
239: {
240:   const PetscReal mu = PetscRealPart(constants[0]);
241:   PetscInt        d;

243:   f0[0] = -2.0*PETSC_PI*PetscCosReal(2.0*PETSC_PI*x[0]) - (dim-1)*mu*PetscSqr(PETSC_PI)*PetscSinReal(PETSC_PI*x[0]);
244:   for (d = 1; d < dim; ++d) {
245:     f0[0] -= mu*PetscSqr(PETSC_PI)*PetscSinReal(PETSC_PI*x[d]);
246:     f0[d]  = -2.0*PETSC_PI*PetscCosReal(2.0*PETSC_PI*x[d]) + mu*PetscPowRealInt(PETSC_PI, 3)*PetscCosReal(PETSC_PI*x[0])*x[d];
247:   }
248: }

250: static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
251: {
252:   PetscInt       sol;

256:   options->sol = SOL_QUADRATIC;

258:   PetscOptionsBegin(comm, "", "Stokes Problem Options", "DMPLEX");
259:   sol  = options->sol;
260:   PetscOptionsEList("-sol", "The MMS solution", "ex62.c", SolTypes, (sizeof(SolTypes)/sizeof(SolTypes[0]))-3, SolTypes[options->sol], &sol, NULL);
261:   options->sol = (SolType) sol;
262:   PetscOptionsEnd();
263:   return 0;
264: }

266: static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm)
267: {
269:   DMCreate(comm, dm);
270:   DMSetType(*dm, DMPLEX);
271:   DMSetFromOptions(*dm);
272:   DMViewFromOptions(*dm, NULL, "-dm_view");
273:   return 0;
274: }

276: static PetscErrorCode SetupParameters(MPI_Comm comm, AppCtx *ctx)
277: {
278:   Parameter     *p;

281:   /* setup PETSc parameter bag */
282:   PetscBagCreate(PETSC_COMM_SELF, sizeof(Parameter), &ctx->bag);
283:   PetscBagGetData(ctx->bag, (void **) &p);
284:   PetscBagSetName(ctx->bag, "par", "Stokes Parameters");
285:   PetscBagRegisterScalar(ctx->bag, &p->mu, 1.0, "mu", "Dynamic Shear Viscosity, Pa s");
286:   PetscBagSetFromOptions(ctx->bag);
287:   {
288:     PetscViewer       viewer;
289:     PetscViewerFormat format;
290:     PetscBool         flg;

292:     PetscOptionsGetViewer(comm, NULL, NULL, "-param_view", &viewer, &format, &flg);
293:     if (flg) {
294:       PetscViewerPushFormat(viewer, format);
295:       PetscBagView(ctx->bag, viewer);
296:       PetscViewerFlush(viewer);
297:       PetscViewerPopFormat(viewer);
298:       PetscViewerDestroy(&viewer);
299:     }
300:   }
301:   return 0;
302: }

304: static PetscErrorCode SetupEqn(DM dm, AppCtx *user)
305: {
306:   PetscErrorCode (*exactFuncs[2])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *);
307:   PetscDS          ds;
308:   DMLabel          label;
309:   const PetscInt   id = 1;

312:   DMGetDS(dm, &ds);
313:   switch (user->sol) {
314:     case SOL_QUADRATIC:
315:       PetscDSSetResidual(ds, 0, f0_quadratic_u, f1_u);
316:       exactFuncs[0] = quadratic_u;
317:       exactFuncs[1] = quadratic_p;
318:       break;
319:     case SOL_TRIG:
320:       PetscDSSetResidual(ds, 0, f0_trig_u, f1_u);
321:       exactFuncs[0] = trig_u;
322:       exactFuncs[1] = trig_p;
323:       break;
324:     default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Unsupported solution type: %s (%D)", SolTypes[PetscMin(user->sol, SOL_UNKNOWN)], user->sol);
325:   }
326:   PetscDSSetResidual(ds, 1, f0_p, NULL);
327:   PetscDSSetJacobian(ds, 0, 0, NULL, NULL,  NULL,  g3_uu);
328:   PetscDSSetJacobian(ds, 0, 1, NULL, NULL,  g2_up, NULL);
329:   PetscDSSetJacobian(ds, 1, 0, NULL, g1_pu, NULL,  NULL);
330:   PetscDSSetJacobianPreconditioner(ds, 0, 0, NULL, NULL, NULL, g3_uu);
331:   PetscDSSetJacobianPreconditioner(ds, 1, 1, g0_pp, NULL, NULL, NULL);

333:   PetscDSSetExactSolution(ds, 0, exactFuncs[0], user);
334:   PetscDSSetExactSolution(ds, 1, exactFuncs[1], user);

336:   DMGetLabel(dm, "marker", &label);
337:   DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", label, 1, &id, 0, 0, NULL, (void (*)(void)) exactFuncs[0], NULL, user, NULL);

339:   /* Make constant values available to pointwise functions */
340:   {
341:     Parameter  *param;
342:     PetscScalar constants[1];

344:     PetscBagGetData(user->bag, (void **) &param);
345:     constants[0] = param->mu; /* dynamic shear viscosity, Pa s */
346:     PetscDSSetConstants(ds, 1, constants);
347:   }
348:   return 0;
349: }

351: static PetscErrorCode zero(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
352: {
353:   PetscInt c;
354:   for (c = 0; c < Nc; ++c) u[c] = 0.0;
355:   return 0;
356: }
357: static PetscErrorCode one(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
358: {
359:   PetscInt c;
360:   for (c = 0; c < Nc; ++c) u[c] = 1.0;
361:   return 0;
362: }

364: static PetscErrorCode CreatePressureNullSpace(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullspace)
365: {
366:   Vec              vec;
367:   PetscErrorCode (*funcs[2])(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void* ctx) = {zero, one};

371:   funcs[field] = one;
372:   {
373:     PetscDS ds;
374:     DMGetDS(dm, &ds);
375:     PetscObjectViewFromOptions((PetscObject) ds, NULL, "-ds_view");
376:   }
377:   DMCreateGlobalVector(dm, &vec);
378:   DMProjectFunction(dm, 0.0, funcs, NULL, INSERT_ALL_VALUES, vec);
379:   VecNormalize(vec, NULL);
380:   MatNullSpaceCreate(PetscObjectComm((PetscObject)dm), PETSC_FALSE, 1, &vec, nullspace);
381:   VecDestroy(&vec);
382:   /* New style for field null spaces */
383:   {
384:     PetscObject  pressure;
385:     MatNullSpace nullspacePres;

387:     DMGetField(dm, field, NULL, &pressure);
388:     MatNullSpaceCreate(PetscObjectComm(pressure), PETSC_TRUE, 0, NULL, &nullspacePres);
389:     PetscObjectCompose(pressure, "nullspace", (PetscObject) nullspacePres);
390:     MatNullSpaceDestroy(&nullspacePres);
391:   }
392:   return 0;
393: }

395: static PetscErrorCode SetupProblem(DM dm, PetscErrorCode (*setupEqn)(DM, AppCtx *), AppCtx *user)
396: {
397:   DM              cdm = dm;
398:   PetscQuadrature q   = NULL;
399:   PetscBool       simplex;
400:   PetscInt        dim, Nf = 2, f, Nc[2];
401:   const char     *name[2]   = {"velocity", "pressure"};
402:   const char     *prefix[2] = {"vel_",     "pres_"};

404:   DMGetDimension(dm, &dim);
405:   DMPlexIsSimplex(dm, &simplex);
406:   Nc[0] = dim;
407:   Nc[1] = 1;
408:   for (f = 0; f < Nf; ++f) {
409:     PetscFE fe;

411:     PetscFECreateDefault(PETSC_COMM_SELF, dim, Nc[f], simplex, prefix[f], -1, &fe);
412:     PetscObjectSetName((PetscObject) fe, name[f]);
413:     if (!q) PetscFEGetQuadrature(fe, &q);
414:     PetscFESetQuadrature(fe, q);
415:     DMSetField(dm, f, NULL, (PetscObject) fe);
416:     PetscFEDestroy(&fe);
417:   }
418:   DMCreateDS(dm);
419:   (*setupEqn)(dm, user);
420:   while (cdm) {
421:     DMCopyDisc(dm, cdm);
422:     DMSetNullSpaceConstructor(cdm, 1, CreatePressureNullSpace);
423:     DMGetCoarseDM(cdm, &cdm);
424:   }
425:   return 0;
426: }

428: int main(int argc, char **argv)
429: {
430:   SNES           snes;
431:   DM             dm;
432:   Vec            u;
433:   AppCtx         user;

435:   PetscInitialize(&argc, &argv, NULL, help);
436:   ProcessOptions(PETSC_COMM_WORLD, &user);
437:   CreateMesh(PETSC_COMM_WORLD, &user, &dm);
438:   SNESCreate(PetscObjectComm((PetscObject) dm), &snes);
439:   SNESSetDM(snes, dm);
440:   DMSetApplicationContext(dm, &user);

442:   SetupParameters(PETSC_COMM_WORLD, &user);
443:   SetupProblem(dm, SetupEqn, &user);
444:   DMPlexCreateClosureIndex(dm, NULL);

446:   DMCreateGlobalVector(dm, &u);
447:   DMPlexSetSNESLocalFEM(dm, &user, &user, &user);
448:   SNESSetFromOptions(snes);
449:   DMSNESCheckFromOptions(snes, u);
450:   PetscObjectSetName((PetscObject) u, "Solution");
451:   {
452:     Mat          J;
453:     MatNullSpace sp;

455:     SNESSetUp(snes);
456:     CreatePressureNullSpace(dm, 1, 1, &sp);
457:     SNESGetJacobian(snes, &J, NULL, NULL, NULL);
458:     MatSetNullSpace(J, sp);
459:     MatNullSpaceDestroy(&sp);
460:     PetscObjectSetName((PetscObject) J, "Jacobian");
461:     MatViewFromOptions(J, NULL, "-J_view");
462:   }
463:   SNESSolve(snes, NULL, u);

465:   VecDestroy(&u);
466:   SNESDestroy(&snes);
467:   DMDestroy(&dm);
468:   PetscBagDestroy(&user.bag);
469:   PetscFinalize();
470:   return 0;
471: }
472: /*TEST

474:   test:
475:     suffix: 2d_p2_p1_check
476:     requires: triangle
477:     args: -sol quadratic -vel_petscspace_degree 2 -pres_petscspace_degree 1 -dmsnes_check 0.0001

479:   test:
480:     suffix: 2d_p2_p1_check_parallel
481:     nsize: {{2 3 5}}
482:     requires: triangle
483:     args: -sol quadratic -dm_refine 2 -petscpartitioner_type simple -vel_petscspace_degree 2 -pres_petscspace_degree 1 -dmsnes_check 0.0001

485:   test:
486:     suffix: 3d_p2_p1_check
487:     requires: ctetgen
488:     args: -sol quadratic -dm_plex_dim 3 -dm_plex_box_faces 2,2,2 -vel_petscspace_degree 2 -pres_petscspace_degree 1 -dmsnes_check 0.0001

490:   test:
491:     suffix: 3d_p2_p1_check_parallel
492:     nsize: {{2 3 5}}
493:     requires: ctetgen
494:     args: -sol quadratic -dm_refine 2 -dm_plex_dim 3 -dm_plex_box_faces 2,2,2 -petscpartitioner_type simple -vel_petscspace_degree 2 -pres_petscspace_degree 1 -dmsnes_check 0.0001

496:   test:
497:     suffix: 2d_p2_p1_conv
498:     requires: triangle
499:     # Using -dm_refine 3 gives L_2 convergence rate: [3.0, 2.1]
500:     args: -sol trig -vel_petscspace_degree 2 -pres_petscspace_degree 1 -snes_convergence_estimate -convest_num_refine 2 -ksp_error_if_not_converged \
501:       -ksp_atol 1e-10 -ksp_error_if_not_converged -pc_use_amat \
502:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type full -pc_fieldsplit_schur_precondition a11 -pc_fieldsplit_off_diag_use_amat \
503:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type lu

505:   test:
506:     suffix: 2d_p2_p1_conv_gamg
507:     requires: triangle
508:     args: -sol trig -vel_petscspace_degree 2 -pres_petscspace_degree 1 -snes_convergence_estimate -convest_num_refine 2  \
509:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type full -pc_fieldsplit_schur_precondition full \
510:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type gamg -fieldsplit_pressure_mg_coarse_pc_type svd

512:   test:
513:     suffix: 3d_p2_p1_conv
514:     requires: ctetgen !single
515:     # Using -dm_refine 2 -convest_num_refine 2 gives L_2 convergence rate: [2.8, 2.8]
516:     args: -sol trig -dm_plex_dim 3 -dm_refine 1 -vel_petscspace_degree 2 -pres_petscspace_degree 1 -snes_convergence_estimate -convest_num_refine 1 \
517:       -ksp_atol 1e-10 -ksp_error_if_not_converged -pc_use_amat \
518:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type full -pc_fieldsplit_schur_precondition a11 -pc_fieldsplit_off_diag_use_amat \
519:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type lu

521:   test:
522:     suffix: 2d_q2_q1_check
523:     args: -sol quadratic -dm_plex_simplex 0 -vel_petscspace_degree 2 -pres_petscspace_degree 1 -dmsnes_check 0.0001

525:   test:
526:     suffix: 3d_q2_q1_check
527:     args: -sol quadratic -dm_plex_simplex 0 -dm_plex_dim 3 -dm_plex_box_faces 2,2,2 -vel_petscspace_degree 2 -pres_petscspace_degree 1 -dmsnes_check 0.0001

529:   test:
530:     suffix: 2d_q2_q1_conv
531:     # Using -dm_refine 3 -convest_num_refine 1 gives L_2 convergence rate: [3.0, 2.1]
532:     args: -sol trig -dm_plex_simplex 0 -vel_petscspace_degree 2 -pres_petscspace_degree 1 -snes_convergence_estimate -convest_num_refine 1 -ksp_error_if_not_converged \
533:       -ksp_atol 1e-10 -ksp_error_if_not_converged -pc_use_amat \
534:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type full -pc_fieldsplit_schur_precondition a11 -pc_fieldsplit_off_diag_use_amat \
535:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type lu

537:   test:
538:     suffix: 3d_q2_q1_conv
539:     requires: !single
540:     # Using -dm_refine 2 -convest_num_refine 2 gives L_2 convergence rate: [2.8, 2.4]
541:     args: -sol trig -dm_plex_simplex 0 -dm_plex_dim 3 -vel_petscspace_degree 2 -pres_petscspace_degree 1 -snes_convergence_estimate -convest_num_refine 1 \
542:       -ksp_atol 1e-10 -ksp_error_if_not_converged -pc_use_amat \
543:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type full -pc_fieldsplit_schur_precondition a11 -pc_fieldsplit_off_diag_use_amat \
544:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type lu

546:   test:
547:     suffix: 2d_p3_p2_check
548:     requires: triangle
549:     args: -sol quadratic -vel_petscspace_degree 3 -pres_petscspace_degree 2 -dmsnes_check 0.0001

551:   test:
552:     suffix: 3d_p3_p2_check
553:     requires: ctetgen !single
554:     args: -sol quadratic -dm_plex_dim 3 -dm_plex_box_faces 2,2,2 -vel_petscspace_degree 3 -pres_petscspace_degree 2 -dmsnes_check 0.0001

556:   test:
557:     suffix: 2d_p3_p2_conv
558:     requires: triangle
559:     # Using -dm_refine 2 gives L_2 convergence rate: [3.8, 3.0]
560:     args: -sol trig -vel_petscspace_degree 3 -pres_petscspace_degree 2 -snes_convergence_estimate -convest_num_refine 2 -ksp_error_if_not_converged \
561:       -ksp_atol 1e-10 -ksp_error_if_not_converged -pc_use_amat \
562:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type full -pc_fieldsplit_schur_precondition a11 -pc_fieldsplit_off_diag_use_amat \
563:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type lu

565:   test:
566:     suffix: 3d_p3_p2_conv
567:     requires: ctetgen long_runtime
568:     # Using -dm_refine 1 -convest_num_refine 2 gives L_2 convergence rate: [3.6, 3.9]
569:     args: -sol trig -dm_plex_dim 3 -dm_refine 1 -vel_petscspace_degree 3 -pres_petscspace_degree 2 -snes_convergence_estimate -convest_num_refine 2 \
570:       -ksp_atol 1e-10 -ksp_error_if_not_converged -pc_use_amat \
571:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type full -pc_fieldsplit_schur_precondition a11 -pc_fieldsplit_off_diag_use_amat \
572:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type lu

574:   test:
575:     suffix: 2d_q1_p0_conv
576:     requires: !single
577:     # Using -dm_refine 3 gives L_2 convergence rate: [1.9, 1.0]
578:     args: -sol quadratic -dm_plex_simplex 0 -vel_petscspace_degree 1 -pres_petscspace_degree 0 -snes_convergence_estimate -convest_num_refine 2 \
579:       -ksp_atol 1e-10 -petscds_jac_pre 0 \
580:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type full -pc_fieldsplit_schur_precondition full \
581:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type gamg -fieldsplit_pressure_mg_levels_pc_type jacobi -fieldsplit_pressure_mg_coarse_pc_type svd

583:   test:
584:     suffix: 3d_q1_p0_conv
585:     requires: !single
586:     # Using -dm_refine 2 -convest_num_refine 2 gives L_2 convergence rate: [1.7, 1.0]
587:     args: -sol quadratic -dm_plex_simplex 0 -dm_plex_dim 3 -dm_refine 1 -vel_petscspace_degree 1 -pres_petscspace_degree 0 -snes_convergence_estimate -convest_num_refine 1 \
588:       -ksp_atol 1e-10 -petscds_jac_pre 0 \
589:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type full -pc_fieldsplit_schur_precondition full \
590:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type gamg -fieldsplit_pressure_mg_levels_pc_type jacobi -fieldsplit_pressure_mg_coarse_pc_type svd

592:   # Stokes preconditioners
593:   #   Block diagonal \begin{pmatrix} A & 0 \\ 0 & I \end{pmatrix}
594:   test:
595:     suffix: 2d_p2_p1_block_diagonal
596:     requires: triangle
597:     args: -sol quadratic -dm_refine 2 -vel_petscspace_degree 2 -pres_petscspace_degree 1 -petscds_jac_pre 0 \
598:       -snes_error_if_not_converged \
599:       -ksp_type fgmres -ksp_gmres_restart 100 -ksp_rtol 1.0e-4 -ksp_error_if_not_converged \
600:       -pc_type fieldsplit -pc_fieldsplit_type additive -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_pc_type jacobi
601:   #   Block triangular \begin{pmatrix} A & B \\ 0 & I \end{pmatrix}
602:   test:
603:     suffix: 2d_p2_p1_block_triangular
604:     requires: triangle
605:     args: -sol quadratic -dm_refine 2 -vel_petscspace_degree 2 -pres_petscspace_degree 1 -petscds_jac_pre 0 \
606:       -snes_error_if_not_converged \
607:       -ksp_type fgmres -ksp_gmres_restart 100 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged \
608:       -pc_type fieldsplit -pc_fieldsplit_type multiplicative -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_pc_type jacobi
609:   #   Diagonal Schur complement \begin{pmatrix} A & 0 \\ 0 & S \end{pmatrix}
610:   test:
611:     suffix: 2d_p2_p1_schur_diagonal
612:     requires: triangle
613:     args: -sol quadratic -dm_refine 2 -vel_petscspace_degree 2 -pres_petscspace_degree 1 \
614:       -snes_error_if_not_converged \
615:       -ksp_type fgmres -ksp_gmres_restart 100 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged -pc_use_amat \
616:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type diag -pc_fieldsplit_off_diag_use_amat \
617:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
618:   #   Upper triangular Schur complement \begin{pmatrix} A & B \\ 0 & S \end{pmatrix}
619:   test:
620:     suffix: 2d_p2_p1_schur_upper
621:     requires: triangle
622:     args: -sol quadratic -dm_refine 2 -vel_petscspace_degree 2 -pres_petscspace_degree 1 -dmsnes_check 0.0001 \
623:       -ksp_type fgmres -ksp_gmres_restart 100 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged -pc_use_amat \
624:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type upper -pc_fieldsplit_off_diag_use_amat \
625:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
626:   #   Lower triangular Schur complement \begin{pmatrix} A & B \\ 0 & S \end{pmatrix}
627:   test:
628:     suffix: 2d_p2_p1_schur_lower
629:     requires: triangle
630:     args: -sol quadratic -dm_refine 2 -vel_petscspace_degree 2 -pres_petscspace_degree 1 \
631:       -snes_error_if_not_converged \
632:       -ksp_type fgmres -ksp_gmres_restart 100 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged -pc_use_amat \
633:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type lower -pc_fieldsplit_off_diag_use_amat \
634:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
635:   #   Full Schur complement \begin{pmatrix} I & 0 \\ B^T A^{-1} & I \end{pmatrix} \begin{pmatrix} A & 0 \\ 0 & S \end{pmatrix} \begin{pmatrix} I & A^{-1} B \\ 0 & I \end{pmatrix}
636:   test:
637:     suffix: 2d_p2_p1_schur_full
638:     requires: triangle
639:     args: -sol quadratic -dm_refine 2 -vel_petscspace_degree 2 -pres_petscspace_degree 1 \
640:       -snes_error_if_not_converged \
641:       -ksp_type fgmres -ksp_gmres_restart 100 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged -pc_use_amat \
642:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full -pc_fieldsplit_off_diag_use_amat \
643:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
644:   #   Full Schur + Velocity GMG
645:   test:
646:     suffix: 2d_p2_p1_gmg_vcycle
647:     requires: triangle
648:     args: -sol quadratic -dm_refine_hierarchy 2 -vel_petscspace_degree 2 -pres_petscspace_degree 1 \
649:       -ksp_type fgmres -ksp_atol 1e-9 -snes_error_if_not_converged -pc_use_amat \
650:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type full -pc_fieldsplit_off_diag_use_amat \
651:         -fieldsplit_velocity_pc_type mg -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type gamg -fieldsplit_pressure_pc_gamg_esteig_ksp_max_it 10 -fieldsplit_pressure_mg_levels_pc_type sor -fieldsplit_pressure_mg_coarse_pc_type svd
652:   #   SIMPLE \begin{pmatrix} I & 0 \\ B^T A^{-1} & I \end{pmatrix} \begin{pmatrix} A & 0 \\ 0 & B^T diag(A)^{-1} B \end{pmatrix} \begin{pmatrix} I & diag(A)^{-1} B \\ 0 & I \end{pmatrix}
653:   test:
654:     suffix: 2d_p2_p1_simple
655:     requires: triangle
656:     args: -sol quadratic -dm_refine 2 -vel_petscspace_degree 2 -pres_petscspace_degree 1 -petscds_jac_pre 0 \
657:       -snes_error_if_not_converged \
658:       -ksp_type fgmres -ksp_gmres_restart 100 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged \
659:       -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full \
660:         -fieldsplit_velocity_pc_type lu -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi \
661:         -fieldsplit_pressure_inner_ksp_type preonly -fieldsplit_pressure_inner_pc_type jacobi -fieldsplit_pressure_upper_ksp_type preonly -fieldsplit_pressure_upper_pc_type jacobi
662:   #   FETI-DP solvers (these solvers are quite inefficient, they are here to exercise the code)
663:   test:
664:     suffix: 2d_p2_p1_fetidp
665:     requires: triangle mumps
666:     nsize: 5
667:     args: -sol quadratic -dm_refine 2 -dm_mat_type is -petscpartitioner_type simple -vel_petscspace_degree 2 -pres_petscspace_degree 1 -petscds_jac_pre 0 \
668:       -snes_error_if_not_converged \
669:       -ksp_type fetidp -ksp_rtol 1.0e-8 \
670:       -ksp_fetidp_saddlepoint -fetidp_ksp_type cg \
671:         -fetidp_fieldsplit_p_ksp_max_it 1 -fetidp_fieldsplit_p_ksp_type richardson -fetidp_fieldsplit_p_ksp_richardson_scale 200 -fetidp_fieldsplit_p_pc_type none \
672:         -fetidp_bddc_pc_bddc_dirichlet_pc_factor_mat_solver_type mumps -fetidp_bddc_pc_bddc_neumann_pc_factor_mat_solver_type mumps -fetidp_fieldsplit_lag_ksp_type preonly
673:   test:
674:     suffix: 2d_q2_q1_fetidp
675:     requires: mumps
676:     nsize: 5
677:     args: -sol quadratic -dm_plex_simplex 0 -dm_refine 2 -dm_mat_type is -petscpartitioner_type simple -vel_petscspace_degree 2 -pres_petscspace_degree 1 -petscds_jac_pre 0 \
678:       -ksp_type fetidp -ksp_rtol 1.0e-8 -ksp_error_if_not_converged \
679:       -ksp_fetidp_saddlepoint -fetidp_ksp_type cg \
680:         -fetidp_fieldsplit_p_ksp_max_it 1 -fetidp_fieldsplit_p_ksp_type richardson -fetidp_fieldsplit_p_ksp_richardson_scale 200 -fetidp_fieldsplit_p_pc_type none \
681:         -fetidp_bddc_pc_bddc_dirichlet_pc_factor_mat_solver_type mumps -fetidp_bddc_pc_bddc_neumann_pc_factor_mat_solver_type mumps -fetidp_fieldsplit_lag_ksp_type preonly
682:   test:
683:     suffix: 3d_p2_p1_fetidp
684:     requires: ctetgen mumps suitesparse
685:     nsize: 5
686:     args: -sol quadratic -dm_plex_dim 3 -dm_plex_box_faces 2,2,2 -dm_refine 1 -dm_mat_type is -petscpartitioner_type simple -vel_petscspace_degree 2 -pres_petscspace_degree 1 -petscds_jac_pre 0 \
687:       -snes_error_if_not_converged \
688:       -ksp_type fetidp -ksp_rtol 1.0e-9  \
689:       -ksp_fetidp_saddlepoint -fetidp_ksp_type cg \
690:         -fetidp_fieldsplit_p_ksp_max_it 1 -fetidp_fieldsplit_p_ksp_type richardson -fetidp_fieldsplit_p_ksp_richardson_scale 1000 -fetidp_fieldsplit_p_pc_type none \
691:         -fetidp_bddc_pc_bddc_use_deluxe_scaling -fetidp_bddc_pc_bddc_benign_trick -fetidp_bddc_pc_bddc_deluxe_singlemat \
692:         -fetidp_pc_discrete_harmonic -fetidp_harmonic_pc_factor_mat_solver_type petsc -fetidp_harmonic_pc_type cholesky \
693:         -fetidp_bddelta_pc_factor_mat_solver_type umfpack -fetidp_fieldsplit_lag_ksp_type preonly -fetidp_bddc_sub_schurs_mat_solver_type mumps -fetidp_bddc_sub_schurs_mat_mumps_icntl_14 100000 \
694:         -fetidp_bddelta_pc_factor_mat_ordering_type external \
695:         -fetidp_bddc_pc_bddc_dirichlet_pc_factor_mat_solver_type umfpack -fetidp_bddc_pc_bddc_neumann_pc_factor_mat_solver_type umfpack \
696:         -fetidp_bddc_pc_bddc_dirichlet_pc_factor_mat_ordering_type external -fetidp_bddc_pc_bddc_neumann_pc_factor_mat_ordering_type external
697:   test:
698:     suffix: 3d_q2_q1_fetidp
699:     requires: suitesparse
700:     nsize: 5
701:     args: -sol quadratic -dm_plex_simplex 0 -dm_plex_dim 3 -dm_plex_box_faces 2,2,2 -dm_refine 1 -dm_mat_type is -petscpartitioner_type simple -vel_petscspace_degree 2 -pres_petscspace_degree 1 -petscds_jac_pre 0 \
702:       -snes_error_if_not_converged \
703:       -ksp_type fetidp -ksp_rtol 1.0e-8 \
704:       -ksp_fetidp_saddlepoint -fetidp_ksp_type cg \
705:         -fetidp_fieldsplit_p_ksp_max_it 1 -fetidp_fieldsplit_p_ksp_type richardson -fetidp_fieldsplit_p_ksp_richardson_scale 2000 -fetidp_fieldsplit_p_pc_type none \
706:         -fetidp_pc_discrete_harmonic -fetidp_harmonic_pc_factor_mat_solver_type petsc -fetidp_harmonic_pc_type cholesky \
707:         -fetidp_bddc_pc_bddc_symmetric -fetidp_fieldsplit_lag_ksp_type preonly \
708:         -fetidp_bddc_pc_bddc_dirichlet_pc_factor_mat_solver_type umfpack -fetidp_bddc_pc_bddc_neumann_pc_factor_mat_solver_type umfpack \
709:         -fetidp_bddc_pc_bddc_dirichlet_pc_factor_mat_ordering_type external -fetidp_bddc_pc_bddc_neumann_pc_factor_mat_ordering_type external
710:   #   BDDC solvers (these solvers are quite inefficient, they are here to exercise the code)
711:   test:
712:     suffix: 2d_p2_p1_bddc
713:     nsize: 2
714:     requires: triangle !single
715:     args: -sol quadratic -dm_plex_box_faces 2,2,2 -dm_refine 1 -dm_mat_type is -petscpartitioner_type simple -vel_petscspace_degree 2 -pres_petscspace_degree 1 -petscds_jac_pre 0 \
716:       -snes_error_if_not_converged \
717:       -ksp_type gmres -ksp_gmres_restart 100 -ksp_rtol 1.0e-8 -ksp_error_if_not_converged \
718:         -pc_type bddc -pc_bddc_corner_selection -pc_bddc_dirichlet_pc_type svd -pc_bddc_neumann_pc_type svd -pc_bddc_coarse_redundant_pc_type svd
719:   #   Vanka
720:   test:
721:     suffix: 2d_q1_p0_vanka
722:     requires: double !complex
723:     args: -sol quadratic -dm_plex_simplex 0 -dm_refine 2 -vel_petscspace_degree 1 -pres_petscspace_degree 0 -petscds_jac_pre 0 \
724:       -snes_rtol 1.0e-4 \
725:       -ksp_type fgmres -ksp_atol 1e-5 -ksp_error_if_not_converged \
726:       -pc_type patch -pc_patch_partition_of_unity 0 -pc_patch_construct_codim 0 -pc_patch_construct_type vanka \
727:         -sub_ksp_type preonly -sub_pc_type lu
728:   test:
729:     suffix: 2d_q1_p0_vanka_denseinv
730:     requires: double !complex
731:     args: -sol quadratic -dm_plex_simplex 0 -dm_refine 2 -vel_petscspace_degree 1 -pres_petscspace_degree 0 -petscds_jac_pre 0 \
732:       -snes_rtol 1.0e-4 \
733:       -ksp_type fgmres -ksp_atol 1e-5 -ksp_error_if_not_converged \
734:       -pc_type patch -pc_patch_partition_of_unity 0 -pc_patch_construct_codim 0 -pc_patch_construct_type vanka \
735:         -pc_patch_dense_inverse -pc_patch_sub_mat_type seqdense
736:   #   Vanka smoother
737:   test:
738:     suffix: 2d_q1_p0_gmg_vanka
739:     requires: double !complex
740:     args: -sol quadratic -dm_plex_simplex 0 -dm_refine_hierarchy 2 -vel_petscspace_degree 1 -pres_petscspace_degree 0 -petscds_jac_pre 0 \
741:       -snes_rtol 1.0e-4 \
742:       -ksp_type fgmres -ksp_atol 1e-5 -ksp_error_if_not_converged \
743:       -pc_type mg \
744:         -mg_levels_ksp_type gmres -mg_levels_ksp_max_it 30 \
745:         -mg_levels_pc_type patch -mg_levels_pc_patch_partition_of_unity 0 -mg_levels_pc_patch_construct_codim 0 -mg_levels_pc_patch_construct_type vanka \
746:           -mg_levels_sub_ksp_type preonly -mg_levels_sub_pc_type lu \
747:         -mg_coarse_pc_type svd

749: TEST*/