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