Actual source code: ex17.c

  1: static char help[] = "Linear elasticity in 2d and 3d with finite elements.\n\
  2: We solve the elasticity problem in a rectangular\n\
  3: domain, using a parallel unstructured mesh (DMPLEX) to discretize it.\n\
  4: This example supports automatic convergence estimation\n\
  5: and eventually adaptivity.\n\n\n";

  7: /*
  8:   https://en.wikipedia.org/wiki/Linear_elasticity

 10:   Converting elastic constants:
 11:     lambda = E nu / ((1 + nu) (1 - 2 nu))
 12:     mu     = E / (2 (1 + nu))
 13: */

 15: #include <petscdmplex.h>
 16: #include <petscsnes.h>
 17: #include <petscds.h>
 18: #include <petscbag.h>
 19: #include <petscconvest.h>

 21: typedef enum {
 22:   SOL_VLAP_QUADRATIC,
 23:   SOL_ELAS_QUADRATIC,
 24:   SOL_VLAP_TRIG,
 25:   SOL_ELAS_TRIG,
 26:   SOL_ELAS_AXIAL_DISP,
 27:   SOL_ELAS_UNIFORM_STRAIN,
 28:   SOL_ELAS_GE,
 29:   SOL_MASS_QUADRATIC,
 30:   NUM_SOLUTION_TYPES
 31: } SolutionType;
 32: const char *solutionTypes[NUM_SOLUTION_TYPES + 1] = {"vlap_quad", "elas_quad", "vlap_trig", "elas_trig", "elas_axial_disp", "elas_uniform_strain", "elas_ge", "mass_quad", "unknown"};

 34: typedef enum {
 35:   DEFORM_NONE,
 36:   DEFORM_SHEAR,
 37:   DEFORM_STEP,
 38:   NUM_DEFORM_TYPES
 39: } DeformType;
 40: const char *deformTypes[NUM_DEFORM_TYPES + 1] = {"none", "shear", "step", "unknown"};

 42: typedef struct {
 43:   PetscScalar mu;     /* shear modulus */
 44:   PetscScalar lambda; /* Lame's first parameter */
 45:   PetscScalar N;      /* Tension force on right wall */
 46: } Parameter;

 48: typedef struct {
 49:   /* Domain and mesh definition */
 50:   char       dmType[256]; /* DM type for the solve */
 51:   DeformType deform;      /* Domain deformation type */
 52:   /* Problem definition */
 53:   SolutionType solType; /* Type of exact solution */
 54:   PetscBag     bag;     /* Problem parameters */
 55:   /* Solver definition */
 56:   PetscBool useNearNullspace; /* Use the rigid body modes as a near nullspace for AMG */
 57: } AppCtx;

 59: static PetscErrorCode zero(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
 60: {
 61:   PetscInt d;
 62:   for (d = 0; d < dim; ++d) u[d] = 0.0;
 63:   return PETSC_SUCCESS;
 64: }

 66: static PetscErrorCode ge_shift(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
 67: {
 68:   PetscInt d;
 69:   u[0] = 0.1;
 70:   for (d = 1; d < dim; ++d) u[d] = 0.0;
 71:   return PETSC_SUCCESS;
 72: }

 74: static PetscErrorCode quadratic_2d_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
 75: {
 76:   u[0] = x[0] * x[0];
 77:   u[1] = x[1] * x[1] - 2.0 * x[0] * x[1];
 78:   return PETSC_SUCCESS;
 79: }

 81: static PetscErrorCode quadratic_3d_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
 82: {
 83:   u[0] = x[0] * x[0];
 84:   u[1] = x[1] * x[1] - 2.0 * x[0] * x[1];
 85:   u[2] = x[2] * x[2] - 2.0 * x[1] * x[2];
 86:   return PETSC_SUCCESS;
 87: }

 89: /*
 90:   u = x^2
 91:   v = y^2 - 2xy
 92:   Delta <u,v> - f = <2, 2> - <2, 2>

 94:   u = x^2
 95:   v = y^2 - 2xy
 96:   w = z^2 - 2yz
 97:   Delta <u,v,w> - f = <2, 2, 2> - <2, 2, 2>
 98: */
 99: static void f0_vlap_quadratic_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
100: {
101:   PetscInt d;
102:   for (d = 0; d < dim; ++d) f0[d] += 2.0;
103: }

105: /*
106:   u = x^2
107:   v = y^2 - 2xy
108:   \varepsilon = / 2x     -y    \
109:                 \ -y   2y - 2x /
110:   Tr(\varepsilon) = div u = 2y
111:   div \sigma = \partial_i \lambda \delta_{ij} \varepsilon_{kk} + \partial_i 2\mu\varepsilon_{ij}
112:     = \lambda \partial_j (2y) + 2\mu < 2-1, 2 >
113:     = \lambda < 0, 2 > + \mu < 2, 4 >

115:   u = x^2
116:   v = y^2 - 2xy
117:   w = z^2 - 2yz
118:   \varepsilon = / 2x     -y       0   \
119:                 | -y   2y - 2x   -z   |
120:                 \  0     -z    2z - 2y/
121:   Tr(\varepsilon) = div u = 2z
122:   div \sigma = \partial_i \lambda \delta_{ij} \varepsilon_{kk} + \partial_i 2\mu\varepsilon_{ij}
123:     = \lambda \partial_j (2z) + 2\mu < 2-1, 2-1, 2 >
124:     = \lambda < 0, 0, 2 > + \mu < 2, 2, 4 >
125: */
126: static void f0_elas_quadratic_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
127: {
128:   const PetscReal mu     = PetscRealPart(constants[0]);
129:   const PetscReal lambda = PetscRealPart(constants[1]);

131:   for (PetscInt d = 0; d < dim - 1; ++d) f0[d] += 2.0 * mu;
132:   f0[dim - 1] += 2.0 * lambda + 4.0 * mu;
133: }

135: static void f0_mass_quadratic_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
136: {
137:   if (dim == 2) {
138:     f0[0] -= x[0] * x[0];
139:     f0[1] -= x[1] * x[1] - 2.0 * x[0] * x[1];
140:   } else {
141:     f0[0] -= x[0] * x[0];
142:     f0[1] -= x[1] * x[1] - 2.0 * x[0] * x[1];
143:     f0[2] -= x[2] * x[2] - 2.0 * x[1] * x[2];
144:   }
145: }

147: static PetscErrorCode trig_2d_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
148: {
149:   u[0] = PetscSinReal(2.0 * PETSC_PI * x[0]);
150:   u[1] = PetscSinReal(2.0 * PETSC_PI * x[1]) - 2.0 * x[0] * x[1];
151:   return PETSC_SUCCESS;
152: }

154: static PetscErrorCode trig_3d_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
155: {
156:   u[0] = PetscSinReal(2.0 * PETSC_PI * x[0]);
157:   u[1] = PetscSinReal(2.0 * PETSC_PI * x[1]) - 2.0 * x[0] * x[1];
158:   u[2] = PetscSinReal(2.0 * PETSC_PI * x[2]) - 2.0 * x[1] * x[2];
159:   return PETSC_SUCCESS;
160: }

162: /*
163:   u = sin(2 pi x)
164:   v = sin(2 pi y) - 2xy
165:   Delta <u,v> - f = <-4 pi^2 u, -4 pi^2 v> - <-4 pi^2 sin(2 pi x), -4 pi^2 sin(2 pi y)>

167:   u = sin(2 pi x)
168:   v = sin(2 pi y) - 2xy
169:   w = sin(2 pi z) - 2yz
170:   Delta <u,v,2> - f = <-4 pi^2 u, -4 pi^2 v, -4 pi^2 w> - <-4 pi^2 sin(2 pi x), -4 pi^2 sin(2 pi y), -4 pi^2 sin(2 pi z)>
171: */
172: static void f0_vlap_trig_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
173: {
174:   PetscInt d;
175:   for (d = 0; d < dim; ++d) f0[d] += -4.0 * PetscSqr(PETSC_PI) * PetscSinReal(2.0 * PETSC_PI * x[d]);
176: }

178: /*
179:   u = sin(2 pi x)
180:   v = sin(2 pi y) - 2xy
181:   \varepsilon = / 2 pi cos(2 pi x)             -y        \
182:                 \      -y          2 pi cos(2 pi y) - 2x /
183:   Tr(\varepsilon) = div u = 2 pi (cos(2 pi x) + cos(2 pi y)) - 2 x
184:   div \sigma = \partial_i \lambda \delta_{ij} \varepsilon_{kk} + \partial_i 2\mu\varepsilon_{ij}
185:     = \lambda \partial_j 2 pi (cos(2 pi x) + cos(2 pi y)) + 2\mu < -4 pi^2 sin(2 pi x) - 1, -4 pi^2 sin(2 pi y) >
186:     = \lambda < -4 pi^2 sin(2 pi x) - 2, -4 pi^2 sin(2 pi y) > + \mu < -8 pi^2 sin(2 pi x) - 2, -8 pi^2 sin(2 pi y) >

188:   u = sin(2 pi x)
189:   v = sin(2 pi y) - 2xy
190:   w = sin(2 pi z) - 2yz
191:   \varepsilon = / 2 pi cos(2 pi x)            -y                     0         \
192:                 |         -y       2 pi cos(2 pi y) - 2x            -z         |
193:                 \          0                  -z         2 pi cos(2 pi z) - 2y /
194:   Tr(\varepsilon) = div u = 2 pi (cos(2 pi x) + cos(2 pi y) + cos(2 pi z)) - 2 x - 2 y
195:   div \sigma = \partial_i \lambda \delta_{ij} \varepsilon_{kk} + \partial_i 2\mu\varepsilon_{ij}
196:     = \lambda \partial_j (2 pi (cos(2 pi x) + cos(2 pi y) + cos(2 pi z)) - 2 x - 2 y) + 2\mu < -4 pi^2 sin(2 pi x) - 1, -4 pi^2 sin(2 pi y) - 1, -4 pi^2 sin(2 pi z) >
197:     = \lambda < -4 pi^2 sin(2 pi x) - 2, -4 pi^2 sin(2 pi y) - 2, -4 pi^2 sin(2 pi z) > + 2\mu < -4 pi^2 sin(2 pi x) - 1, -4 pi^2 sin(2 pi y) - 1, -4 pi^2 sin(2 pi z) >
198: */
199: static void f0_elas_trig_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
200: {
201:   const PetscReal mu     = PetscRealPart(constants[0]);
202:   const PetscReal lambda = PetscRealPart(constants[1]);
203:   const PetscReal fact   = 4.0 * PetscSqr(PETSC_PI);

205:   for (PetscInt d = 0; d < dim; ++d) f0[d] += -(2.0 * mu + lambda) * fact * PetscSinReal(2.0 * PETSC_PI * x[d]) - (d < dim - 1 ? 2.0 * (mu + lambda) : 0.0);
206: }

208: static PetscErrorCode axial_disp_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
209: {
210:   AppCtx    *user = (AppCtx *)ctx;
211:   Parameter *param;

213:   PetscCall(PetscBagGetData(user->bag, &param));
214:   {
215:     const PetscReal mu     = PetscRealPart(param->mu);
216:     const PetscReal lambda = PetscRealPart(param->lambda);
217:     const PetscReal N      = PetscRealPart(param->N);

219:     u[0] = (3. * lambda * lambda + 8. * lambda * mu + 4 * mu * mu) / (4 * mu * (3 * lambda * lambda + 5. * lambda * mu + 2 * mu * mu)) * N * x[0];
220:     u[1] = 0.25 * lambda / mu / (lambda + mu) * N * x[1];
221:     for (PetscInt d = 2; d < dim; ++d) u[d] = 0.0;
222:   }
223:   return PETSC_SUCCESS;
224: }

226: /*
227:   We will pull/push on the right side of a block of linearly elastic material. The uniform traction conditions on the
228:   right side of the box will result in a uniform strain along x and y. The Neumann BC is given by

230:      n_i \sigma_{ij} = t_i

232:   u = (1/(2\mu) - 1) x
233:   v = -y
234:   f = 0
235:   t = <4\mu/\lambda (\lambda + \mu), 0>
236:   \varepsilon = / 1/(2\mu) - 1   0 \
237:                 \ 0             -1 /
238:   Tr(\varepsilon) = div u = 1/(2\mu) - 2
239:   div \sigma = \partial_i \lambda \delta_{ij} \varepsilon_{kk} + \partial_i 2\mu\varepsilon_{ij}
240:     = \lambda \partial_j (1/(2\mu) - 2) + 2\mu < 0, 0 >
241:     = \lambda < 0, 0 > + \mu < 0, 0 > = 0
242:   NBC =  <1,0> . <4\mu/\lambda (\lambda + \mu), 0> = 4\mu/\lambda (\lambda + \mu)

244:   u = x - 1/2
245:   v = 0
246:   w = 0
247:   \varepsilon = / x  0  0 \
248:                 | 0  0  0 |
249:                 \ 0  0  0 /
250:   Tr(\varepsilon) = div u = x
251:   div \sigma = \partial_i \lambda \delta_{ij} \varepsilon_{kk} + \partial_i 2\mu\varepsilon_{ij}
252:     = \lambda \partial_j x + 2\mu < 1, 0, 0 >
253:     = \lambda < 1, 0, 0 > + \mu < 2, 0, 0 >
254: */
255: static void f0_elas_axial_disp_bd_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
256: {
257:   const PetscReal N = PetscRealPart(constants[2]);

259:   f0[0] = N;
260: }

262: static PetscErrorCode uniform_strain_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
263: {
264:   const PetscReal eps_xx = 0.1;
265:   const PetscReal eps_xy = 0.3;
266:   const PetscReal eps_yy = 0.25;
267:   PetscInt        d;

269:   u[0] = eps_xx * x[0] + eps_xy * x[1];
270:   u[1] = eps_xy * x[0] + eps_yy * x[1];
271:   for (d = 2; d < dim; ++d) u[d] = 0.0;
272:   return PETSC_SUCCESS;
273: }

275: static void f0_mass_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
276: {
277:   const PetscInt Nc = dim;
278:   PetscInt       c;

280:   for (c = 0; c < Nc; ++c) f0[c] = u[c];
281: }

283: static void f1_vlap_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])
284: {
285:   const PetscInt Nc = dim;
286:   PetscInt       c, d;

288:   for (c = 0; c < Nc; ++c)
289:     for (d = 0; d < dim; ++d) f1[c * dim + d] += u_x[c * dim + d];
290: }

