xref: /petsc/src/dm/dt/fe/tests/ex3.c (revision e239af90ce05a1392760c22063b12a16a0c1567a)
1d21efd2eSMatthew G. Knepley static const char help[] = "Tests for determining whether a new finite element works";
2d21efd2eSMatthew G. Knepley 
3d21efd2eSMatthew G. Knepley /*
4d21efd2eSMatthew G. Knepley   Use -interpolation_view and -l2_projection_view to look at the interpolants.
5d21efd2eSMatthew G. Knepley */
6d21efd2eSMatthew G. Knepley 
7d21efd2eSMatthew G. Knepley #include <petscdmplex.h>
8d21efd2eSMatthew G. Knepley #include <petscfe.h>
9d21efd2eSMatthew G. Knepley #include <petscds.h>
10d21efd2eSMatthew G. Knepley #include <petscsnes.h>
11d21efd2eSMatthew G. Knepley 
12d21efd2eSMatthew G. Knepley static void constant(PetscInt dim, PetscInt Nf, PetscInt NfAux,
13d21efd2eSMatthew G. Knepley                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
14d21efd2eSMatthew G. Knepley                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
15d21efd2eSMatthew G. Knepley                      PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
16d21efd2eSMatthew G. Knepley {
17d21efd2eSMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
18d21efd2eSMatthew G. Knepley   for (PetscInt c = 0; c < Nc; ++c) f0[c] += 5.;
19d21efd2eSMatthew G. Knepley }
20d21efd2eSMatthew G. Knepley 
21d21efd2eSMatthew G. Knepley static void linear(PetscInt dim, PetscInt Nf, PetscInt NfAux,
22d21efd2eSMatthew G. Knepley                    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
23d21efd2eSMatthew G. Knepley                    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
24d21efd2eSMatthew G. Knepley                    PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
25d21efd2eSMatthew G. Knepley {
26d21efd2eSMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
27d21efd2eSMatthew G. Knepley   for (PetscInt c = 0; c < Nc; ++c) f0[c] += 5.*x[c];
28d21efd2eSMatthew G. Knepley }
29d21efd2eSMatthew G. Knepley 
30d21efd2eSMatthew G. Knepley static void quadratic(PetscInt dim, PetscInt Nf, PetscInt NfAux,
31d21efd2eSMatthew G. Knepley                       const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
32d21efd2eSMatthew G. Knepley                       const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
33d21efd2eSMatthew G. Knepley                       PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
34d21efd2eSMatthew G. Knepley {
35d21efd2eSMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
36d21efd2eSMatthew G. Knepley   for (PetscInt c = 0; c < Nc; ++c) f0[c] += 5.*x[c]*x[c];
37d21efd2eSMatthew G. Knepley }
38d21efd2eSMatthew G. Knepley 
39d21efd2eSMatthew G. Knepley static void trig(PetscInt dim, PetscInt Nf, PetscInt NfAux,
40d21efd2eSMatthew G. Knepley                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
41d21efd2eSMatthew G. Knepley                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
42d21efd2eSMatthew G. Knepley                  PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
43d21efd2eSMatthew G. Knepley {
44d21efd2eSMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
45d21efd2eSMatthew G. Knepley   for (PetscInt c = 0; c < Nc; ++c) f0[c] += PetscCosReal(2.*PETSC_PI*x[c]);
46d21efd2eSMatthew G. Knepley }
47d21efd2eSMatthew G. Knepley 
48*e239af90SMatthew G. Knepley /*
49*e239af90SMatthew G. Knepley  The prime basis for the Wheeler-Yotov-Xue prism.
50*e239af90SMatthew G. Knepley  */
51*e239af90SMatthew G. Knepley static void prime(PetscInt dim, PetscInt Nf, PetscInt NfAux,
52*e239af90SMatthew G. Knepley                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
53*e239af90SMatthew G. Knepley                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
54*e239af90SMatthew G. Knepley                   PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
55*e239af90SMatthew G. Knepley {
56*e239af90SMatthew G. Knepley   PetscReal x = X[0], y = X[1], z = X[2], b = 1 + x + y + z;
57*e239af90SMatthew G. Knepley   f0[0] += b + 2.0*x*z + 2.0*y*z + x*y + x*x;
58*e239af90SMatthew G. Knepley   f0[1] += b + 2.0*x*z + 2.0*y*z + x*y + y*y;
59*e239af90SMatthew G. Knepley   f0[2] += b - 3.0*x*z - 3.0*y*z -   2.0*z*z;
60*e239af90SMatthew G. Knepley }
61*e239af90SMatthew G. Knepley 
62*e239af90SMatthew G. Knepley static const char    *names[]     = {"constant", "linear", "quadratic", "trig", "prime"};
63*e239af90SMatthew G. Knepley static PetscPointFunc functions[] = { constant,   linear,   quadratic,   trig,   prime };
64d21efd2eSMatthew G. Knepley 
65d21efd2eSMatthew G. Knepley typedef struct {
66d21efd2eSMatthew G. Knepley   PetscPointFunc exactSol;
67*e239af90SMatthew G. Knepley   PetscReal shear,flatten;
68d21efd2eSMatthew G. Knepley } AppCtx;
69d21efd2eSMatthew G. Knepley 
70d21efd2eSMatthew G. Knepley static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
71d21efd2eSMatthew G. Knepley {
72d21efd2eSMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN] = "constant";
73d21efd2eSMatthew G. Knepley   PetscInt       Nfunc = sizeof(names)/sizeof(char *), i;
74d21efd2eSMatthew G. Knepley   PetscErrorCode ierr;
75d21efd2eSMatthew G. Knepley 
76d21efd2eSMatthew G. Knepley   PetscFunctionBeginUser;
77d21efd2eSMatthew G. Knepley   options->exactSol = NULL;
78*e239af90SMatthew G. Knepley   options->shear    = 0.;
79*e239af90SMatthew G. Knepley   options->flatten  = 1.;
80d21efd2eSMatthew G. Knepley 
81d21efd2eSMatthew G. Knepley   ierr = PetscOptionsBegin(comm, "", "FE Test Options", "PETSCFE");CHKERRQ(ierr);
82d21efd2eSMatthew G. Knepley   ierr = PetscOptionsString("-func", "Function to project into space", "", name, name, PETSC_MAX_PATH_LEN, NULL);CHKERRQ(ierr);
83*e239af90SMatthew G. Knepley   ierr = PetscOptionsReal("-shear", "Factor by which to shear along the x-direction", "", options->shear, &(options->shear), NULL);CHKERRQ(ierr);
84*e239af90SMatthew G. Knepley   ierr = PetscOptionsReal("-flatten", "Factor by which to flatten", "", options->flatten, &(options->flatten), NULL);CHKERRQ(ierr);
85d21efd2eSMatthew G. Knepley   ierr = PetscOptionsEnd();CHKERRQ(ierr);
86d21efd2eSMatthew G. Knepley 
87d21efd2eSMatthew G. Knepley   for (i = 0; i < Nfunc; ++i) {
88d21efd2eSMatthew G. Knepley     PetscBool flg;
89d21efd2eSMatthew G. Knepley 
90d21efd2eSMatthew G. Knepley     ierr = PetscStrcmp(name, names[i], &flg);CHKERRQ(ierr);
91d21efd2eSMatthew G. Knepley     if (flg) {options->exactSol = functions[i]; break;}
92d21efd2eSMatthew G. Knepley   }
93*e239af90SMatthew G. Knepley   PetscCheck(options->exactSol, comm, PETSC_ERR_ARG_WRONG, "Invalid test function %s", name);
94d21efd2eSMatthew G. Knepley   PetscFunctionReturn(0);
95d21efd2eSMatthew G. Knepley }
96d21efd2eSMatthew G. Knepley 
97d21efd2eSMatthew G. Knepley /* The exact solution is the negative of the f0 contribution */
98d21efd2eSMatthew G. Knepley static PetscErrorCode exactSolution(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
99d21efd2eSMatthew G. Knepley {
100d21efd2eSMatthew G. Knepley   AppCtx  *user    = (AppCtx *) ctx;
101*e239af90SMatthew G. Knepley   PetscInt uOff[2] = {0, Nc};
102d21efd2eSMatthew G. Knepley 
103d21efd2eSMatthew G. Knepley   user->exactSol(dim, 1, 0, uOff, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, time, x, 0, NULL, u);
104d21efd2eSMatthew G. Knepley   for (PetscInt c = 0; c < Nc; ++c) u[c] *= -1.;
105d21efd2eSMatthew G. Knepley   return 0;
106d21efd2eSMatthew G. Knepley }
107d21efd2eSMatthew G. Knepley 
108d21efd2eSMatthew G. Knepley static void f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
109d21efd2eSMatthew G. Knepley                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
110d21efd2eSMatthew G. Knepley                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
111d21efd2eSMatthew G. Knepley                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
112d21efd2eSMatthew G. Knepley {
113d21efd2eSMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
114d21efd2eSMatthew G. Knepley   for (PetscInt c = 0; c < Nc; ++c) f0[c] += u[c];
115d21efd2eSMatthew G. Knepley }
116d21efd2eSMatthew G. Knepley 
117d21efd2eSMatthew G. Knepley static void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
118d21efd2eSMatthew G. Knepley                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
119d21efd2eSMatthew G. Knepley                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
120d21efd2eSMatthew G. Knepley                PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
121d21efd2eSMatthew G. Knepley {
122d21efd2eSMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
123d21efd2eSMatthew G. Knepley   for (PetscInt c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0;
124d21efd2eSMatthew G. Knepley }
125d21efd2eSMatthew G. Knepley 
126d21efd2eSMatthew G. Knepley static PetscErrorCode SetupProblem(DM dm, AppCtx *user)
127d21efd2eSMatthew G. Knepley {
128d21efd2eSMatthew G. Knepley   PetscDS        ds;
129d21efd2eSMatthew G. Knepley   PetscWeakForm  wf;
130d21efd2eSMatthew G. Knepley   PetscErrorCode ierr;
131d21efd2eSMatthew G. Knepley 
132d21efd2eSMatthew G. Knepley   PetscFunctionBeginUser;
133d21efd2eSMatthew G. Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
134d21efd2eSMatthew G. Knepley   ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr);
135d21efd2eSMatthew G. Knepley   ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, 0, 0, 0, f0, 0, NULL);CHKERRQ(ierr);
136d21efd2eSMatthew G. Knepley   ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, 0, 0, 1, user->exactSol, 0, NULL);CHKERRQ(ierr);
137d21efd2eSMatthew G. Knepley   ierr = PetscWeakFormSetIndexJacobian(wf, NULL, 0, 0, 0, 0, 0, g0, 0, NULL, 0, NULL, 0, NULL);CHKERRQ(ierr);
138d21efd2eSMatthew G. Knepley   ierr = PetscDSSetExactSolution(ds, 0, exactSolution, user);CHKERRQ(ierr);
139d21efd2eSMatthew G. Knepley   PetscFunctionReturn(0);
140d21efd2eSMatthew G. Knepley }
141d21efd2eSMatthew G. Knepley 
142d21efd2eSMatthew G. Knepley static PetscErrorCode SetupDiscretization(DM dm, const char name[], AppCtx *user)
143d21efd2eSMatthew G. Knepley {
144d21efd2eSMatthew G. Knepley   DM             cdm = dm;
145d21efd2eSMatthew G. Knepley   PetscFE        fe;
146d21efd2eSMatthew G. Knepley   char           prefix[PETSC_MAX_PATH_LEN];
147d21efd2eSMatthew G. Knepley   PetscErrorCode ierr;
148d21efd2eSMatthew G. Knepley 
149d21efd2eSMatthew G. Knepley   PetscFunctionBeginUser;
150d21efd2eSMatthew G. Knepley   ierr = PetscSNPrintf(prefix, PETSC_MAX_PATH_LEN, "%s_", name);CHKERRQ(ierr);
151d21efd2eSMatthew G. Knepley   ierr = DMCreateFEDefault(dm, 1, name ? prefix : NULL, -1, &fe);CHKERRQ(ierr);
152d21efd2eSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) fe, name ? name : "Solution");CHKERRQ(ierr);
153d21efd2eSMatthew G. Knepley   /* Set discretization and boundary conditions for each mesh */
154d21efd2eSMatthew G. Knepley   ierr = DMSetField(dm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr);
155d21efd2eSMatthew G. Knepley   ierr = DMCreateDS(dm);CHKERRQ(ierr);
156d21efd2eSMatthew G. Knepley   ierr = SetupProblem(dm, user);CHKERRQ(ierr);
157d21efd2eSMatthew G. Knepley   while (cdm) {
158d21efd2eSMatthew G. Knepley     ierr = DMCopyDisc(dm, cdm);CHKERRQ(ierr);
159d21efd2eSMatthew G. Knepley     ierr = DMGetCoarseDM(cdm, &cdm);CHKERRQ(ierr);
160d21efd2eSMatthew G. Knepley   }
161d21efd2eSMatthew G. Knepley   ierr = PetscFEDestroy(&fe);CHKERRQ(ierr);
162d21efd2eSMatthew G. Knepley   PetscFunctionReturn(0);
163d21efd2eSMatthew G. Knepley }
164d21efd2eSMatthew G. Knepley 
165d21efd2eSMatthew G. Knepley /* This test tells us whether the given function is contained in the approximation space */
166d21efd2eSMatthew G. Knepley static PetscErrorCode CheckInterpolation(DM dm, AppCtx *user)
167d21efd2eSMatthew G. Knepley {
168d21efd2eSMatthew G. Knepley   PetscSimplePointFunc exactSol[1];
169d21efd2eSMatthew G. Knepley   void                *exactCtx[1];
170d21efd2eSMatthew G. Knepley   PetscDS              ds;
171d21efd2eSMatthew G. Knepley   Vec                  u;
172d21efd2eSMatthew G. Knepley   PetscReal            error, tol = PETSC_SMALL;
173d21efd2eSMatthew G. Knepley   MPI_Comm             comm;
174d21efd2eSMatthew G. Knepley   PetscErrorCode       ierr;
175d21efd2eSMatthew G. Knepley 
176d21efd2eSMatthew G. Knepley   PetscFunctionBeginUser;
177d21efd2eSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
178d21efd2eSMatthew G. Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
179d21efd2eSMatthew G. Knepley   ierr = DMGetGlobalVector(dm, &u);CHKERRQ(ierr);
180d21efd2eSMatthew G. Knepley   ierr = PetscDSGetExactSolution(ds, 0, &exactSol[0], &exactCtx[0]);CHKERRQ(ierr);
181d21efd2eSMatthew G. Knepley   ierr = DMProjectFunction(dm, 0.0, exactSol, exactCtx, INSERT_ALL_VALUES, u);CHKERRQ(ierr);
182d21efd2eSMatthew G. Knepley   ierr = VecViewFromOptions(u, NULL, "-interpolation_view");CHKERRQ(ierr);
183d21efd2eSMatthew G. Knepley   ierr = DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error);CHKERRQ(ierr);
184d21efd2eSMatthew G. Knepley   ierr = DMRestoreGlobalVector(dm, &u);CHKERRQ(ierr);
185d21efd2eSMatthew G. Knepley   if (error > tol) {ierr = PetscPrintf(comm, "Interpolation tests FAIL at tolerance %g error %g\n", (double) tol, (double) error);CHKERRQ(ierr);}
186d21efd2eSMatthew G. Knepley   else             {ierr = PetscPrintf(comm, "Interpolation tests pass at tolerance %g\n", (double) tol);CHKERRQ(ierr);}
187d21efd2eSMatthew G. Knepley   PetscFunctionReturn(0);
188d21efd2eSMatthew G. Knepley }
189d21efd2eSMatthew G. Knepley 
190d21efd2eSMatthew G. Knepley /* This test tells us whether the element is unisolvent (the mass matrix has full rank), and what rate of convergence we achieve */
191d21efd2eSMatthew G. Knepley static PetscErrorCode CheckL2Projection(DM dm, AppCtx *user)
192d21efd2eSMatthew G. Knepley {
193d21efd2eSMatthew G. Knepley   PetscSimplePointFunc exactSol[1];
194d21efd2eSMatthew G. Knepley   void                *exactCtx[1];
195d21efd2eSMatthew G. Knepley   SNES                 snes;
196d21efd2eSMatthew G. Knepley   PetscDS              ds;
197d21efd2eSMatthew G. Knepley   Vec                  u;
198d21efd2eSMatthew G. Knepley   PetscReal            error, tol = PETSC_SMALL;
199d21efd2eSMatthew G. Knepley   MPI_Comm             comm;
200d21efd2eSMatthew G. Knepley   PetscErrorCode       ierr;
201d21efd2eSMatthew G. Knepley 
202d21efd2eSMatthew G. Knepley   PetscFunctionBeginUser;
203d21efd2eSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
204d21efd2eSMatthew G. Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
205d21efd2eSMatthew G. Knepley   ierr = DMGetGlobalVector(dm, &u);CHKERRQ(ierr);
206d21efd2eSMatthew G. Knepley   ierr = PetscDSGetExactSolution(ds, 0, &exactSol[0], &exactCtx[0]);CHKERRQ(ierr);
207d21efd2eSMatthew G. Knepley   ierr = SNESCreate(comm, &snes);CHKERRQ(ierr);
208d21efd2eSMatthew G. Knepley   ierr = SNESSetDM(snes, dm);CHKERRQ(ierr);
209d21efd2eSMatthew G. Knepley   ierr = VecSet(u, 0.0);CHKERRQ(ierr);
210d21efd2eSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) u, "solution");CHKERRQ(ierr);
211d21efd2eSMatthew G. Knepley   ierr = DMPlexSetSNESLocalFEM(dm, user, user, user);CHKERRQ(ierr);
212d21efd2eSMatthew G. Knepley   ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
213d21efd2eSMatthew G. Knepley   ierr = DMSNESCheckFromOptions(snes, u);CHKERRQ(ierr);
214d21efd2eSMatthew G. Knepley   ierr = SNESSolve(snes, NULL, u);CHKERRQ(ierr);
215d21efd2eSMatthew G. Knepley   ierr = SNESDestroy(&snes);CHKERRQ(ierr);
216d21efd2eSMatthew G. Knepley   ierr = VecViewFromOptions(u, NULL, "-l2_projection_view");CHKERRQ(ierr);
217d21efd2eSMatthew G. Knepley   ierr = DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error);CHKERRQ(ierr);
218d21efd2eSMatthew G. Knepley   ierr = DMRestoreGlobalVector(dm, &u);CHKERRQ(ierr);
219d21efd2eSMatthew G. Knepley   if (error > tol) {ierr = PetscPrintf(comm, "L2 projection tests FAIL at tolerance %g error %g\n", (double) tol, (double) error);CHKERRQ(ierr);}
220d21efd2eSMatthew G. Knepley   else             {ierr = PetscPrintf(comm, "L2 projection tests pass at tolerance %g\n", (double) tol);CHKERRQ(ierr);}
221d21efd2eSMatthew G. Knepley   PetscFunctionReturn(0);
222d21efd2eSMatthew G. Knepley }
223d21efd2eSMatthew G. Knepley 
224*e239af90SMatthew G. Knepley /* Distorts the mesh by shearing in the x-direction and flattening, factors provided in the options. */
225*e239af90SMatthew G. Knepley static PetscErrorCode DistortMesh(DM dm, AppCtx *user)
226*e239af90SMatthew G. Knepley {
227*e239af90SMatthew G. Knepley   Vec            coordinates;
228*e239af90SMatthew G. Knepley   PetscScalar   *ca;
229*e239af90SMatthew G. Knepley   PetscInt       dE, n, i;
230*e239af90SMatthew G. Knepley   PetscErrorCode ierr;
231*e239af90SMatthew G. Knepley 
232*e239af90SMatthew G. Knepley   PetscFunctionBeginUser;
233*e239af90SMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr);
234*e239af90SMatthew G. Knepley   ierr = DMGetCoordinates(dm, &coordinates);CHKERRQ(ierr);
235*e239af90SMatthew G. Knepley   ierr = VecGetLocalSize(coordinates, &n);CHKERRQ(ierr);
236*e239af90SMatthew G. Knepley   ierr = VecGetArray(coordinates, &ca);CHKERRQ(ierr);
237*e239af90SMatthew G. Knepley   for (i = 0; i < (n/dE); ++i) {
238*e239af90SMatthew G. Knepley     ca[i*dE+0] += user->shear*ca[i*dE+0];
239*e239af90SMatthew G. Knepley     ca[i*dE+1] *= user->flatten;
240*e239af90SMatthew G. Knepley   }
241*e239af90SMatthew G. Knepley   ierr = VecRestoreArray(coordinates, &ca);CHKERRQ(ierr);
242*e239af90SMatthew G. Knepley   PetscFunctionReturn(0);
243*e239af90SMatthew G. Knepley }
244*e239af90SMatthew G. Knepley 
245d21efd2eSMatthew G. Knepley int main(int argc, char **argv)
246d21efd2eSMatthew G. Knepley {
247d21efd2eSMatthew G. Knepley   DM             dm;
248d21efd2eSMatthew G. Knepley   AppCtx         user;
249d21efd2eSMatthew G. Knepley   PetscMPIInt    size;
250d21efd2eSMatthew G. Knepley   PetscErrorCode ierr;
251d21efd2eSMatthew G. Knepley 
252d21efd2eSMatthew G. Knepley   ierr = PetscInitialize(&argc, &argv, NULL, help); if (ierr) return ierr;
253d21efd2eSMatthew G. Knepley   ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size);CHKERRMPI(ierr);
254*e239af90SMatthew G. Knepley   PetscCheck(size == 1, PETSC_COMM_WORLD, PETSC_ERR_SUP, "This is a uniprocessor example only.");
255d21efd2eSMatthew G. Knepley   ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr);
256d21efd2eSMatthew G. Knepley   ierr = DMCreate(PETSC_COMM_WORLD, &dm);CHKERRQ(ierr);
257d21efd2eSMatthew G. Knepley   ierr = DMSetType(dm, DMPLEX);CHKERRQ(ierr);
258d21efd2eSMatthew G. Knepley   ierr = DMSetFromOptions(dm);CHKERRQ(ierr);
259*e239af90SMatthew G. Knepley   ierr = DistortMesh(dm,&user);CHKERRQ(ierr);
260*e239af90SMatthew G. Knepley   ierr = DMViewFromOptions(dm, NULL, "-dm_view");CHKERRQ(ierr);
261d21efd2eSMatthew G. Knepley   ierr = SetupDiscretization(dm, NULL, &user);CHKERRQ(ierr);
262d21efd2eSMatthew G. Knepley 
263d21efd2eSMatthew G. Knepley   ierr = CheckInterpolation(dm, &user);CHKERRQ(ierr);
264d21efd2eSMatthew G. Knepley   ierr = CheckL2Projection(dm, &user);CHKERRQ(ierr);
265d21efd2eSMatthew G. Knepley 
266d21efd2eSMatthew G. Knepley   ierr = DMDestroy(&dm);CHKERRQ(ierr);
267d21efd2eSMatthew G. Knepley   ierr = PetscFinalize();
268d21efd2eSMatthew G. Knepley   return ierr;
269d21efd2eSMatthew G. Knepley }
270d21efd2eSMatthew G. Knepley 
271d21efd2eSMatthew G. Knepley /*TEST
272d21efd2eSMatthew G. Knepley 
273d21efd2eSMatthew G. Knepley   testset:
274d21efd2eSMatthew G. Knepley     args: -dm_plex_reference_cell_domain -dm_plex_cell triangle -petscspace_degree 1\
275d21efd2eSMatthew G. Knepley           -snes_error_if_not_converged -ksp_error_if_not_converged -pc_type lu
276d21efd2eSMatthew G. Knepley 
277d21efd2eSMatthew G. Knepley     test:
278d21efd2eSMatthew G. Knepley       suffix: p1_0
279d21efd2eSMatthew G. Knepley       args: -func {{constant linear}}
280d21efd2eSMatthew G. Knepley 
281d21efd2eSMatthew G. Knepley     # Using -dm_refine 2 -convest_num_refine 4 gives convergence rate 2.0
282d21efd2eSMatthew G. Knepley     test:
283d21efd2eSMatthew G. Knepley       suffix: p1_1
284d21efd2eSMatthew G. Knepley       args: -func {{quadratic trig}} \
285d21efd2eSMatthew G. Knepley             -snes_convergence_estimate -convest_num_refine 2
286d21efd2eSMatthew G. Knepley 
287d21efd2eSMatthew G. Knepley   testset:
288*e239af90SMatthew G. Knepley     requires: !complex double
289d21efd2eSMatthew G. Knepley     args: -dm_plex_reference_cell_domain -dm_plex_cell triangular_prism \
290d21efd2eSMatthew G. Knepley             -petscspace_type sum \
291d21efd2eSMatthew G. Knepley             -petscspace_variables 3 \
292d21efd2eSMatthew G. Knepley             -petscspace_components 3 \
293d21efd2eSMatthew G. Knepley             -petscspace_sum_spaces 2 \
294d21efd2eSMatthew G. Knepley             -petscspace_sum_concatenate false \
295d21efd2eSMatthew G. Knepley               -sumcomp_0_petscspace_variables 3 \
296d21efd2eSMatthew G. Knepley               -sumcomp_0_petscspace_components 3 \
297d21efd2eSMatthew G. Knepley               -sumcomp_0_petscspace_degree 1 \
298d21efd2eSMatthew G. Knepley               -sumcomp_1_petscspace_variables 3 \
299d21efd2eSMatthew G. Knepley               -sumcomp_1_petscspace_components 3 \
300d21efd2eSMatthew G. Knepley               -sumcomp_1_petscspace_type wxy \
301d21efd2eSMatthew G. Knepley             -petscdualspace_form_degree 0 \
302d21efd2eSMatthew G. Knepley             -petscdualspace_order 1 \
303d21efd2eSMatthew G. Knepley             -petscdualspace_components 3 \
304d21efd2eSMatthew G. Knepley           -snes_error_if_not_converged -ksp_error_if_not_converged -pc_type lu
305d21efd2eSMatthew G. Knepley 
306d21efd2eSMatthew G. Knepley     test:
307d21efd2eSMatthew G. Knepley       suffix: wxy_0
308d21efd2eSMatthew G. Knepley       args: -func constant
309d21efd2eSMatthew G. Knepley 
310d21efd2eSMatthew G. Knepley     test:
311d21efd2eSMatthew G. Knepley       suffix: wxy_1
312d21efd2eSMatthew G. Knepley       args: -func linear
313d21efd2eSMatthew G. Knepley 
314*e239af90SMatthew G. Knepley     test:
315*e239af90SMatthew G. Knepley       suffix: wxy_2
316*e239af90SMatthew G. Knepley       args: -func prime
317*e239af90SMatthew G. Knepley 
318*e239af90SMatthew G. Knepley     test:
319*e239af90SMatthew G. Knepley       suffix: wxy_3
320*e239af90SMatthew G. Knepley       args: -func linear -shear 1 -flatten 1e-5
321*e239af90SMatthew G. Knepley 
322d21efd2eSMatthew G. Knepley TEST*/
323