xref: /petsc/src/snes/tests/ex8.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
1557cf195SMatthew G. Knepley static char help[] = "Test adaptive interpolation of functions of a given polynomial order\n\n";
2557cf195SMatthew G. Knepley 
3557cf195SMatthew G. Knepley #include <petscdmplex.h>
4557cf195SMatthew G. Knepley #include <petscsnes.h>
5557cf195SMatthew G. Knepley 
6557cf195SMatthew G. Knepley /*
7557cf195SMatthew G. Knepley   What properties does the adapted interpolator have?
8557cf195SMatthew G. Knepley 
9557cf195SMatthew G. Knepley 1) If we adapt to quadratics, we can get lower interpolation error for quadratics (than local interpolation) when using a linear basis
10557cf195SMatthew G. Knepley 
11557cf195SMatthew G. Knepley $ ./ex8 -dm_refine 2 -petscspace_degree 1 -qorder 1 -dim 2 -porder 2 -K 2 -num_comp 1 -use_poly 1
12557cf195SMatthew G. Knepley Function tests FAIL for order 2 at tolerance 1e-10 error 0.00273757
13557cf195SMatthew G. Knepley Function tests FAIL for order 2 derivatives at tolerance 1e-10 error 0.0721688
14557cf195SMatthew G. Knepley Interpolation tests FAIL for order 2 at tolerance 1e-10 error 0.00284555
15557cf195SMatthew G. Knepley Interpolation tests FAIL for order 2 derivatives at tolerance 1e-10 error 0.0721688
16557cf195SMatthew G. Knepley  Adapting interpolator using polynomials
17557cf195SMatthew G. Knepley The number of input vectors 4 < 7 the maximum number of column entries
18557cf195SMatthew G. Knepley   Interpolation poly tests FAIL for order 2 at tolerance 1e-10 error 0.00659864
19557cf195SMatthew G. Knepley   Interpolation poly tests FAIL for order 2 derivatives at tolerance 1e-10 error 0.0836582
20557cf195SMatthew G. Knepley   Interpolation trig (0, 0) tests FAIL for order 1 at tolerance 1e-10 error 0.476194
21557cf195SMatthew G. Knepley   Interpolation trig (0, 0) tests FAIL for order 1 derivatives at tolerance 1e-10 error 2.22144
22557cf195SMatthew G. Knepley   Interpolation trig (0, 1) tests FAIL for order 1 at tolerance 1e-10 error 1.39768
23557cf195SMatthew G. Knepley   Interpolation trig (0, 1) tests FAIL for order 1 derivatives at tolerance 1e-10 error 2.22144
24557cf195SMatthew G. Knepley   Interpolation trig (1, 0) tests FAIL for order 2 at tolerance 1e-10 error 1.07315
25557cf195SMatthew G. Knepley   Interpolation trig (1, 0) tests FAIL for order 2 derivatives at tolerance 1e-10 error 4.55403
26557cf195SMatthew G. Knepley   Interpolation trig (1, 1) tests FAIL for order 2 at tolerance 1e-10 error 1.07315
27557cf195SMatthew G. Knepley   Interpolation trig (1, 1) tests FAIL for order 2 derivatives at tolerance 1e-10 error 4.55403
28557cf195SMatthew G. Knepley 
29557cf195SMatthew G. Knepley $ ./ex8 -dm_refine 2 -petscspace_degree 1 -qorder 1 -dim 2 -porder 2 -K 3 -num_comp 1 -use_poly 1
30557cf195SMatthew G. Knepley Function tests FAIL for order 2 at tolerance 1e-10 error 0.00273757
31557cf195SMatthew G. Knepley Function tests FAIL for order 2 derivatives at tolerance 1e-10 error 0.0721688
32557cf195SMatthew G. Knepley Interpolation tests FAIL for order 2 at tolerance 1e-10 error 0.00284555
33557cf195SMatthew G. Knepley Interpolation tests FAIL for order 2 derivatives at tolerance 1e-10 error 0.0721688
34557cf195SMatthew G. Knepley  Adapting interpolator using polynomials
35557cf195SMatthew G. Knepley The number of input vectors 6 < 7 the maximum number of column entries
36557cf195SMatthew G. Knepley   Interpolation poly tests FAIL for order 2 at tolerance 1e-10 error 0.00194055
37557cf195SMatthew G. Knepley   Interpolation poly tests FAIL for order 2 derivatives at tolerance 1e-10 error 0.0525591
38557cf195SMatthew G. Knepley   Interpolation trig (0, 0) tests FAIL for order 1 at tolerance 1e-10 error 0.476255
39557cf195SMatthew G. Knepley   Interpolation trig (0, 0) tests FAIL for order 1 derivatives at tolerance 1e-10 error 2.22132
40557cf195SMatthew G. Knepley   Interpolation trig (0, 1) tests FAIL for order 1 at tolerance 1e-10 error 1.39785
41557cf195SMatthew G. Knepley   Interpolation trig (0, 1) tests FAIL for order 1 derivatives at tolerance 1e-10 error 2.22119
42557cf195SMatthew G. Knepley   Interpolation trig (1, 0) tests FAIL for order 2 at tolerance 1e-10 error 1.0727
43557cf195SMatthew G. Knepley   Interpolation trig (1, 0) tests FAIL for order 2 derivatives at tolerance 1e-10 error 4.55364
44557cf195SMatthew G. Knepley   Interpolation trig (1, 1) tests FAIL for order 2 at tolerance 1e-10 error 1.0727
45557cf195SMatthew G. Knepley   Interpolation trig (1, 1) tests FAIL for order 2 derivatives at tolerance 1e-10 error 4.55364
46557cf195SMatthew G. Knepley   Interpolation trig (2, 0) tests FAIL for order 3 at tolerance 1e-10 error 0.705258
47557cf195SMatthew G. Knepley   Interpolation trig (2, 0) tests FAIL for order 3 derivatives at tolerance 1e-10 error 6.82037
48557cf195SMatthew G. Knepley   Interpolation trig (2, 1) tests FAIL for order 3 at tolerance 1e-10 error 0.705258
49557cf195SMatthew G. Knepley   Interpolation trig (2, 1) tests FAIL for order 3 derivatives at tolerance 1e-10 error 6.82037
50557cf195SMatthew G. Knepley 
51557cf195SMatthew G. Knepley 2) We can more accurately capture low harmonics
52557cf195SMatthew G. Knepley 
53557cf195SMatthew G. Knepley If we adapt polynomials, we can be exact
54557cf195SMatthew G. Knepley 
55557cf195SMatthew G. Knepley $ ./ex8 -dm_refine 2 -petscspace_degree 1 -qorder 1 -dim 2 -porder 1 -K 2 -num_comp 1 -use_poly 1
56557cf195SMatthew G. Knepley Function tests pass for order 1 at tolerance 1e-10
57557cf195SMatthew G. Knepley Function tests pass for order 1 derivatives at tolerance 1e-10
58557cf195SMatthew G. Knepley Interpolation tests pass for order 1 at tolerance 1e-10
59557cf195SMatthew G. Knepley Interpolation tests pass for order 1 derivatives at tolerance 1e-10
60557cf195SMatthew G. Knepley  Adapting interpolator using polynomials
61557cf195SMatthew G. Knepley The number of input vectors 4 < 7 the maximum number of column entries
62557cf195SMatthew G. Knepley   Interpolation poly tests pass for order 1 at tolerance 1e-10
63557cf195SMatthew G. Knepley   Interpolation poly tests pass for order 1 derivatives at tolerance 1e-10
64557cf195SMatthew G. Knepley   Interpolation trig (0, 0) tests FAIL for order 1 at tolerance 1e-10 error 0.476194
65557cf195SMatthew G. Knepley   Interpolation trig (0, 0) tests FAIL for order 1 derivatives at tolerance 1e-10 error 2.22144
66557cf195SMatthew G. Knepley   Interpolation trig (0, 1) tests FAIL for order 1 at tolerance 1e-10 error 1.39768
67557cf195SMatthew G. Knepley   Interpolation trig (0, 1) tests FAIL for order 1 derivatives at tolerance 1e-10 error 2.22144
68557cf195SMatthew G. Knepley   Interpolation trig (1, 0) tests FAIL for order 2 at tolerance 1e-10 error 1.07315
69557cf195SMatthew G. Knepley   Interpolation trig (1, 0) tests FAIL for order 2 derivatives at tolerance 1e-10 error 4.55403
70557cf195SMatthew G. Knepley   Interpolation trig (1, 1) tests FAIL for order 2 at tolerance 1e-10 error 1.07315
71557cf195SMatthew G. Knepley   Interpolation trig (1, 1) tests FAIL for order 2 derivatives at tolerance 1e-10 error 4.55403
72557cf195SMatthew G. Knepley 
73557cf195SMatthew G. Knepley and least for small K,
74557cf195SMatthew G. Knepley 
75557cf195SMatthew G. Knepley $ ./ex8 -dm_refine 2 -petscspace_degree 1 -qorder 1 -dim 2 -porder 1 -K 4 -num_comp 1 -use_poly 1
76557cf195SMatthew G. Knepley Function tests pass for order 1 at tolerance 1e-10
77557cf195SMatthew G. Knepley Function tests pass for order 1 derivatives at tolerance 1e-10
78557cf195SMatthew G. Knepley Interpolation tests pass for order 1 at tolerance 1e-10
79557cf195SMatthew G. Knepley Interpolation tests pass for order 1 derivatives at tolerance 1e-10
80557cf195SMatthew G. Knepley  Adapting interpolator using polynomials
81557cf195SMatthew G. Knepley   Interpolation poly tests FAIL for order 1 at tolerance 1e-10 error 0.0015351
82557cf195SMatthew G. Knepley   Interpolation poly tests FAIL for order 1 derivatives at tolerance 1e-10 error 0.0427369
83557cf195SMatthew G. Knepley   Interpolation trig (0, 0) tests FAIL for order 1 at tolerance 1e-10 error 0.476359
84557cf195SMatthew G. Knepley   Interpolation trig (0, 0) tests FAIL for order 1 derivatives at tolerance 1e-10 error 2.22115
85557cf195SMatthew G. Knepley   Interpolation trig (0, 1) tests FAIL for order 1 at tolerance 1e-10 error 1.3981
86557cf195SMatthew G. Knepley   Interpolation trig (0, 1) tests FAIL for order 1 derivatives at tolerance 1e-10 error 2.22087
87557cf195SMatthew G. Knepley   Interpolation trig (1, 0) tests FAIL for order 2 at tolerance 1e-10 error 1.07228
88557cf195SMatthew G. Knepley   Interpolation trig (1, 0) tests FAIL for order 2 derivatives at tolerance 1e-10 error 4.55238
89557cf195SMatthew G. Knepley   Interpolation trig (1, 1) tests FAIL for order 2 at tolerance 1e-10 error 1.07228
90557cf195SMatthew G. Knepley   Interpolation trig (1, 1) tests FAIL for order 2 derivatives at tolerance 1e-10 error 4.55238
91557cf195SMatthew G. Knepley   Interpolation trig (2, 0) tests FAIL for order 3 at tolerance 1e-10 error 0.704947
92557cf195SMatthew G. Knepley   Interpolation trig (2, 0) tests FAIL for order 3 derivatives at tolerance 1e-10 error 6.82254
93557cf195SMatthew G. Knepley   Interpolation trig (2, 1) tests FAIL for order 3 at tolerance 1e-10 error 0.704948
94557cf195SMatthew G. Knepley   Interpolation trig (2, 1) tests FAIL for order 3 derivatives at tolerance 1e-10 error 6.82254
95557cf195SMatthew G. Knepley   Interpolation trig (3, 0) tests FAIL for order 4 at tolerance 1e-10 error 0.893279
96557cf195SMatthew G. Knepley   Interpolation trig (3, 0) tests FAIL for order 4 derivatives at tolerance 1e-10 error 8.93718
97557cf195SMatthew G. Knepley   Interpolation trig (3, 1) tests FAIL for order 4 at tolerance 1e-10 error 0.89328
98557cf195SMatthew G. Knepley   Interpolation trig (3, 1) tests FAIL for order 4 derivatives at tolerance 1e-10 error 8.93717
99557cf195SMatthew G. Knepley 
100557cf195SMatthew G. Knepley but adapting to harmonics gives alright polynomials errors and much better harmonics errors.
101557cf195SMatthew G. Knepley 
102557cf195SMatthew G. Knepley $ ./ex8 -dm_refine 2 -petscspace_degree 1 -qorder 1 -dim 2 -porder 1 -K 4 -num_comp 1 -use_poly 0
103557cf195SMatthew G. Knepley Function tests pass for order 1 at tolerance 1e-10
104557cf195SMatthew G. Knepley Function tests pass for order 1 derivatives at tolerance 1e-10
105557cf195SMatthew G. Knepley Interpolation tests pass for order 1 at tolerance 1e-10
106557cf195SMatthew G. Knepley Interpolation tests pass for order 1 derivatives at tolerance 1e-10
107557cf195SMatthew G. Knepley  Adapting interpolator using harmonics
108557cf195SMatthew G. Knepley   Interpolation poly tests FAIL for order 1 at tolerance 1e-10 error 0.0720606
109557cf195SMatthew G. Knepley   Interpolation poly tests FAIL for order 1 derivatives at tolerance 1e-10 error 1.97779
110557cf195SMatthew G. Knepley   Interpolation trig (0, 0) tests FAIL for order 1 at tolerance 1e-10 error 0.0398055
111557cf195SMatthew G. Knepley   Interpolation trig (0, 0) tests FAIL for order 1 derivatives at tolerance 1e-10 error 0.995963
112557cf195SMatthew G. Knepley   Interpolation trig (0, 1) tests FAIL for order 1 at tolerance 1e-10 error 0.0398051
113557cf195SMatthew G. Knepley   Interpolation trig (0, 1) tests FAIL for order 1 derivatives at tolerance 1e-10 error 0.995964
114557cf195SMatthew G. Knepley   Interpolation trig (1, 0) tests FAIL for order 2 at tolerance 1e-10 error 0.0238441
115557cf195SMatthew G. Knepley   Interpolation trig (1, 0) tests FAIL for order 2 derivatives at tolerance 1e-10 error 0.888611
116557cf195SMatthew G. Knepley   Interpolation trig (1, 1) tests FAIL for order 2 at tolerance 1e-10 error 0.0238346
117557cf195SMatthew G. Knepley   Interpolation trig (1, 1) tests FAIL for order 2 derivatives at tolerance 1e-10 error 0.888612
118557cf195SMatthew G. Knepley   Interpolation trig (2, 0) tests FAIL for order 3 at tolerance 1e-10 error 0.0537968
119557cf195SMatthew G. Knepley   Interpolation trig (2, 0) tests FAIL for order 3 derivatives at tolerance 1e-10 error 1.57665
120557cf195SMatthew G. Knepley   Interpolation trig (2, 1) tests FAIL for order 3 at tolerance 1e-10 error 0.0537779
121557cf195SMatthew G. Knepley   Interpolation trig (2, 1) tests FAIL for order 3 derivatives at tolerance 1e-10 error 1.57666
122557cf195SMatthew G. Knepley   Interpolation trig (3, 0) tests FAIL for order 4 at tolerance 1e-10 error 0.0775838
123557cf195SMatthew G. Knepley   Interpolation trig (3, 0) tests FAIL for order 4 derivatives at tolerance 1e-10 error 2.36926
124557cf195SMatthew G. Knepley   Interpolation trig (3, 1) tests FAIL for order 4 at tolerance 1e-10 error 0.0775464
125557cf195SMatthew G. Knepley   Interpolation trig (3, 1) tests FAIL for order 4 derivatives at tolerance 1e-10 error 2.36929
126557cf195SMatthew G. Knepley */
127557cf195SMatthew G. Knepley 
128557cf195SMatthew G. Knepley typedef struct {
129557cf195SMatthew G. Knepley   /* Element definition */
130557cf195SMatthew G. Knepley   PetscInt qorder; /* Order of the quadrature */
131557cf195SMatthew G. Knepley   PetscInt Nc;     /* Number of field components */
132557cf195SMatthew G. Knepley   /* Testing space */
133557cf195SMatthew G. Knepley   PetscInt  porder;       /* Order of polynomials to test */
134557cf195SMatthew G. Knepley   PetscReal constants[3]; /* Constant values for each dimension */
135557cf195SMatthew G. Knepley   PetscInt  m;            /* The frequency of sinusoids to use */
136557cf195SMatthew G. Knepley   PetscInt  dir;          /* The direction of sinusoids to use */
137557cf195SMatthew G. Knepley   /* Adaptation */
138557cf195SMatthew G. Knepley   PetscInt  K;       /* Number of coarse modes used for optimization */
139557cf195SMatthew G. Knepley   PetscBool usePoly; /* Use polynomials, or harmonics, to adapt interpolator */
140557cf195SMatthew G. Knepley } AppCtx;
141557cf195SMatthew G. Knepley 
1429371c9d4SSatish Balay typedef enum {
1439371c9d4SSatish Balay   INTERPOLATION,
1449371c9d4SSatish Balay   RESTRICTION,
1459371c9d4SSatish Balay   INJECTION
1469371c9d4SSatish Balay } InterpType;
147557cf195SMatthew G. Knepley 
148557cf195SMatthew G. Knepley /* u = 1 */
constant(PetscInt dim,PetscReal time,const PetscReal coords[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)149*2a8381b2SBarry Smith PetscErrorCode constant(PetscInt dim, PetscReal time, const PetscReal coords[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
150d71ae5a4SJacob Faibussowitsch {
151557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
152557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
153557cf195SMatthew G. Knepley 
154557cf195SMatthew G. Knepley   if (Nc > 1) {
155557cf195SMatthew G. Knepley     for (d = 0; d < Nc; ++d) u[d] = user->constants[d];
156557cf195SMatthew G. Knepley   } else {
157557cf195SMatthew G. Knepley     u[0] = user->constants[d];
158557cf195SMatthew G. Knepley   }
1593ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
160557cf195SMatthew G. Knepley }
constantDer(PetscInt dim,PetscReal time,const PetscReal coords[],const PetscReal n[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)161*2a8381b2SBarry Smith PetscErrorCode constantDer(PetscInt dim, PetscReal time, const PetscReal coords[], const PetscReal n[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
162d71ae5a4SJacob Faibussowitsch {
163557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
164557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
165557cf195SMatthew G. Knepley 
166557cf195SMatthew G. Knepley   if (Nc > 1) {
167557cf195SMatthew G. Knepley     for (d = 0; d < Nc; ++d) u[d] = 0.0;
168557cf195SMatthew G. Knepley   } else {
169557cf195SMatthew G. Knepley     u[0] = user->constants[d];
170557cf195SMatthew G. Knepley   }
1713ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
172557cf195SMatthew G. Knepley }
173557cf195SMatthew G. Knepley 
174557cf195SMatthew G. Knepley /* u = x */
linear(PetscInt dim,PetscReal time,const PetscReal coords[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)175*2a8381b2SBarry Smith PetscErrorCode linear(PetscInt dim, PetscReal time, const PetscReal coords[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
176d71ae5a4SJacob Faibussowitsch {
177557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
178557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
179557cf195SMatthew G. Knepley 
180557cf195SMatthew G. Knepley   if (Nc > 1) {
181557cf195SMatthew G. Knepley     for (d = 0; d < Nc; ++d) u[d] = coords[d];
182557cf195SMatthew G. Knepley   } else {
183557cf195SMatthew G. Knepley     u[0] = coords[d];
184557cf195SMatthew G. Knepley   }
1853ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
186557cf195SMatthew G. Knepley }
linearDer(PetscInt dim,PetscReal time,const PetscReal coords[],const PetscReal n[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)187*2a8381b2SBarry Smith PetscErrorCode linearDer(PetscInt dim, PetscReal time, const PetscReal coords[], const PetscReal n[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
188d71ae5a4SJacob Faibussowitsch {
189557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
190557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
191557cf195SMatthew G. Knepley 
192557cf195SMatthew G. Knepley   if (Nc > 1) {
193557cf195SMatthew G. Knepley     PetscInt e;
194557cf195SMatthew G. Knepley     for (d = 0; d < Nc; ++d) {
195557cf195SMatthew G. Knepley       u[d] = 0.0;
196557cf195SMatthew G. Knepley       for (e = 0; e < dim; ++e) u[d] += (d == e ? 1.0 : 0.0) * n[e];
197557cf195SMatthew G. Knepley     }
198557cf195SMatthew G. Knepley   } else {
199557cf195SMatthew G. Knepley     u[0] = n[d];
200557cf195SMatthew G. Knepley   }
2013ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
202557cf195SMatthew G. Knepley }
203557cf195SMatthew G. Knepley 
204557cf195SMatthew G. Knepley /* u = x^2 or u = (x^2, xy) or u = (xy, yz, zx) */
quadratic(PetscInt dim,PetscReal time,const PetscReal coords[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)205*2a8381b2SBarry Smith PetscErrorCode quadratic(PetscInt dim, PetscReal time, const PetscReal coords[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
206d71ae5a4SJacob Faibussowitsch {
207557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
208557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
209557cf195SMatthew G. Knepley 
210557cf195SMatthew G. Knepley   if (Nc > 1) {
2119371c9d4SSatish Balay     if (Nc > 2) {
2129371c9d4SSatish Balay       u[0] = coords[0] * coords[1];
2139371c9d4SSatish Balay       u[1] = coords[1] * coords[2];
2149371c9d4SSatish Balay       u[2] = coords[2] * coords[0];
2159371c9d4SSatish Balay     } else {
2169371c9d4SSatish Balay       u[0] = coords[0] * coords[0];
2179371c9d4SSatish Balay       u[1] = coords[0] * coords[1];
2189371c9d4SSatish Balay     }
219557cf195SMatthew G. Knepley   } else {
220557cf195SMatthew G. Knepley     u[0] = coords[d] * coords[d];
221557cf195SMatthew G. Knepley   }
2223ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
223557cf195SMatthew G. Knepley }
quadraticDer(PetscInt dim,PetscReal time,const PetscReal coords[],const PetscReal n[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)224*2a8381b2SBarry Smith PetscErrorCode quadraticDer(PetscInt dim, PetscReal time, const PetscReal coords[], const PetscReal n[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
225d71ae5a4SJacob Faibussowitsch {
226557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
227557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
228557cf195SMatthew G. Knepley 
229557cf195SMatthew G. Knepley   if (Nc > 1) {
2309371c9d4SSatish Balay     if (Nc > 2) {
2319371c9d4SSatish Balay       u[0] = coords[1] * n[0] + coords[0] * n[1];
2329371c9d4SSatish Balay       u[1] = coords[2] * n[1] + coords[1] * n[2];
2339371c9d4SSatish Balay       u[2] = coords[2] * n[0] + coords[0] * n[2];
2349371c9d4SSatish Balay     } else {
2359371c9d4SSatish Balay       u[0] = 2.0 * coords[0] * n[0];
2369371c9d4SSatish Balay       u[1] = coords[1] * n[0] + coords[0] * n[1];
2379371c9d4SSatish Balay     }
238557cf195SMatthew G. Knepley   } else {
239557cf195SMatthew G. Knepley     u[0] = 2.0 * coords[d] * n[d];
240557cf195SMatthew G. Knepley   }
2413ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
242557cf195SMatthew G. Knepley }
243557cf195SMatthew G. Knepley 
244557cf195SMatthew G. Knepley /* u = x^3 or u = (x^3, x^2y) or u = (x^2y, y^2z, z^2x) */
cubic(PetscInt dim,PetscReal time,const PetscReal coords[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)245*2a8381b2SBarry Smith PetscErrorCode cubic(PetscInt dim, PetscReal time, const PetscReal coords[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
246d71ae5a4SJacob Faibussowitsch {
247557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
248557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
249557cf195SMatthew G. Knepley 
250557cf195SMatthew G. Knepley   if (Nc > 1) {
2519371c9d4SSatish Balay     if (Nc > 2) {
2529371c9d4SSatish Balay       u[0] = coords[0] * coords[0] * coords[1];
2539371c9d4SSatish Balay       u[1] = coords[1] * coords[1] * coords[2];
2549371c9d4SSatish Balay       u[2] = coords[2] * coords[2] * coords[0];
2559371c9d4SSatish Balay     } else {
2569371c9d4SSatish Balay       u[0] = coords[0] * coords[0] * coords[0];
2579371c9d4SSatish Balay       u[1] = coords[0] * coords[0] * coords[1];
2589371c9d4SSatish Balay     }
259557cf195SMatthew G. Knepley   } else {
260557cf195SMatthew G. Knepley     u[0] = coords[d] * coords[d] * coords[d];
261557cf195SMatthew G. Knepley   }
2623ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
263557cf195SMatthew G. Knepley }
cubicDer(PetscInt dim,PetscReal time,const PetscReal coords[],const PetscReal n[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)264*2a8381b2SBarry Smith PetscErrorCode cubicDer(PetscInt dim, PetscReal time, const PetscReal coords[], const PetscReal n[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
265d71ae5a4SJacob Faibussowitsch {
266557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
267557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
268557cf195SMatthew G. Knepley 
269557cf195SMatthew G. Knepley   if (Nc > 1) {
2709371c9d4SSatish Balay     if (Nc > 2) {
2719371c9d4SSatish Balay       u[0] = 2.0 * coords[0] * coords[1] * n[0] + coords[0] * coords[0] * n[1];
2729371c9d4SSatish Balay       u[1] = 2.0 * coords[1] * coords[2] * n[1] + coords[1] * coords[1] * n[2];
2739371c9d4SSatish Balay       u[2] = 2.0 * coords[2] * coords[0] * n[2] + coords[2] * coords[2] * n[0];
2749371c9d4SSatish Balay     } else {
2759371c9d4SSatish Balay       u[0] = 3.0 * coords[0] * coords[0] * n[0];
2769371c9d4SSatish Balay       u[1] = 2.0 * coords[0] * coords[1] * n[0] + coords[0] * coords[0] * n[1];
2779371c9d4SSatish Balay     }
278557cf195SMatthew G. Knepley   } else {
279557cf195SMatthew G. Knepley     u[0] = 3.0 * coords[d] * coords[d] * n[d];
280557cf195SMatthew G. Knepley   }
2813ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
282557cf195SMatthew G. Knepley }
283557cf195SMatthew G. Knepley 
284557cf195SMatthew G. Knepley /* u = x^4 or u = (x^4, x^2y^2) or u = (x^2y^2, y^2z^2, z^2x^2) */
quartic(PetscInt dim,PetscReal time,const PetscReal coords[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)285*2a8381b2SBarry Smith PetscErrorCode quartic(PetscInt dim, PetscReal time, const PetscReal coords[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
286d71ae5a4SJacob Faibussowitsch {
287557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
288557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
289557cf195SMatthew G. Knepley 
290557cf195SMatthew G. Knepley   if (Nc > 1) {
2919371c9d4SSatish Balay     if (Nc > 2) {
2929371c9d4SSatish Balay       u[0] = coords[0] * coords[0] * coords[1] * coords[1];
2939371c9d4SSatish Balay       u[1] = coords[1] * coords[1] * coords[2] * coords[2];
2949371c9d4SSatish Balay       u[2] = coords[2] * coords[2] * coords[0] * coords[0];
2959371c9d4SSatish Balay     } else {
2969371c9d4SSatish Balay       u[0] = coords[0] * coords[0] * coords[0] * coords[0];
2979371c9d4SSatish Balay       u[1] = coords[0] * coords[0] * coords[1] * coords[1];
2989371c9d4SSatish Balay     }
299557cf195SMatthew G. Knepley   } else {
300557cf195SMatthew G. Knepley     u[0] = coords[d] * coords[d] * coords[d] * coords[d];
301557cf195SMatthew G. Knepley   }
3023ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
303557cf195SMatthew G. Knepley }
quarticDer(PetscInt dim,PetscReal time,const PetscReal coords[],const PetscReal n[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)304*2a8381b2SBarry Smith PetscErrorCode quarticDer(PetscInt dim, PetscReal time, const PetscReal coords[], const PetscReal n[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
305d71ae5a4SJacob Faibussowitsch {
306557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
307557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
308557cf195SMatthew G. Knepley 
309557cf195SMatthew G. Knepley   if (Nc > 1) {
3109371c9d4SSatish Balay     if (Nc > 2) {
3119371c9d4SSatish Balay       u[0] = 2.0 * coords[0] * coords[1] * coords[1] * n[0] + 2.0 * coords[0] * coords[0] * coords[1] * n[1];
312557cf195SMatthew G. Knepley       u[1] = 2.0 * coords[1] * coords[2] * coords[2] * n[1] + 2.0 * coords[1] * coords[1] * coords[2] * n[2];
3139371c9d4SSatish Balay       u[2] = 2.0 * coords[2] * coords[0] * coords[0] * n[2] + 2.0 * coords[2] * coords[2] * coords[0] * n[0];
3149371c9d4SSatish Balay     } else {
3159371c9d4SSatish Balay       u[0] = 4.0 * coords[0] * coords[0] * coords[0] * n[0];
3169371c9d4SSatish Balay       u[1] = 2.0 * coords[0] * coords[1] * coords[1] * n[0] + 2.0 * coords[0] * coords[0] * coords[1] * n[1];
3179371c9d4SSatish Balay     }
318557cf195SMatthew G. Knepley   } else {
319557cf195SMatthew G. Knepley     u[0] = 4.0 * coords[d] * coords[d] * coords[d] * n[d];
320557cf195SMatthew G. Knepley   }
3213ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
322557cf195SMatthew G. Knepley }
323557cf195SMatthew G. Knepley 
mytanh(PetscInt dim,PetscReal time,const PetscReal coords[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)324*2a8381b2SBarry Smith PetscErrorCode mytanh(PetscInt dim, PetscReal time, const PetscReal coords[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
325d71ae5a4SJacob Faibussowitsch {
326557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
327557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
328557cf195SMatthew G. Knepley 
329557cf195SMatthew G. Knepley   if (Nc > 1) {
330557cf195SMatthew G. Knepley     for (d = 0; d < Nc; ++d) u[d] = PetscTanhReal(coords[d] - 0.5);
331557cf195SMatthew G. Knepley   } else {
332557cf195SMatthew G. Knepley     u[0] = PetscTanhReal(coords[d] - 0.5);
333557cf195SMatthew G. Knepley   }
3343ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
335557cf195SMatthew G. Knepley }
mytanhDer(PetscInt dim,PetscReal time,const PetscReal coords[],const PetscReal n[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)336*2a8381b2SBarry Smith PetscErrorCode mytanhDer(PetscInt dim, PetscReal time, const PetscReal coords[], const PetscReal n[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
337d71ae5a4SJacob Faibussowitsch {
338557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
339557cf195SMatthew G. Knepley   PetscInt d    = user->dir;
340557cf195SMatthew G. Knepley 
341557cf195SMatthew G. Knepley   if (Nc > 1) {
342557cf195SMatthew G. Knepley     for (d = 0; d < Nc; ++d) u[d] = 1.0 / PetscSqr(PetscCoshReal(coords[d] - 0.5)) * n[d];
343557cf195SMatthew G. Knepley   } else {
344557cf195SMatthew G. Knepley     u[0] = 1.0 / PetscSqr(PetscCoshReal(coords[d] - 0.5)) * n[d];
345557cf195SMatthew G. Knepley   }
3463ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
347557cf195SMatthew G. Knepley }
348557cf195SMatthew G. Knepley 
trig(PetscInt dim,PetscReal time,const PetscReal coords[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)349*2a8381b2SBarry Smith PetscErrorCode trig(PetscInt dim, PetscReal time, const PetscReal coords[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
350d71ae5a4SJacob Faibussowitsch {
351557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
352557cf195SMatthew G. Knepley   PetscInt m = user->m, d = user->dir;
353557cf195SMatthew G. Knepley 
354557cf195SMatthew G. Knepley   if (Nc > 1) {
355557cf195SMatthew G. Knepley     for (d = 0; d < Nc; ++d) u[d] = PetscSinReal(PETSC_PI * m * coords[d]);
356557cf195SMatthew G. Knepley   } else {
357557cf195SMatthew G. Knepley     u[0] = PetscSinReal(PETSC_PI * m * coords[d]);
358557cf195SMatthew G. Knepley   }
3593ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
360557cf195SMatthew G. Knepley }
trigDer(PetscInt dim,PetscReal time,const PetscReal coords[],const PetscReal n[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)361*2a8381b2SBarry Smith PetscErrorCode trigDer(PetscInt dim, PetscReal time, const PetscReal coords[], const PetscReal n[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
362d71ae5a4SJacob Faibussowitsch {
363557cf195SMatthew G. Knepley   AppCtx  *user = (AppCtx *)ctx;
364557cf195SMatthew G. Knepley   PetscInt m = user->m, d = user->dir;
365557cf195SMatthew G. Knepley 
366557cf195SMatthew G. Knepley   if (Nc > 1) {
367557cf195SMatthew G. Knepley     for (d = 0; d < Nc; ++d) u[d] = PETSC_PI * m * PetscCosReal(PETSC_PI * m * coords[d]) * n[d];
368557cf195SMatthew G. Knepley   } else {
369557cf195SMatthew G. Knepley     u[0] = PETSC_PI * m * PetscCosReal(PETSC_PI * m * coords[d]) * n[d];
370557cf195SMatthew G. Knepley   }
3713ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
372557cf195SMatthew G. Knepley }
373557cf195SMatthew G. Knepley 
ProcessOptions(MPI_Comm comm,AppCtx * options)374d71ae5a4SJacob Faibussowitsch static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
375d71ae5a4SJacob Faibussowitsch {
376557cf195SMatthew G. Knepley   PetscFunctionBeginUser;
377557cf195SMatthew G. Knepley   options->qorder  = 0;
378557cf195SMatthew G. Knepley   options->Nc      = PETSC_DEFAULT;
379557cf195SMatthew G. Knepley   options->porder  = 0;
380557cf195SMatthew G. Knepley   options->m       = 1;
381557cf195SMatthew G. Knepley   options->dir     = 0;
382557cf195SMatthew G. Knepley   options->K       = 0;
383557cf195SMatthew G. Knepley   options->usePoly = PETSC_TRUE;
384557cf195SMatthew G. Knepley 
385d0609cedSBarry Smith   PetscOptionsBegin(comm, "", "Projection Test Options", "DMPlex");
3869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-qorder", "The quadrature order", "ex8.c", options->qorder, &options->qorder, NULL));
3879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-num_comp", "The number of field components", "ex8.c", options->Nc, &options->Nc, NULL));
3889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-porder", "The order of polynomials to test", "ex8.c", options->porder, &options->porder, NULL));
3899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-K", "The number of coarse modes used in optimization", "ex8.c", options->K, &options->K, NULL));
3909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-use_poly", "Use polynomials (or harmonics) to adapt interpolator", "ex8.c", options->usePoly, &options->usePoly, NULL));
391d0609cedSBarry Smith   PetscOptionsEnd();
3923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
393557cf195SMatthew G. Knepley }
394557cf195SMatthew G. Knepley 
CreateMesh(MPI_Comm comm,AppCtx * user,DM * dm)395d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm)
396d71ae5a4SJacob Faibussowitsch {
397557cf195SMatthew G. Knepley   PetscFunctionBeginUser;
3989566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
3999566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
4009566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(*dm));
4019566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view"));
4023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
403557cf195SMatthew G. Knepley }
404557cf195SMatthew G. Knepley 
405557cf195SMatthew G. Knepley /* Setup functions to approximate */
SetupFunctions(DM dm,PetscBool usePoly,PetscInt order,PetscInt dir,PetscErrorCode (** exactFuncs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),PetscErrorCode (** exactFuncDers)(PetscInt,PetscReal,const PetscReal[],const PetscReal[],PetscInt,PetscScalar *,void *),AppCtx * user)406d71ae5a4SJacob Faibussowitsch static PetscErrorCode SetupFunctions(DM dm, PetscBool usePoly, PetscInt order, PetscInt dir, PetscErrorCode (**exactFuncs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), PetscErrorCode (**exactFuncDers)(PetscInt, PetscReal, const PetscReal[], const PetscReal[], PetscInt, PetscScalar *, void *), AppCtx *user)
407d71ae5a4SJacob Faibussowitsch {
408557cf195SMatthew G. Knepley   PetscInt dim;
409557cf195SMatthew G. Knepley 
410557cf195SMatthew G. Knepley   PetscFunctionBeginUser;
411557cf195SMatthew G. Knepley   user->dir = dir;
412557cf195SMatthew G. Knepley   if (usePoly) {
413557cf195SMatthew G. Knepley     switch (order) {
414557cf195SMatthew G. Knepley     case 0:
415557cf195SMatthew G. Knepley       exactFuncs[0]    = constant;
416557cf195SMatthew G. Knepley       exactFuncDers[0] = constantDer;
417557cf195SMatthew G. Knepley       break;
418557cf195SMatthew G. Knepley     case 1:
419557cf195SMatthew G. Knepley       exactFuncs[0]    = linear;
420557cf195SMatthew G. Knepley       exactFuncDers[0] = linearDer;
421557cf195SMatthew G. Knepley       break;
422557cf195SMatthew G. Knepley     case 2:
423557cf195SMatthew G. Knepley       exactFuncs[0]    = quadratic;
424557cf195SMatthew G. Knepley       exactFuncDers[0] = quadraticDer;
425557cf195SMatthew G. Knepley       break;
426557cf195SMatthew G. Knepley     case 3:
427557cf195SMatthew G. Knepley       exactFuncs[0]    = cubic;
428557cf195SMatthew G. Knepley       exactFuncDers[0] = cubicDer;
429557cf195SMatthew G. Knepley       break;
430557cf195SMatthew G. Knepley     case 4:
431557cf195SMatthew G. Knepley       exactFuncs[0]    = quartic;
432557cf195SMatthew G. Knepley       exactFuncDers[0] = quarticDer;
433557cf195SMatthew G. Knepley       break;
434d71ae5a4SJacob Faibussowitsch     default:
435d71ae5a4SJacob Faibussowitsch       PetscCall(DMGetDimension(dm, &dim));
436d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Could not determine functions to test for dimension %" PetscInt_FMT " order %" PetscInt_FMT, dim, order);
437557cf195SMatthew G. Knepley     }
438557cf195SMatthew G. Knepley   } else {
439557cf195SMatthew G. Knepley     user->m          = order;
440557cf195SMatthew G. Knepley     exactFuncs[0]    = trig;
441557cf195SMatthew G. Knepley     exactFuncDers[0] = trigDer;
442557cf195SMatthew G. Knepley   }
4433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
444557cf195SMatthew G. Knepley }
445557cf195SMatthew G. Knepley 
ComputeError(DM dm,PetscErrorCode (** exactFuncs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),PetscErrorCode (** exactFuncDers)(PetscInt,PetscReal,const PetscReal[],const PetscReal[],PetscInt,PetscScalar *,void *),void ** exactCtxs,PetscReal * error,PetscReal * errorDer,AppCtx * user)446d71ae5a4SJacob Faibussowitsch static PetscErrorCode ComputeError(DM dm, PetscErrorCode (**exactFuncs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), PetscErrorCode (**exactFuncDers)(PetscInt, PetscReal, const PetscReal[], const PetscReal[], PetscInt, PetscScalar *, void *), void **exactCtxs, PetscReal *error, PetscReal *errorDer, AppCtx *user)
447d71ae5a4SJacob Faibussowitsch {
448557cf195SMatthew G. Knepley   Vec       u;
449557cf195SMatthew G. Knepley   PetscReal n[3] = {1.0, 1.0, 1.0};
450557cf195SMatthew G. Knepley 
451557cf195SMatthew G. Knepley   PetscFunctionBeginUser;
4529566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(dm, &u));
453557cf195SMatthew G. Knepley   /* Project function into FE function space */
4549566063dSJacob Faibussowitsch   PetscCall(DMProjectFunction(dm, 0.0, exactFuncs, exactCtxs, INSERT_ALL_VALUES, u));
4559566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(u, NULL, "-projection_view"));
456557cf195SMatthew G. Knepley   /* Compare approximation to exact in L_2 */
4579566063dSJacob Faibussowitsch   PetscCall(DMComputeL2Diff(dm, 0.0, exactFuncs, exactCtxs, u, error));
4589566063dSJacob Faibussowitsch   PetscCall(DMComputeL2GradientDiff(dm, 0.0, exactFuncDers, exactCtxs, u, n, errorDer));
4599566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(dm, &u));
4603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
461557cf195SMatthew G. Knepley }
462557cf195SMatthew G. Knepley 
CheckFunctions(DM dm,PetscInt order,AppCtx * user)463d71ae5a4SJacob Faibussowitsch static PetscErrorCode CheckFunctions(DM dm, PetscInt order, AppCtx *user)
464d71ae5a4SJacob Faibussowitsch {
465*2a8381b2SBarry Smith   PetscErrorCode (*exactFuncs[1])(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, PetscCtx ctx);
466*2a8381b2SBarry Smith   PetscErrorCode (*exactFuncDers[1])(PetscInt dim, PetscReal time, const PetscReal x[], const PetscReal n[], PetscInt Nf, PetscScalar *u, PetscCtx ctx);
467557cf195SMatthew G. Knepley   void     *exactCtxs[3];
468557cf195SMatthew G. Knepley   MPI_Comm  comm;
469557cf195SMatthew G. Knepley   PetscReal error, errorDer, tol = PETSC_SMALL;
470557cf195SMatthew G. Knepley 
471557cf195SMatthew G. Knepley   PetscFunctionBeginUser;
472557cf195SMatthew G. Knepley   exactCtxs[0]       = user;
473557cf195SMatthew G. Knepley   exactCtxs[1]       = user;
474557cf195SMatthew G. Knepley   exactCtxs[2]       = user;
475557cf195SMatthew G. Knepley   user->constants[0] = 1.0;
476557cf195SMatthew G. Knepley   user->constants[1] = 2.0;
477557cf195SMatthew G. Knepley   user->constants[2] = 3.0;
4789566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4799566063dSJacob Faibussowitsch   PetscCall(SetupFunctions(dm, PETSC_TRUE, order, 0, exactFuncs, exactFuncDers, user));
4809566063dSJacob Faibussowitsch   PetscCall(ComputeError(dm, exactFuncs, exactFuncDers, exactCtxs, &error, &errorDer, user));
481557cf195SMatthew G. Knepley   /* Report result */
48263a3b9bcSJacob Faibussowitsch   if (error > tol) PetscCall(PetscPrintf(comm, "Function tests FAIL for order %" PetscInt_FMT " at tolerance %g error %g\n", order, (double)tol, (double)error));
48363a3b9bcSJacob Faibussowitsch   else PetscCall(PetscPrintf(comm, "Function tests pass for order %" PetscInt_FMT " at tolerance %g\n", order, (double)tol));
48463a3b9bcSJacob Faibussowitsch   if (errorDer > tol) PetscCall(PetscPrintf(comm, "Function tests FAIL for order %" PetscInt_FMT " derivatives at tolerance %g error %g\n", order, (double)tol, (double)errorDer));
48563a3b9bcSJacob Faibussowitsch   else PetscCall(PetscPrintf(comm, "Function tests pass for order %" PetscInt_FMT " derivatives at tolerance %g\n", order, (double)tol));
4863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
487557cf195SMatthew G. Knepley }
488557cf195SMatthew G. Knepley 
489557cf195SMatthew G. Knepley /* Compare approximation to exact in L_2 */
CheckTransferError(DM fdm,PetscBool usePoly,PetscInt order,PetscInt dir,const char * testname,Vec fu,AppCtx * user)490d71ae5a4SJacob Faibussowitsch static PetscErrorCode CheckTransferError(DM fdm, PetscBool usePoly, PetscInt order, PetscInt dir, const char *testname, Vec fu, AppCtx *user)
491d71ae5a4SJacob Faibussowitsch {
492*2a8381b2SBarry Smith   PetscErrorCode (*exactFuncs[1])(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, PetscCtx ctx);
493*2a8381b2SBarry Smith   PetscErrorCode (*exactFuncDers[1])(PetscInt dim, PetscReal time, const PetscReal x[], const PetscReal n[], PetscInt Nf, PetscScalar *u, PetscCtx ctx);
494557cf195SMatthew G. Knepley   PetscReal n[3] = {1.0, 1.0, 1.0};
495557cf195SMatthew G. Knepley   void     *exactCtxs[3];
496557cf195SMatthew G. Knepley   MPI_Comm  comm;
497557cf195SMatthew G. Knepley   PetscReal error, errorDer, tol = PETSC_SMALL;
498557cf195SMatthew G. Knepley 
499557cf195SMatthew G. Knepley   PetscFunctionBeginUser;
500557cf195SMatthew G. Knepley   exactCtxs[0]       = user;
501557cf195SMatthew G. Knepley   exactCtxs[1]       = user;
502557cf195SMatthew G. Knepley   exactCtxs[2]       = user;
503557cf195SMatthew G. Knepley   user->constants[0] = 1.0;
504557cf195SMatthew G. Knepley   user->constants[1] = 2.0;
505557cf195SMatthew G. Knepley   user->constants[2] = 3.0;
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)fdm, &comm));
5079566063dSJacob Faibussowitsch   PetscCall(SetupFunctions(fdm, usePoly, order, dir, exactFuncs, exactFuncDers, user));
50838cc584fSMatthew G. Knepley   PetscCall(DMGetCoordinatesLocalSetUp(fdm));
5099566063dSJacob Faibussowitsch   PetscCall(DMComputeL2Diff(fdm, 0.0, exactFuncs, exactCtxs, fu, &error));
5109566063dSJacob Faibussowitsch   PetscCall(DMComputeL2GradientDiff(fdm, 0.0, exactFuncDers, exactCtxs, fu, n, &errorDer));
511557cf195SMatthew G. Knepley   /* Report result */
51263a3b9bcSJacob Faibussowitsch   if (error > tol) PetscCall(PetscPrintf(comm, "%s tests FAIL for order %" PetscInt_FMT " at tolerance %g error %g\n", testname, order, (double)tol, (double)error));
51363a3b9bcSJacob Faibussowitsch   else PetscCall(PetscPrintf(comm, "%s tests pass for order %" PetscInt_FMT " at tolerance %g\n", testname, order, (double)tol));
51463a3b9bcSJacob Faibussowitsch   if (errorDer > tol) PetscCall(PetscPrintf(comm, "%s tests FAIL for order %" PetscInt_FMT " derivatives at tolerance %g error %g\n", testname, order, (double)tol, (double)errorDer));
51563a3b9bcSJacob Faibussowitsch   else PetscCall(PetscPrintf(comm, "%s tests pass for order %" PetscInt_FMT " derivatives at tolerance %g\n", testname, order, (double)tol));
5163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
517557cf195SMatthew G. Knepley }
518557cf195SMatthew G. Knepley 
CheckTransfer(DM dm,InterpType inType,PetscInt order,AppCtx * user)519d71ae5a4SJacob Faibussowitsch static PetscErrorCode CheckTransfer(DM dm, InterpType inType, PetscInt order, AppCtx *user)
520d71ae5a4SJacob Faibussowitsch {
521*2a8381b2SBarry Smith   PetscErrorCode (*exactFuncs[1])(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, PetscCtx ctx);
522*2a8381b2SBarry Smith   PetscErrorCode (*exactFuncDers[1])(PetscInt, PetscReal, const PetscReal x[], const PetscReal n[], PetscInt, PetscScalar *u, PetscCtx ctx);
523d6837840SMatthew G. Knepley   void       *exactCtxs[3];
524d6837840SMatthew G. Knepley   DM          rdm = NULL, idm = NULL, fdm = NULL;
525557cf195SMatthew G. Knepley   Mat         Interp, InterpAdapt = NULL;
526d6837840SMatthew G. Knepley   Vec         iu, fu, scaling = NULL;
527557cf195SMatthew G. Knepley   MPI_Comm    comm;
528d6837840SMatthew G. Knepley   const char *testname = "Unknown";
529557cf195SMatthew G. Knepley   char        checkname[PETSC_MAX_PATH_LEN];
530557cf195SMatthew G. Knepley 
531557cf195SMatthew G. Knepley   PetscFunctionBeginUser;
532d6837840SMatthew G. Knepley   exactCtxs[0] = exactCtxs[1] = exactCtxs[2] = user;
5339566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5349566063dSJacob Faibussowitsch   PetscCall(DMRefine(dm, comm, &rdm));
5359566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(rdm, NULL, "-ref_dm_view"));
5369566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(rdm, dm));
5379566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, rdm));
538557cf195SMatthew G. Knepley   switch (inType) {
539557cf195SMatthew G. Knepley   case INTERPOLATION:
540557cf195SMatthew G. Knepley     testname = "Interpolation";
541557cf195SMatthew G. Knepley     idm      = dm;
542557cf195SMatthew G. Knepley     fdm      = rdm;
543557cf195SMatthew G. Knepley     break;
544557cf195SMatthew G. Knepley   case RESTRICTION:
545557cf195SMatthew G. Knepley     testname = "Restriction";
546557cf195SMatthew G. Knepley     idm      = rdm;
547557cf195SMatthew G. Knepley     fdm      = dm;
548557cf195SMatthew G. Knepley     break;
549557cf195SMatthew G. Knepley   case INJECTION:
550557cf195SMatthew G. Knepley     testname = "Injection";
551557cf195SMatthew G. Knepley     idm      = rdm;
552557cf195SMatthew G. Knepley     fdm      = dm;
553557cf195SMatthew G. Knepley     break;
554557cf195SMatthew G. Knepley   }
5559566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(idm, &iu));
5569566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(fdm, &fu));
5579566063dSJacob Faibussowitsch   PetscCall(DMSetApplicationContext(dm, user));
5589566063dSJacob Faibussowitsch   PetscCall(DMSetApplicationContext(rdm, user));
559557cf195SMatthew G. Knepley   /* Project function into initial FE function space */
5609566063dSJacob Faibussowitsch   PetscCall(SetupFunctions(dm, PETSC_TRUE, order, 0, exactFuncs, exactFuncDers, user));
5619566063dSJacob Faibussowitsch   PetscCall(DMProjectFunction(idm, 0.0, exactFuncs, exactCtxs, INSERT_ALL_VALUES, iu));
562557cf195SMatthew G. Knepley   /* Interpolate function into final FE function space */
563557cf195SMatthew G. Knepley   switch (inType) {
564557cf195SMatthew G. Knepley   case INTERPOLATION:
5659566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(dm, rdm, &Interp, &scaling));
5669566063dSJacob Faibussowitsch     PetscCall(MatInterpolate(Interp, iu, fu));
567557cf195SMatthew G. Knepley     break;
568557cf195SMatthew G. Knepley   case RESTRICTION:
5699566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(dm, rdm, &Interp, &scaling));
5709566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Interp, iu, fu));
5719566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(fu, scaling, fu));
572557cf195SMatthew G. Knepley     break;
573557cf195SMatthew G. Knepley   case INJECTION:
5749566063dSJacob Faibussowitsch     PetscCall(DMCreateInjection(dm, rdm, &Interp));
5759566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Interp, iu, fu));
576557cf195SMatthew G. Knepley     break;
577557cf195SMatthew G. Knepley   }
5789566063dSJacob Faibussowitsch   PetscCall(CheckTransferError(fdm, PETSC_TRUE, order, 0, testname, fu, user));
579557cf195SMatthew G. Knepley   if (user->K && (inType == INTERPOLATION)) {
580557cf195SMatthew G. Knepley     KSP      smoother;
5812b3cbbdaSStefano Zampini     Mat      A, iVM, fVM;
5822b3cbbdaSStefano Zampini     Vec      iV, fV;
5832b3cbbdaSStefano Zampini     PetscInt k, dim, d, im, fm;
584557cf195SMatthew G. Knepley 
5859566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(comm, " Adapting interpolator using %s\n", user->usePoly ? "polynomials" : "harmonics"));
5869566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
587557cf195SMatthew G. Knepley     /* Project coarse modes into initial and final FE function space */
5882b3cbbdaSStefano Zampini     PetscCall(DMGetGlobalVector(idm, &iV));
5892b3cbbdaSStefano Zampini     PetscCall(DMGetGlobalVector(fdm, &fV));
5902b3cbbdaSStefano Zampini     PetscCall(VecGetLocalSize(iV, &im));
5912b3cbbdaSStefano Zampini     PetscCall(VecGetLocalSize(fV, &fm));
5922b3cbbdaSStefano Zampini     PetscCall(MatCreateDense(PetscObjectComm((PetscObject)dm), im, PETSC_DECIDE, PETSC_DECIDE, user->K * dim, NULL, &iVM));
5932b3cbbdaSStefano Zampini     PetscCall(MatCreateDense(PetscObjectComm((PetscObject)dm), fm, PETSC_DECIDE, PETSC_DECIDE, user->K * dim, NULL, &fVM));
5942b3cbbdaSStefano Zampini     PetscCall(DMRestoreGlobalVector(idm, &iV));
5952b3cbbdaSStefano Zampini     PetscCall(DMRestoreGlobalVector(fdm, &fV));
596557cf195SMatthew G. Knepley     for (k = 0; k < user->K; ++k) {
597557cf195SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
5982b3cbbdaSStefano Zampini         PetscCall(MatDenseGetColumnVecWrite(iVM, k * dim + d, &iV));
5992b3cbbdaSStefano Zampini         PetscCall(MatDenseGetColumnVecWrite(fVM, k * dim + d, &fV));
6009566063dSJacob Faibussowitsch         PetscCall(SetupFunctions(idm, user->usePoly, user->usePoly ? k : k + 1, d, exactFuncs, exactFuncDers, user));
6012b3cbbdaSStefano Zampini         PetscCall(DMProjectFunction(idm, 0.0, exactFuncs, exactCtxs, INSERT_ALL_VALUES, iV));
6022b3cbbdaSStefano Zampini         PetscCall(DMProjectFunction(fdm, 0.0, exactFuncs, exactCtxs, INSERT_ALL_VALUES, fV));
6032b3cbbdaSStefano Zampini         PetscCall(MatDenseRestoreColumnVecWrite(iVM, k * dim + d, &iV));
6042b3cbbdaSStefano Zampini         PetscCall(MatDenseRestoreColumnVecWrite(fVM, k * dim + d, &fV));
605557cf195SMatthew G. Knepley       }
606557cf195SMatthew G. Knepley     }
6072b3cbbdaSStefano Zampini 
608557cf195SMatthew G. Knepley     /* Adapt interpolator */
6099566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(rdm, &A));
6109566063dSJacob Faibussowitsch     PetscCall(MatShift(A, 1.0));
6119566063dSJacob Faibussowitsch     PetscCall(KSPCreate(comm, &smoother));
6129566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(smoother));
6139566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(smoother, A, A));
6142b3cbbdaSStefano Zampini     PetscCall(DMAdaptInterpolator(dm, rdm, Interp, smoother, fVM, iVM, &InterpAdapt, user));
615557cf195SMatthew G. Knepley     /* Interpolate function into final FE function space */
6169566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(checkname, PETSC_MAX_PATH_LEN, "  %s poly", testname));
6179566063dSJacob Faibussowitsch     PetscCall(MatInterpolate(InterpAdapt, iu, fu));
6189566063dSJacob Faibussowitsch     PetscCall(CheckTransferError(fdm, PETSC_TRUE, order, 0, checkname, fu, user));
619557cf195SMatthew G. Knepley     for (k = 0; k < user->K; ++k) {
620557cf195SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
62163a3b9bcSJacob Faibussowitsch         PetscCall(PetscSNPrintf(checkname, PETSC_MAX_PATH_LEN, "  %s trig (%" PetscInt_FMT ", %" PetscInt_FMT ")", testname, k, d));
6222b3cbbdaSStefano Zampini         PetscCall(MatDenseGetColumnVecRead(iVM, k * dim + d, &iV));
6232b3cbbdaSStefano Zampini         PetscCall(MatDenseGetColumnVecWrite(fVM, k * dim + d, &fV));
6242b3cbbdaSStefano Zampini         PetscCall(MatInterpolate(InterpAdapt, iV, fV));
6252b3cbbdaSStefano Zampini         PetscCall(CheckTransferError(fdm, PETSC_FALSE, k + 1, d, checkname, fV, user));
6262b3cbbdaSStefano Zampini         PetscCall(MatDenseRestoreColumnVecRead(iVM, k * dim + d, &iV));
6272b3cbbdaSStefano Zampini         PetscCall(MatDenseRestoreColumnVecWrite(fVM, k * dim + d, &fV));
628557cf195SMatthew G. Knepley       }
629557cf195SMatthew G. Knepley     }
630557cf195SMatthew G. Knepley     /* Cleanup */
6319566063dSJacob Faibussowitsch     PetscCall(KSPDestroy(&smoother));
6329566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
6339566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&InterpAdapt));
6342b3cbbdaSStefano Zampini     PetscCall(MatDestroy(&iVM));
6352b3cbbdaSStefano Zampini     PetscCall(MatDestroy(&fVM));
636557cf195SMatthew G. Knepley   }
6379566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(idm, &iu));
6389566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(fdm, &fu));
6399566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Interp));
6409566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&scaling));
6419566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
6423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
643557cf195SMatthew G. Knepley }
644557cf195SMatthew G. Knepley 
main(int argc,char ** argv)645d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
646d71ae5a4SJacob Faibussowitsch {
647557cf195SMatthew G. Knepley   DM        dm;
64830602db0SMatthew G. Knepley   PetscFE   fe;
64930602db0SMatthew G. Knepley   AppCtx    user;
65030602db0SMatthew G. Knepley   PetscInt  dim;
65130602db0SMatthew G. Knepley   PetscBool simplex;
652557cf195SMatthew G. Knepley 
653327415f7SBarry Smith   PetscFunctionBeginUser;
6549566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
6559566063dSJacob Faibussowitsch   PetscCall(ProcessOptions(PETSC_COMM_WORLD, &user));
6569566063dSJacob Faibussowitsch   PetscCall(CreateMesh(PETSC_COMM_WORLD, &user, &dm));
65730602db0SMatthew G. Knepley 
6589566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
6599566063dSJacob Faibussowitsch   PetscCall(DMPlexIsSimplex(dm, &simplex));
6609566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_WORLD, dim, user.Nc < 0 ? dim : user.Nc, simplex, NULL, user.qorder, &fe));
6619566063dSJacob Faibussowitsch   PetscCall(DMSetField(dm, 0, NULL, (PetscObject)fe));
6629566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
6639566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(dm));
66430602db0SMatthew G. Knepley 
6659566063dSJacob Faibussowitsch   PetscCall(CheckFunctions(dm, user.porder, &user));
6669566063dSJacob Faibussowitsch   PetscCall(CheckTransfer(dm, INTERPOLATION, user.porder, &user));
6679566063dSJacob Faibussowitsch   PetscCall(CheckTransfer(dm, INJECTION, user.porder, &user));
6689566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm));
6699566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
670b122ec5aSJacob Faibussowitsch   return 0;
671557cf195SMatthew G. Knepley }
672557cf195SMatthew G. Knepley 
673557cf195SMatthew G. Knepley /*TEST
674557cf195SMatthew G. Knepley 
675557cf195SMatthew G. Knepley   # TODO dim 3 will not work until I get composite elements in 3D (see plexrefine.c:34)
676557cf195SMatthew G. Knepley   # 2D/3D P_1 on a simplex
677557cf195SMatthew G. Knepley   test:
678557cf195SMatthew G. Knepley     suffix: p1
679557cf195SMatthew G. Knepley     requires: triangle ctetgen
68030602db0SMatthew G. Knepley     args: -dm_plex_dim {{2}separate output} -dm_plex_box_faces 2,2,2 -petscspace_degree 1 -num_comp 1 -qorder 1 -porder {{1}separate output}
681557cf195SMatthew G. Knepley   test:
682557cf195SMatthew G. Knepley     suffix: p1_pragmatic
683557cf195SMatthew G. Knepley     requires: triangle ctetgen pragmatic
68430602db0SMatthew G. Knepley     args: -dm_plex_dim {{2}separate output} -dm_plex_box_faces 2,2,2 -petscspace_degree 1 -qorder 1 -dm_plex_hash_location -porder {{1 2}separate output}
685557cf195SMatthew G. Knepley   test:
686557cf195SMatthew G. Knepley     suffix: p1_adapt
687557cf195SMatthew G. Knepley     requires: triangle ctetgen
68830602db0SMatthew G. Knepley     args: -dm_plex_dim {{2}separate output} -dm_plex_box_faces 2,2,2 -dm_refine 3 -petscspace_degree 1 -qorder 1 -porder {{1 2}separate output}
689557cf195SMatthew G. Knepley 
690557cf195SMatthew G. Knepley   # TODO dim 3 will not work until I get composite elements in 3D (see plexrefine.c:34)
691557cf195SMatthew G. Knepley   # 2D/3D P_2 on a simplex
692557cf195SMatthew G. Knepley   test:
693557cf195SMatthew G. Knepley     suffix: p2
694557cf195SMatthew G. Knepley     requires: triangle ctetgen
69530602db0SMatthew G. Knepley     args: -dm_plex_dim {{2}separate output} -dm_plex_box_faces 2,2,2 -petscspace_degree 2 -qorder 2 -porder {{1 2 3}separate output}
696557cf195SMatthew G. Knepley   test:
697557cf195SMatthew G. Knepley     suffix: p2_pragmatic
698557cf195SMatthew G. Knepley     requires: triangle ctetgen pragmatic
69930602db0SMatthew G. Knepley     args: -dm_plex_dim {{2}separate output} -dm_plex_box_faces 2,2,2 -petscspace_degree 2 -qorder 2 -dm_plex_hash_location -porder {{1 2 3}separate output}
700557cf195SMatthew G. Knepley 
701557cf195SMatthew G. Knepley   # TODO dim 3 will not work until I get composite elements in 3D (see plexrefine.c:34)
702557cf195SMatthew G. Knepley   # TODO This is broken. Check ex3 which worked
703557cf195SMatthew G. Knepley   # 2D/3D P_3 on a simplex
704557cf195SMatthew G. Knepley   test:
705d6837840SMatthew G. Knepley     TODO: gll Lagrange nodes break this
706557cf195SMatthew G. Knepley     suffix: p3
707557cf195SMatthew G. Knepley     requires: triangle ctetgen !single
70830602db0SMatthew G. Knepley     args: -dm_plex_dim {{2}separate output} -dm_plex_box_faces 2,2,2 -petscspace_degree 3 -qorder 3 -porder {{1 2 3 4}separate output}
709557cf195SMatthew G. Knepley   test:
710d6837840SMatthew G. Knepley     TODO: gll Lagrange nodes break this
711557cf195SMatthew G. Knepley     suffix: p3_pragmatic
712557cf195SMatthew G. Knepley     requires: triangle ctetgen pragmatic !single
71330602db0SMatthew G. Knepley     args: -dm_plex_dim {{2}separate output} -dm_plex_box_faces 2,2,2 -petscspace_degree 3 -qorder 3 -dm_plex_hash_location -porder {{1 2 3 4}separate output}
714557cf195SMatthew G. Knepley 
715557cf195SMatthew G. Knepley   # 2D/3D Q_1 on a tensor cell
716557cf195SMatthew G. Knepley   test:
717557cf195SMatthew G. Knepley     suffix: q1
71830602db0SMatthew G. Knepley     args: -dm_plex_dim {{2 3}separate output} -dm_plex_box_faces 2,2,2 -dm_plex_simplex 0 -petscspace_degree 1 -qorder 1 -porder {{1 2}separate output}
719557cf195SMatthew G. Knepley 
720557cf195SMatthew G. Knepley   # 2D/3D Q_2 on a tensor cell
721557cf195SMatthew G. Knepley   test:
722557cf195SMatthew G. Knepley     suffix: q2
72399a192c5SJunchao Zhang     requires: !single
72430602db0SMatthew G. Knepley     args: -dm_plex_dim {{2 3}separate output} -dm_plex_box_faces 2,2,2 -dm_plex_simplex 0 -petscspace_degree 2 -qorder 2 -porder {{1 2 3}separate output}
725557cf195SMatthew G. Knepley 
726557cf195SMatthew G. Knepley   # 2D/3D Q_3 on a tensor cell
727557cf195SMatthew G. Knepley   test:
728d6837840SMatthew G. Knepley     TODO: gll Lagrange nodes break this
729557cf195SMatthew G. Knepley     suffix: q3
73099a192c5SJunchao Zhang     requires: !single
73130602db0SMatthew G. Knepley     args: -dm_plex_dim {{2 3}separate output} -dm_plex_box_faces 2,2,2 -dm_plex_simplex 0 -petscspace_degree 3 -qorder 3 -porder {{1 2 3 4}separate output}
732557cf195SMatthew G. Knepley 
733557cf195SMatthew G. Knepley   # 2D/3D P_1disc on a triangle/quadrilateral
734557cf195SMatthew G. Knepley   # TODO Missing injection functional for simplices
735557cf195SMatthew G. Knepley   test:
736557cf195SMatthew G. Knepley     suffix: p1d
737557cf195SMatthew G. Knepley     requires: triangle ctetgen
73830602db0SMatthew G. Knepley     args: -dm_plex_dim {{2}separate output} -dm_plex_box_faces 2,2,2 -dm_plex_simplex {{0}separate output} -petscspace_degree 1 -petscdualspace_lagrange_continuity 0 -qorder 1 -porder {{1 2}separate output}
739557cf195SMatthew G. Knepley 
740557cf195SMatthew G. Knepley TEST*/
741