292: static void f1_elas_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])
293: {
294:   const PetscReal mu     = PetscRealPart(constants[0]);
295:   const PetscReal lambda = PetscRealPart(constants[1]);
296:   const PetscInt  Nc     = dim;

298:   for (PetscInt c = 0; c < Nc; ++c) {
299:     for (PetscInt d = 0; d < dim; ++d) {
300:       f1[c * dim + d] += mu * (u_x[c * dim + d] + u_x[d * dim + c]);
301:       f1[c * dim + c] += lambda * u_x[d * dim + d];
302:     }
303:   }
304: }

306: static void g0_mass_uu(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
307: {
308:   const PetscInt Nc = dim;

310:   for (PetscInt c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0;
311: }

313: static void g3_vlap_uu(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])
314: {
315:   const PetscInt Nc = dim;

317:   for (PetscInt c = 0; c < Nc; ++c) {
318:     for (PetscInt d = 0; d < dim; ++d) g3[((c * Nc + c) * dim + d) * dim + d] = 1.0;
319:   }
320: }

322: /*
323:   \partial_df \phi_fc g_{fc,gc,df,dg} \partial_dg \phi_gc

325:   \partial_df \phi_fc \lambda \delta_{fc,df} \sum_gc \partial_dg \phi_gc \delta_{gc,dg}
326:   = \partial_fc \phi_fc \sum_gc \partial_gc \phi_gc
327: */
328: static void g3_elas_uu(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])
329: {
330:   const PetscReal mu     = PetscRealPart(constants[0]);
331:   const PetscReal lambda = PetscRealPart(constants[1]);
332:   const PetscInt  Nc     = dim;

334:   for (PetscInt c = 0; c < Nc; ++c) {
335:     for (PetscInt d = 0; d < dim; ++d) {
336:       g3[((c * Nc + c) * dim + d) * dim + d] += mu;
337:       g3[((c * Nc + d) * dim + d) * dim + c] += mu;
338:       g3[((c * Nc + d) * dim + c) * dim + d] += lambda;
339:     }
340:   }
341: }

343: static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
344: {
345:   PetscInt sol = 0, def = 0;

347:   PetscFunctionBeginUser;
348:   options->deform           = DEFORM_NONE;
349:   options->solType          = SOL_VLAP_QUADRATIC;
350:   options->useNearNullspace = PETSC_TRUE;
351:   PetscCall(PetscStrncpy(options->dmType, DMPLEX, 256));

353:   PetscOptionsBegin(comm, "", "Linear Elasticity Problem Options", "DMPLEX");
354:   PetscCall(PetscOptionsEList("-deform_type", "Type of domain deformation", "ex17.c", deformTypes, NUM_DEFORM_TYPES, deformTypes[options->deform], &def, NULL));
355:   options->deform = (DeformType)def;
356:   PetscCall(PetscOptionsEList("-sol_type", "Type of exact solution", "ex17.c", solutionTypes, NUM_SOLUTION_TYPES, solutionTypes[options->solType], &sol, NULL));
357:   options->solType = (SolutionType)sol;
358:   PetscCall(PetscOptionsBool("-near_nullspace", "Use the rigid body modes as an AMG near nullspace", "ex17.c", options->useNearNullspace, &options->useNearNullspace, NULL));
359:   PetscCall(PetscOptionsFList("-dm_type", "Convert DMPlex to another format", "ex17.c", DMList, options->dmType, options->dmType, 256, NULL));
360:   PetscOptionsEnd();
361:   PetscFunctionReturn(PETSC_SUCCESS);
362: }

364: static PetscErrorCode SetupParameters(MPI_Comm comm, AppCtx *ctx)
365: {
366:   PetscBag   bag;
367:   Parameter *p;

369:   PetscFunctionBeginUser;
370:   /* setup PETSc parameter bag */
371:   PetscCall(PetscBagGetData(ctx->bag, &p));
372:   PetscCall(PetscBagSetName(ctx->bag, "par", "Elastic Parameters"));
373:   bag = ctx->bag;
374:   PetscCall(PetscBagRegisterScalar(bag, &p->mu, 1.0, "mu", "Shear Modulus, Pa"));
375:   PetscCall(PetscBagRegisterScalar(bag, &p->lambda, 1.0, "lambda", "Lame's first parameter, Pa"));
376:   PetscCall(PetscBagRegisterScalar(bag, &p->N, -1.0, "N", "Tension on right wall, Pa"));
377:   PetscCall(PetscBagSetFromOptions(bag));
378:   {
379:     PetscViewer       viewer;
380:     PetscViewerFormat format;
381:     PetscBool         flg;

383:     PetscCall(PetscOptionsCreateViewer(comm, NULL, NULL, "-param_view", &viewer, &format, &flg));
384:     if (flg) {
385:       PetscCall(PetscViewerPushFormat(viewer, format));
386:       PetscCall(PetscBagView(bag, viewer));
387:       PetscCall(PetscViewerFlush(viewer));
388:       PetscCall(PetscViewerPopFormat(viewer));
389:       PetscCall(PetscViewerDestroy(&viewer));
390:     }
391:   }
392:   PetscFunctionReturn(PETSC_SUCCESS);
393: }

395: static PetscErrorCode DMPlexDistortGeometry(DM dm)
396: {
397:   DM           cdm;
398:   DMLabel      label;
399:   Vec          coordinates;
400:   PetscScalar *coords;
401:   PetscReal    mid = 0.5;
402:   PetscInt     cdim, d, vStart, vEnd, v;

404:   PetscFunctionBeginUser;
405:   PetscCall(DMGetCoordinateDM(dm, &cdm));
406:   PetscCall(DMGetCoordinateDim(dm, &cdim));
407:   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
408:   PetscCall(DMGetLabel(dm, "marker", &label));
409:   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
410:   PetscCall(VecGetArrayWrite(coordinates, &coords));
411:   for (v = vStart; v < vEnd; ++v) {
412:     PetscScalar *pcoords, shift;
413:     PetscInt     val;

415:     PetscCall(DMLabelGetValue(label, v, &val));
416:     if (val >= 0) continue;
417:     PetscCall(DMPlexPointLocalRef(cdm, v, coords, &pcoords));
418:     shift = 0.2 * PetscAbsScalar(pcoords[0] - mid);
419:     shift = PetscRealPart(pcoords[0]) > mid ? shift : -shift;
420:     for (d = 1; d < cdim; ++d) pcoords[d] += shift;
421:   }
422:   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
423:   PetscFunctionReturn(PETSC_SUCCESS);
424: }

426: static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm)
427: {
428:   PetscFunctionBeginUser;
429:   PetscCall(DMCreate(comm, dm));
430:   PetscCall(DMSetType(*dm, DMPLEX));
431:   PetscCall(DMSetFromOptions(*dm));
432:   switch (user->deform) {
433:   case DEFORM_NONE:
434:     break;
435:   case DEFORM_SHEAR:
436:     PetscCall(DMPlexShearGeometry(*dm, DM_X, NULL));
437:     break;
438:   case DEFORM_STEP:
439:     PetscCall(DMPlexDistortGeometry(*dm));
440:     break;
441:   default:
442:     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid deformation type: %s (%d)", deformTypes[PetscMin(user->deform, NUM_DEFORM_TYPES)], user->deform);
443:   }
444:   PetscCall(DMSetApplicationContext(*dm, user));
445:   PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view"));
446:   PetscFunctionReturn(PETSC_SUCCESS);
447: }

449: static PetscErrorCode SetupPrimalProblem(DM dm, AppCtx *user)
450: {
451:   PetscErrorCode (*exact)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *);
452:   Parameter    *param;
453:   PetscDS       ds;
454:   PetscWeakForm wf;
455:   DMLabel       label;
456:   PetscInt      id, bd;
457:   PetscInt      dim;

459:   PetscFunctionBeginUser;
460:   PetscCall(DMGetDS(dm, &ds));
461:   PetscCall(PetscDSGetWeakForm(ds, &wf));
462:   PetscCall(PetscDSGetSpatialDimension(ds, &dim));
463:   PetscCall(PetscBagGetData(user->bag, &param));
464:   switch (user->solType) {
465:   case SOL_MASS_QUADRATIC:
466:     PetscCall(PetscDSSetResidual(ds, 0, f0_mass_u, NULL));
467:     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_mass_uu, NULL, NULL, NULL));
468:     PetscCall(PetscWeakFormSetIndexResidual(wf, NULL, 0, 0, 0, 1, f0_mass_quadratic_u, 0, NULL));
469:     switch (dim) {
470:     case 2:
471:       exact = quadratic_2d_u;
472:       break;
473:     case 3:
474:       exact = quadratic_3d_u;
475:       break;
476:     default:
477:       SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Invalid dimension: %" PetscInt_FMT, dim);
478:     }
479:     break;
480:   case SOL_VLAP_QUADRATIC:
481:     PetscCall(PetscDSSetResidual(ds, 0, f0_vlap_quadratic_u, f1_vlap_u));
482:     PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, g3_vlap_uu));
483:     switch (dim) {
484:     case 2:
485:       exact = quadratic_2d_u;
486:       break;
487:     case 3:
488:       exact = quadratic_3d_u;
489:       break;
490:     default:
491:       SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Invalid dimension: %" PetscInt_FMT, dim);
492:     }
493:     break;
494:   case SOL_ELAS_QUADRATIC:
495:     PetscCall(PetscDSSetResidual(ds, 0, f0_elas_quadratic_u, f1_elas_u));
496:     PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, g3_elas_uu));
497:     switch (dim) {
498:     case 2:
499:       exact = quadratic_2d_u;
500:       break;
501:     case 3:
502:       exact = quadratic_3d_u;
503:       break;
504:     default:
505:       SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Invalid dimension: %" PetscInt_FMT, dim);
506:     }
507:     break;
508:   case SOL_VLAP_TRIG:
509:     PetscCall(PetscDSSetResidual(ds, 0, f0_vlap_trig_u, f1_vlap_u));
510:     PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, g3_vlap_uu));
511:     switch (dim) {
512:     case 2:
513:       exact = trig_2d_u;
514:       break;
515:     case 3:
516:       exact = trig_3d_u;
517:       break;
518:     default:
519:       SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Invalid dimension: %" PetscInt_FMT, dim);
520:     }
521:     break;
522:   case SOL_ELAS_TRIG:
523:     PetscCall(PetscDSSetResidual(ds, 0, f0_elas_trig_u, f1_elas_u));
524:     PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, g3_elas_uu));
525:     switch (dim) {
526:     case 2:
527:       exact = trig_2d_u;
528:       break;
529:     case 3:
530:       exact = trig_3d_u;
531:       break;
532:     default:
533:       SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Invalid dimension: %" PetscInt_FMT, dim);
534:     }
535:     break;
536:   case SOL_ELAS_AXIAL_DISP:
537:     PetscCall(PetscDSSetResidual(ds, 0, NULL, f1_elas_u));
538:     PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, g3_elas_uu));
539:     id = dim == 3 ? 5 : 2;
540:     PetscCall(DMGetLabel(dm, "marker", &label));
541:     PetscCall(DMAddBoundary(dm, DM_BC_NATURAL, "right", label, 1, &id, 0, 0, NULL, (PetscVoidFn *)NULL, NULL, user, &bd));
542:     PetscCall(PetscDSGetBoundary(ds, bd, &wf, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL));
543:     PetscCall(PetscWeakFormSetIndexBdResidual(wf, label, id, 0, 0, 0, f0_elas_axial_disp_bd_u, 0, NULL));
544:     exact = axial_disp_u;
545:     break;
546:   case SOL_ELAS_UNIFORM_STRAIN:
547:     PetscCall(PetscDSSetResidual(ds, 0, NULL, f1_elas_u));
548:     PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, g3_elas_uu));
549:     exact = uniform_strain_u;
550:     break;
551:   case SOL_ELAS_GE:
552:     PetscCall(PetscDSSetResidual(ds, 0, NULL, f1_elas_u));
553:     PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, g3_elas_uu));
554:     exact = zero; /* No exact solution available */
555:     break;
556:   default:
557:     SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Invalid solution type: %s (%d)", solutionTypes[PetscMin(user->solType, NUM_SOLUTION_TYPES)], user->solType);
558:   }
559:   PetscCall(PetscDSSetExactSolution(ds, 0, exact, user));
560:   PetscCall(DMGetLabel(dm, "marker", &label));
561:   if (user->solType == SOL_ELAS_AXIAL_DISP) {
562:     PetscInt cmp;

564:     id  = dim == 3 ? 6 : 4;
565:     cmp = 0;
566:     PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "left", label, 1, &id, 0, 1, &cmp, (PetscVoidFn *)zero, NULL, user, NULL));
567:     cmp = dim == 3 ? 2 : 1;
568:     id  = dim == 3 ? 1 : 1;
569:     PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "bottom", label, 1, &id, 0, 1, &cmp, (PetscVoidFn *)zero, NULL, user, NULL));
570:     if (dim == 3) {
571:       cmp = 1;
572:       id  = 3;
573:       PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "front", label, 1, &id, 0, 1, &cmp, (PetscVoidFn *)zero, NULL, user, NULL));
574:     }
575:   } else if (user->solType == SOL_ELAS_GE) {
576:     PetscInt cmp;

578:     id = dim == 3 ? 6 : 4;
579:     PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "left", label, 1, &id, 0, 0, NULL, (PetscVoidFn *)zero, NULL, user, NULL));
580:     id  = dim == 3 ? 5 : 2;
581:     cmp = 0;
582:     PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "right", label, 1, &id, 0, 1, &cmp, (PetscVoidFn *)ge_shift, NULL, user, NULL));
583:   } else {
584:     id = 1;
585:     PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", label, 1, &id, 0, 0, NULL, (PetscVoidFn *)exact, NULL, user, NULL));
586:   }
587:   /* Setup constants */
588:   {
589:     PetscScalar constants[3];

591:     constants[0] = param->mu;     /* shear modulus, Pa */
592:     constants[1] = param->lambda; /* Lame's first parameter, Pa */
593:     constants[2] = param->N;      /* Tension on right wall, Pa */
594:     PetscCall(PetscDSSetConstants(ds, 3, constants));
595:   }
596:   PetscFunctionReturn(PETSC_SUCCESS);
597: }

599: static PetscErrorCode CreateElasticityNullSpace(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullspace)
600: {
601:   PetscFunctionBegin;
602:   PetscCall(DMPlexCreateRigidBody(dm, origField, nullspace));
603:   PetscFunctionReturn(PETSC_SUCCESS);
604: }

606: PetscErrorCode SetupFE(DM dm, const char name[], PetscErrorCode (*setup)(DM, AppCtx *), PetscCtx ctx)
607: {
608:   AppCtx        *user = (AppCtx *)ctx;
609:   DM             cdm  = dm;
610:   PetscFE        fe;
611:   char           prefix[PETSC_MAX_PATH_LEN];
612:   DMPolytopeType ct;
613:   PetscInt       dim, cStart;

615:   PetscFunctionBegin;
616:   /* Create finite element */
617:   PetscCall(DMGetDimension(dm, &dim));
618:   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
619:   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
620:   PetscCall(PetscSNPrintf(prefix, PETSC_MAX_PATH_LEN, "%s_", name));
621:   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, dim, ct, name ? prefix : NULL, -1, &fe));
622:   PetscCall(PetscObjectSetName((PetscObject)fe, name));
623:   /* Set discretization and boundary conditions for each mesh */
624:   PetscCall(DMSetField(dm, 0, NULL, (PetscObject)fe));
625:   PetscCall(DMCreateDS(dm));
626:   PetscCall((*setup)(dm, user));
627:   while (cdm) {
628:     PetscCall(DMCopyDisc(dm, cdm));
629:     if (user->useNearNullspace) PetscCall(DMSetNearNullSpaceConstructor(cdm, 0, CreateElasticityNullSpace));
630:     PetscCall(DMGetCoarseDM(cdm, &cdm));
631:   }
632:   PetscCall(PetscFEDestroy(&fe));
633:   PetscFunctionReturn(PETSC_SUCCESS);
634: }

636: int main(int argc, char **argv)
637: {
638:   DM     dm;   /* Problem specification */
639:   SNES   snes; /* Nonlinear solver */
640:   Vec    u;    /* Solutions */
641:   AppCtx user; /* User-defined work context */

643:   PetscFunctionBeginUser;
644:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
645:   PetscCall(ProcessOptions(PETSC_COMM_WORLD, &user));
646:   PetscCall(PetscBagCreate(PETSC_COMM_SELF, sizeof(Parameter), &user.bag));
647:   PetscCall(SetupParameters(PETSC_COMM_WORLD, &user));
648:   /* Primal system */
649:   PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));
650:   PetscCall(CreateMesh(PETSC_COMM_WORLD, &user, &dm));
651:   PetscCall(SNESSetDM(snes, dm));
652:   PetscCall(SetupFE(dm, "displacement", SetupPrimalProblem, &user));
653:   PetscCall(DMCreateGlobalVector(dm, &u));
654:   PetscCall(PetscObjectSetName((PetscObject)u, "displacement"));
655:   PetscCall(DMPlexSetSNESLocalFEM(dm, PETSC_FALSE, &user));
656:   PetscCall(SNESSetFromOptions(snes));
657:   PetscCall(DMSNESCheckFromOptions(snes, u));
658:   PetscCall(SNESSolve(snes, NULL, u));
659:   PetscCall(SNESGetSolution(snes, &u));
660:   PetscCall(VecViewFromOptions(u, NULL, "-displacement_view"));
661:   /* Cleanup */
662:   PetscCall(VecDestroy(&u));
663:   PetscCall(SNESDestroy(&snes));
664:   PetscCall(DMDestroy(&dm));
665:   PetscCall(PetscBagDestroy(&user.bag));
666:   PetscCall(PetscFinalize());
667:   return 0;
668: }

670: /*TEST

672:   testset:
673:     args: -dm_plex_box_faces 1,1,1

675:     test:
676:       suffix: 2d_p1_quad_vlap
677:       requires: triangle
678:       args: -displacement_petscspace_degree 1 -dm_refine 2 -convest_num_refine 3 -snes_convergence_estimate
679:     test:
680:       suffix: 2d_p2_quad_vlap
681:       requires: triangle
682:       args: -displacement_petscspace_degree 2 -dm_refine 2 -dmsnes_check .0001
683:     test:
684:       suffix: 2d_p3_quad_vlap
685:       requires: triangle
686:       args: -displacement_petscspace_degree 3 -dm_refine 2 -dmsnes_check .0001
687:     test:
688:       suffix: 2d_q1_quad_vlap
689:       args: -dm_plex_simplex 0 -displacement_petscspace_degree 1 -dm_refine 2 -convest_num_refine 3 -snes_convergence_estimate
690:     test:
691:       suffix: 2d_q2_quad_vlap
692:       args: -dm_plex_simplex 0 -displacement_petscspace_degree 2 -dm_refine 2 -dmsnes_check .0001
693:     test:
694:       suffix: 2d_q3_quad_vlap
695:       requires: !single
696:       args: -dm_plex_simplex 0 -displacement_petscspace_degree 3 -dm_refine 2 -dmsnes_check .0001
697:     test:
698:       suffix: 2d_p1_quad_elas
699:       requires: triangle
700:       args: -sol_type elas_quad -displacement_petscspace_degree 1 -dm_refine 2 -convest_num_refine 3 -snes_convergence_estimate
701:     test:
702:       suffix: 2d_p2_quad_elas
703:       requires: triangle
704:       args: -sol_type elas_quad -displacement_petscspace_degree 2 -dmsnes_check .0001
705:     test:
706:       suffix: 2d_p3_quad_elas
707:       requires: triangle
708:       args: -sol_type elas_quad -displacement_petscspace_degree 3 -dmsnes_check .0001
709:     test:
710:       suffix: 2d_q1_quad_elas
711:       args: -sol_type elas_quad -dm_plex_simplex 0 -displacement_petscspace_degree 1 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
712:     test:
713:       suffix: 2d_q1_quad_elas_shear
714:       args: -sol_type elas_quad -dm_plex_simplex 0 -deform_type shear -displacement_petscspace_degree 1 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
715:     test:
716:       suffix: 2d_q2_quad_elas
717:       args: -sol_type elas_quad -dm_plex_simplex 0 -displacement_petscspace_degree 2 -dmsnes_check .0001
718:     test:
719:       suffix: 2d_q2_quad_elas_shear
720:       args: -sol_type elas_quad -dm_plex_simplex 0 -deform_type shear -displacement_petscspace_degree 2 -dmsnes_check
721:     test:
722:       suffix: 2d_q3_quad_elas
723:       args: -sol_type elas_quad -dm_plex_simplex 0 -displacement_petscspace_degree 3 -dmsnes_check .0001
724:     test:
725:       suffix: 2d_q3_quad_elas_shear
726:       requires: !single
727:       args: -sol_type elas_quad -dm_plex_simplex 0 -deform_type shear -displacement_petscspace_degree 3 -dmsnes_check

729:     test:
730:       suffix: 3d_p1_quad_vlap
731:       requires: ctetgen
732:       args: -dm_plex_dim 3 -dm_refine 1 -displacement_petscspace_degree 1 -convest_num_refine 2 -snes_convergence_estimate
733:     test:
734:       suffix: 3d_p2_quad_vlap
735:       requires: ctetgen
736:       args: -dm_plex_dim 3 -displacement_petscspace_degree 2 -dm_refine 1 -dmsnes_check .0001
737:     test:
738:       suffix: 3d_p3_quad_vlap
739:       requires: ctetgen
740:       args: -dm_plex_dim 3 -displacement_petscspace_degree 3 -dm_refine 0 -dmsnes_check .0001
741:     test:
742:       suffix: 3d_q1_quad_vlap
743:       args: -dm_plex_dim 3 -dm_plex_box_faces 2,2,2 -dm_plex_simplex 0 -displacement_petscspace_degree 1 -convest_num_refine 2 -snes_convergence_estimate
744:     test:
745:       suffix: 3d_q2_quad_vlap
746:       args: -dm_plex_dim 3 -dm_plex_simplex 0 -displacement_petscspace_degree 2 -dm_refine 1 -dmsnes_check .0001
747:     test:
748:       suffix: 3d_q3_quad_vlap
749:       args: -dm_plex_dim 3 -dm_plex_simplex 0 -displacement_petscspace_degree 3 -dm_refine 0 -dmsnes_check .0001
750:     test:
751:       suffix: 3d_p1_quad_elas
752:       requires: ctetgen
753:       args: -sol_type elas_quad -dm_plex_dim 3 -dm_refine 1 -displacement_petscspace_degree 1 -convest_num_refine 2 -snes_convergence_estimate
754:     test:
755:       suffix: 3d_p2_quad_elas
756:       requires: ctetgen
757:       args: -sol_type elas_quad -dm_plex_dim 3 -displacement_petscspace_degree 2 -dm_refine 1 -dmsnes_check .0001
758:     test:
759:       suffix: 3d_p3_quad_elas
760:       requires: ctetgen
761:       args: -sol_type elas_quad -dm_plex_dim 3 -displacement_petscspace_degree 3 -dm_refine 0 -dmsnes_check .0001
762:     test:
763:       suffix: 3d_q1_quad_elas
764:       args: -sol_type elas_quad -dm_plex_dim 3 -dm_plex_box_faces 2,2,2 -dm_plex_simplex 0 -displacement_petscspace_degree 1 -convest_num_refine 2 -snes_convergence_estimate
765:     test:
766:       suffix: 3d_q2_quad_elas
767:       args: -sol_type elas_quad -dm_plex_dim 3 -dm_plex_simplex 0 -displacement_petscspace_degree 2 -dm_refine 1 -dmsnes_check .0001
768:     test:
769:       suffix: 3d_q3_quad_elas
770:       requires: !single
771:       args: -sol_type elas_quad -dm_plex_dim 3 -dm_plex_simplex 0 -displacement_petscspace_degree 3 -dm_refine 0 -dmsnes_check .0001

773:     test:
774:       suffix: 2d_p1_trig_vlap
775:       requires: triangle
776:       args: -sol_type vlap_trig -displacement_petscspace_degree 1 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
777:     test:
778:       suffix: 2d_p2_trig_vlap
779:       requires: triangle
780:       args: -sol_type vlap_trig -displacement_petscspace_degree 2 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
781:     test:
782:       suffix: 2d_p3_trig_vlap
783:       requires: triangle
784:       args: -sol_type vlap_trig -displacement_petscspace_degree 3 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
785:     test:
786:       suffix: 2d_q1_trig_vlap
787:       args: -sol_type vlap_trig -dm_plex_simplex 0 -displacement_petscspace_degree 1 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
788:     test:
789:       suffix: 2d_q2_trig_vlap
790:       args: -sol_type vlap_trig -dm_plex_simplex 0 -displacement_petscspace_degree 2 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
791:     test:
792:       suffix: 2d_q3_trig_vlap
793:       args: -sol_type vlap_trig -dm_plex_simplex 0 -displacement_petscspace_degree 3 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
794:     test:
795:       suffix: 2d_p1_trig_elas
796:       requires: triangle
797:       args: -sol_type elas_trig -displacement_petscspace_degree 1 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
798:     test:
799:       suffix: 2d_p2_trig_elas
800:       requires: triangle
801:       args: -sol_type elas_trig -displacement_petscspace_degree 2 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
802:     test:
803:       suffix: 2d_p3_trig_elas
804:       requires: triangle
805:       args: -sol_type elas_trig -displacement_petscspace_degree 3 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
806:     test:
807:       suffix: 2d_q1_trig_elas
808:       args: -sol_type elas_trig -dm_plex_simplex 0 -displacement_petscspace_degree 1 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
809:     test:
810:       suffix: 2d_q1_trig_elas_shear
811:       args: -sol_type elas_trig -dm_plex_simplex 0 -deform_type shear -displacement_petscspace_degree 1 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
812:     test:
813:       suffix: 2d_q2_trig_elas
814:       args: -sol_type elas_trig -dm_plex_simplex 0 -displacement_petscspace_degree 2 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
815:     test:
816:       suffix: 2d_q2_trig_elas_shear
817:       args: -sol_type elas_trig -dm_plex_simplex 0 -deform_type shear -displacement_petscspace_degree 2 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
818:     test:
819:       suffix: 2d_q3_trig_elas
820:       args: -sol_type elas_trig -dm_plex_simplex 0 -displacement_petscspace_degree 3 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate
821:     test:
822:       suffix: 2d_q3_trig_elas_shear
823:       args: -sol_type elas_trig -dm_plex_simplex 0 -deform_type shear -displacement_petscspace_degree 3 -dm_refine 1 -convest_num_refine 3 -snes_convergence_estimate

825:     test:
826:       suffix: 3d_p1_trig_vlap
827:       requires: ctetgen
828:       args: -sol_type vlap_trig -dm_plex_dim 3 -dm_refine 1 -displacement_petscspace_degree 1 -convest_num_refine 2 -snes_convergence_estimate
829:     test:
830:       suffix: 3d_p2_trig_vlap
831:       requires: ctetgen
832:       args: -sol_type vlap_trig -dm_plex_dim 3 -displacement_petscspace_degree 2 -dm_refine 0 -convest_num_refine 1 -snes_convergence_estimate
833:     test:
834:       suffix: 3d_p3_trig_vlap
835:       requires: ctetgen
836:       args: -sol_type vlap_trig -dm_plex_dim 3 -displacement_petscspace_degree 3 -dm_refine 0 -convest_num_refine 1 -snes_convergence_estimate
837:     test:
838:       suffix: 3d_q1_trig_vlap
839:       args: -sol_type vlap_trig -dm_plex_dim 3 -dm_plex_box_faces 2,2,2 -dm_plex_simplex 0 -displacement_petscspace_degree 1 -convest_num_refine 2 -snes_convergence_estimate
840:     test:
841:       suffix: 3d_q2_trig_vlap
842:       args: -sol_type vlap_trig -dm_plex_dim 3 -dm_plex_simplex 0 -displacement_petscspace_degree 2 -dm_refine 0 -convest_num_refine 1 -snes_convergence_estimate
843:     test:
844:       suffix: 3d_q3_trig_vlap
845:       requires: !__float128
846:       args: -sol_type vlap_trig -dm_plex_dim 3 -dm_plex_simplex 0 -displacement_petscspace_degree 3 -dm_refine 0 -convest_num_refine 1 -snes_convergence_estimate
847:     test:
848:       suffix: 3d_p1_trig_elas
849:       requires: ctetgen
850:       args: -sol_type elas_trig -dm_plex_dim 3 -dm_refine 1 -displacement_petscspace_degree 1 -convest_num_refine 2 -snes_convergence_estimate
851:     test:
852:       suffix: 3d_p2_trig_elas
853:       requires: ctetgen
854:       args: -sol_type elas_trig -dm_plex_dim 3 -displacement_petscspace_degree 2 -dm_refine 0 -convest_num_refine 1 -snes_convergence_estimate
855:     test:
856:       suffix: 3d_p3_trig_elas
857:       requires: ctetgen
858:       args: -sol_type elas_trig -dm_plex_dim 3 -displacement_petscspace_degree 3 -dm_refine 0 -convest_num_refine 1 -snes_convergence_estimate
859:     test:
860:       suffix: 3d_q1_trig_elas
861:       args: -sol_type elas_trig -dm_plex_dim 3 -dm_plex_box_faces 2,2,2 -dm_plex_simplex 0 -displacement_petscspace_degree 1 -convest_num_refine 2 -snes_convergence_estimate
862:     test:
863:       suffix: 3d_q2_trig_elas
864:       args: -sol_type elas_trig -dm_plex_dim 3 -dm_plex_simplex 0 -displacement_petscspace_degree 2 -dm_refine 0 -convest_num_refine 1 -snes_convergence_estimate
865:     test:
866:       suffix: 3d_q3_trig_elas
867:       requires: !__float128
868:       args: -sol_type elas_trig -dm_plex_dim 3 -dm_plex_simplex 0 -displacement_petscspace_degree 3 -dm_refine 0 -convest_num_refine 1 -snes_convergence_estimate

870:     test:
871:       suffix: 2d_p1_axial_elas
872:       requires: triangle
873:       args: -sol_type elas_axial_disp -displacement_petscspace_degree 1 -dm_plex_separate_marker -dm_refine 2 -dmsnes_check .0001 -pc_type lu
874:     test:
875:       suffix: 2d_p2_axial_elas
876:       requires: triangle
877:       args: -sol_type elas_axial_disp -displacement_petscspace_degree 2 -dm_plex_separate_marker -dmsnes_check .0001 -pc_type lu
878:     test:
879:       suffix: 2d_p3_axial_elas
880:       requires: triangle
881:       args: -sol_type elas_axial_disp -displacement_petscspace_degree 3 -dm_plex_separate_marker -dmsnes_check .0001 -pc_type lu
882:     test:
883:       suffix: 2d_q1_axial_elas
884:       args: -sol_type elas_axial_disp -dm_plex_simplex 0 -displacement_petscspace_degree 1 -dm_plex_separate_marker -dm_refine 1 -dmsnes_check .0001 -pc_type lu
885:     test:
886:       suffix: 2d_q2_axial_elas
887:       args: -sol_type elas_axial_disp -dm_plex_simplex 0 -displacement_petscspace_degree 2 -dm_plex_separate_marker -dmsnes_check .0001 -pc_type lu
888:     test:
889:       suffix: 2d_q3_axial_elas
890:       args: -sol_type elas_axial_disp -dm_plex_simplex 0 -displacement_petscspace_degree 3 -dm_plex_separate_marker -dmsnes_check .0001 -pc_type lu

892:     test:
893:       suffix: 2d_p1_uniform_elas
894:       requires: triangle
895:       args: -sol_type elas_uniform_strain -displacement_petscspace_degree 1 -dm_refine 2 -dmsnes_check .0001 -pc_type lu
896:     test:
897:       suffix: 2d_p2_uniform_elas
898:       requires: triangle
899:       args: -sol_type elas_uniform_strain -displacement_petscspace_degree 2 -dm_refine 2 -dmsnes_check .0001 -pc_type lu
900:     test:
901:       suffix: 2d_p3_uniform_elas
902:       requires: triangle
903:       args: -sol_type elas_uniform_strain -displacement_petscspace_degree 3 -dm_refine 2 -dmsnes_check .0001 -pc_type lu
904:     test:
905:       suffix: 2d_q1_uniform_elas
906:       args: -sol_type elas_uniform_strain -dm_plex_simplex 0 -displacement_petscspace_degree 1 -dm_refine 2 -dmsnes_check .0001 -pc_type lu
907:     test:
908:       suffix: 2d_q2_uniform_elas
909:       requires: !single
910:       args: -sol_type elas_uniform_strain -dm_plex_simplex 0 -displacement_petscspace_degree 2 -dm_refine 2 -dmsnes_check .0001 -pc_type lu
911:     test:
912:       suffix: 2d_q3_uniform_elas
913:       requires: !single
914:       args: -sol_type elas_uniform_strain -dm_plex_simplex 0 -displacement_petscspace_degree 3 -dm_refine 2 -dmsnes_check .0001 -pc_type lu
915:     test:
916:       suffix: 2d_p1_uniform_elas_step
917:       requires: triangle
918:       args: -sol_type elas_uniform_strain -deform_type step -displacement_petscspace_degree 1 -dm_refine 2 -dmsnes_check .0001 -pc_type lu

920:   testset:
921:     args: -dm_plex_simplex 0 -dm_plex_box_faces 3,3 -deform_type step -displacement_petscspace_degree 1 -dmsnes_check .0001 -pc_type lu

923:     test:
924:       suffix: 2d_q1_uniform_elas_step
925:       args: -sol_type elas_uniform_strain -dm_refine 2
926:     test:
927:       suffix: 2d_q1_quad_vlap_step
928:       args:
929:     test:
930:       suffix: 2d_q2_quad_vlap_step
931:       args: -displacement_petscspace_degree 2
932:     test:
933:       suffix: 2d_q1_quad_mass_step
934:       args: -sol_type mass_quad

936:   testset:
937:     filter: grep -v "variant HERMITIAN"
938:     args: -dm_plex_dim 3 -dm_plex_simplex 0 -dm_plex_box_lower -5,-5,-0.25 -dm_plex_box_upper 5,5,0.25 \
939:           -dm_plex_box_faces 5,5,2 -dm_plex_separate_marker -dm_refine 0 -petscpartitioner_type simple \
940:           -sol_type elas_ge

942:     test:
943:       suffix: ge_q1_0
944:       args: -displacement_petscspace_degree 1 \
945:             -snes_max_it 2 -snes_rtol 1.e-10 \
946:             -ksp_type cg -ksp_rtol 1.e-10 -ksp_max_it 100 -ksp_norm_type unpreconditioned \
947:             -pc_type gamg -pc_gamg_type agg -pc_gamg_agg_nsmooths 1 \
948:               -pc_gamg_coarse_eq_limit 10 -pc_gamg_reuse_interpolation true \
949:               -pc_gamg_threshold 0.05 -pc_gamg_threshold_scale .0 \
950:               -mg_levels_ksp_max_it 2 -mg_levels_ksp_type chebyshev -mg_levels_ksp_chebyshev_esteig 0,0.05,0,1.1 -mg_levels_pc_type jacobi \
951:               -matptap_via scalable
952:       output_file: output/empty.out
953:     test:
954:       suffix: ge_q1_gmg
955:       args: -displacement_petscspace_degree 1 \
956:             -dm_plex_box_faces 2,2 -dm_refine_hierarchy 3 \
957:             -snes_max_it 2 -snes_rtol 1.e-10 \
958:             -ksp_type cg -ksp_rtol 1.e-10 -ksp_max_it 100 -ksp_norm_type unpreconditioned \
959:             -pc_type mg -pc_mg_type full \
960:               -mg_levels_ksp_max_it 4 -mg_levels_esteig_ksp_type cg \
961:               -mg_levels_esteig_ksp_max_it 10 -mg_levels_ksp_chebyshev_esteig 0,0.1,0,1.1 \
962:               -mg_levels_pc_type jacobi
963:       output_file: output/empty.out
964:     test:
965:       nsize: 5
966:       suffix: ge_q1_gdsw
967:       args: -snes_max_it 1 -ksp_type cg -ksp_norm_type natural -displacement_petscspace_degree 1 -snes_monitor_short -ksp_monitor_short -pc_type mg -pc_mg_adapt_interp_coarse_space gdsw -pc_mg_levels 2 -pc_mg_galerkin -mg_levels_pc_type bjacobi -mg_levels_esteig_ksp_type cg -mg_levels_sub_pc_type icc -mg_coarse_redundant_pc_type cholesky -ksp_view

969: TEST*/