xref: /petsc/src/dm/field/impls/shell/dmfieldshell.c (revision 9566063d113dddea24716c546802770db7481bc0)
151a454edSToby Isaac #include <petsc/private/dmfieldimpl.h> /*I "petscdmfield.h" I*/
251a454edSToby Isaac 
3028944aaSToby Isaac typedef struct _n_DMField_Shell
451a454edSToby Isaac {
5028944aaSToby Isaac   void *ctx;
6028944aaSToby Isaac   PetscErrorCode (*destroy) (DMField);
7028944aaSToby Isaac }
8028944aaSToby Isaac DMField_Shell;
9028944aaSToby Isaac 
10028944aaSToby Isaac PetscErrorCode DMFieldShellGetContext(DMField field, void *ctx)
11028944aaSToby Isaac {
12028944aaSToby Isaac   PetscBool      flg;
13028944aaSToby Isaac 
1451a454edSToby Isaac   PetscFunctionBegin;
15028944aaSToby Isaac   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
16028944aaSToby Isaac   PetscValidPointer(ctx,2);
17*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)field,DMFIELDSHELL,&flg));
18028944aaSToby Isaac   if (flg) *(void**)ctx = ((DMField_Shell*)(field->data))->ctx;
19028944aaSToby Isaac   else SETERRQ(PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Cannot get context from non-shell shield");
2051a454edSToby Isaac   PetscFunctionReturn(0);
2151a454edSToby Isaac }
2251a454edSToby Isaac 
23028944aaSToby Isaac static PetscErrorCode DMFieldDestroy_Shell(DMField field)
24028944aaSToby Isaac {
25028944aaSToby Isaac   DMField_Shell *shell = (DMField_Shell *) field->data;
2651a454edSToby Isaac 
27028944aaSToby Isaac   PetscFunctionBegin;
28*9566063dSJacob Faibussowitsch   if (shell->destroy) PetscCall((*(shell->destroy)) (field));
29*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(field->data));
30028944aaSToby Isaac   PetscFunctionReturn(0);
31028944aaSToby Isaac }
32028944aaSToby Isaac 
33028944aaSToby Isaac PetscErrorCode DMFieldShellEvaluateFEDefault(DMField field, IS pointIS, PetscQuadrature quad, PetscDataType type, void *B, void *D, void *H)
34028944aaSToby Isaac {
35028944aaSToby Isaac   DM              dm = field->dm;
36028944aaSToby Isaac   DMField         coordField;
37028944aaSToby Isaac   PetscFEGeom    *geom;
38028944aaSToby Isaac   Vec             pushforward;
39028944aaSToby Isaac   PetscInt        dimC, dim, numPoints, Nq, p, Nc;
40028944aaSToby Isaac   PetscScalar    *pfArray;
41028944aaSToby Isaac 
42028944aaSToby Isaac   PetscFunctionBegin;
43028944aaSToby Isaac   Nc   = field->numComponents;
44*9566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateField(dm, &coordField));
45*9566063dSJacob Faibussowitsch   PetscCall(DMFieldCreateFEGeom(coordField, pointIS, quad, PETSC_FALSE, &geom));
46*9566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimC));
47*9566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureGetData(quad, &dim, NULL, &Nq, NULL, NULL));
48*9566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(pointIS, &numPoints));
49*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(dimC * Nq * numPoints, &pfArray));
50028944aaSToby Isaac   for (p = 0; p < numPoints * dimC * Nq; p++) pfArray[p] = (PetscScalar) geom->v[p];
51*9566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)pointIS), dimC, dimC * Nq * numPoints, PETSC_DETERMINE, pfArray, &pushforward));
52*9566063dSJacob Faibussowitsch   PetscCall(DMFieldEvaluate(field, pushforward, type, B, D, H));
53028944aaSToby Isaac   /* TODO: handle covariant/contravariant pullbacks */
54028944aaSToby Isaac   if (D) {
55028944aaSToby Isaac     if (type == PETSC_SCALAR) {
56028944aaSToby Isaac       PetscScalar *sD = (PetscScalar *) D;
57028944aaSToby Isaac       PetscInt q;
58028944aaSToby Isaac 
59028944aaSToby Isaac       for (p = 0; p < numPoints * Nq; p++) {
60028944aaSToby Isaac         for (q = 0; q < Nc; q++) {
61028944aaSToby Isaac           PetscScalar d[3];
62028944aaSToby Isaac 
63028944aaSToby Isaac           PetscInt i, j;
64028944aaSToby Isaac 
65028944aaSToby Isaac           for (i = 0; i < dimC; i++) d[i] = sD[(p * Nc + q) * dimC + i];
66028944aaSToby Isaac           for (i = 0; i < dimC; i++) sD[(p * Nc + q) * dimC + i] = 0.;
67028944aaSToby Isaac           for (i = 0; i < dimC; i++) {
68028944aaSToby Isaac             for (j = 0; j < dimC; j++) {
69028944aaSToby Isaac               sD[(p * Nc + q) * dimC + i] += geom->J[(p * dimC + j) * dimC + i] * d[j];
70028944aaSToby Isaac             }
71028944aaSToby Isaac           }
72028944aaSToby Isaac         }
73028944aaSToby Isaac       }
74028944aaSToby Isaac     } else {
75028944aaSToby Isaac       PetscReal *rD = (PetscReal *) D;
76028944aaSToby Isaac       PetscInt q;
77028944aaSToby Isaac 
78028944aaSToby Isaac       for (p = 0; p < numPoints * Nq; p++) {
79028944aaSToby Isaac         for (q = 0; q < Nc; q++) {
80028944aaSToby Isaac           PetscReal d[3];
81028944aaSToby Isaac 
82028944aaSToby Isaac           PetscInt i, j;
83028944aaSToby Isaac 
84028944aaSToby Isaac           for (i = 0; i < dimC; i++) d[i] = rD[(p * Nc + q) * dimC + i];
85028944aaSToby Isaac           for (i = 0; i < dimC; i++) rD[(p * Nc + q) * dimC + i] = 0.;
86028944aaSToby Isaac           for (i = 0; i < dimC; i++) {
87028944aaSToby Isaac             for (j = 0; j < dimC; j++) {
88028944aaSToby Isaac               rD[(p * Nc + q) * dimC + i] += geom->J[(p * dimC + j) * dimC + i] * d[j];
89028944aaSToby Isaac             }
90028944aaSToby Isaac           }
91028944aaSToby Isaac         }
92028944aaSToby Isaac       }
93028944aaSToby Isaac     }
94028944aaSToby Isaac   }
95028944aaSToby Isaac   if (H) {
96028944aaSToby Isaac     if (type == PETSC_SCALAR) {
97028944aaSToby Isaac       PetscScalar *sH = (PetscScalar *) H;
98028944aaSToby Isaac       PetscInt q;
99028944aaSToby Isaac 
100028944aaSToby Isaac       for (p = 0; p < numPoints * Nq; p++) {
101028944aaSToby Isaac         for (q = 0; q < Nc; q++) {
102028944aaSToby Isaac           PetscScalar d[3][3];
103028944aaSToby Isaac 
104028944aaSToby Isaac           PetscInt i, j, k, l;
105028944aaSToby Isaac 
106028944aaSToby Isaac           for (i = 0; i < dimC; i++) for (j = 0; j < dimC; j++) d[i][j] = sH[((p * Nc + q) * dimC + i) * dimC + j];
107028944aaSToby Isaac           for (i = 0; i < dimC; i++) for (j = 0; j < dimC; j++) sH[((p * Nc + q) * dimC + i) * dimC + j] = 0.;
108028944aaSToby Isaac           for (i = 0; i < dimC; i++) {
109028944aaSToby Isaac             for (j = 0; j < dimC; j++) {
110028944aaSToby Isaac               for (k = 0; k < dimC; k++) {
111028944aaSToby Isaac                 for (l = 0; l < dimC; l++) {
112028944aaSToby Isaac                   sH[((p * Nc + q) * dimC + i) * dimC + j] += geom->J[(p * dimC + k) * dimC + i] * geom->J[(p * dimC + l) * dimC + j] * d[k][l];
113028944aaSToby Isaac                 }
114028944aaSToby Isaac               }
115028944aaSToby Isaac             }
116028944aaSToby Isaac           }
117028944aaSToby Isaac         }
118028944aaSToby Isaac       }
119028944aaSToby Isaac     } else {
120028944aaSToby Isaac       PetscReal *rH = (PetscReal *) H;
121028944aaSToby Isaac       PetscInt q;
122028944aaSToby Isaac 
123028944aaSToby Isaac       for (p = 0; p < numPoints * Nq; p++) {
124028944aaSToby Isaac         for (q = 0; q < Nc; q++) {
125028944aaSToby Isaac           PetscReal d[3][3];
126028944aaSToby Isaac 
127028944aaSToby Isaac           PetscInt i, j, k, l;
128028944aaSToby Isaac 
129028944aaSToby Isaac           for (i = 0; i < dimC; i++) for (j = 0; j < dimC; j++) d[i][j] = rH[((p * Nc + q) * dimC + i) * dimC + j];
130028944aaSToby Isaac           for (i = 0; i < dimC; i++) for (j = 0; j < dimC; j++) rH[((p * Nc + q) * dimC + i) * dimC + j] = 0.;
131028944aaSToby Isaac           for (i = 0; i < dimC; i++) {
132028944aaSToby Isaac             for (j = 0; j < dimC; j++) {
133028944aaSToby Isaac               for (k = 0; k < dimC; k++) {
134028944aaSToby Isaac                 for (l = 0; l < dimC; l++) {
135028944aaSToby Isaac                   rH[((p * Nc + q) * dimC + i) * dimC + j] += geom->J[(p * dimC + k) * dimC + i] * geom->J[(p * dimC + l) * dimC + j] * d[k][l];
136028944aaSToby Isaac                 }
137028944aaSToby Isaac               }
138028944aaSToby Isaac             }
139028944aaSToby Isaac           }
140028944aaSToby Isaac         }
141028944aaSToby Isaac       }
142028944aaSToby Isaac     }
143028944aaSToby Isaac   }
144*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pushforward));
145*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(pfArray));
146*9566063dSJacob Faibussowitsch   PetscCall(PetscFEGeomDestroy(&geom));
147028944aaSToby Isaac   PetscFunctionReturn(0);
148028944aaSToby Isaac }
149028944aaSToby Isaac 
150028944aaSToby Isaac PetscErrorCode DMFieldShellEvaluateFVDefault(DMField field, IS pointIS, PetscDataType type, void *B, void *D, void *H)
151028944aaSToby Isaac {
152028944aaSToby Isaac   DM              dm = field->dm;
153028944aaSToby Isaac   DMField         coordField;
154028944aaSToby Isaac   PetscFEGeom    *geom;
155028944aaSToby Isaac   Vec             pushforward;
156028944aaSToby Isaac   PetscInt        dimC, dim, numPoints, Nq, p;
157028944aaSToby Isaac   PetscScalar    *pfArray;
158028944aaSToby Isaac   PetscQuadrature quad;
159a2aba86cSMatthew G. Knepley   MPI_Comm        comm;
160028944aaSToby Isaac 
161028944aaSToby Isaac   PetscFunctionBegin;
162*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) field, &comm));
163*9566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
164*9566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimC));
165*9566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateField(dm, &coordField));
166*9566063dSJacob Faibussowitsch   PetscCall(DMFieldGetFVQuadrature_Internal(coordField, pointIS, &quad));
167a2aba86cSMatthew G. Knepley   PetscCheck(quad, comm, PETSC_ERR_ARG_WRONGSTATE, "coordinate field must have default quadrature for FV computation");
168*9566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL));
169a2aba86cSMatthew G. Knepley   PetscCheck(Nq == 1, comm, PETSC_ERR_ARG_WRONGSTATE, "quadrature must have only one point");
170*9566063dSJacob Faibussowitsch   PetscCall(DMFieldCreateFEGeom(coordField, pointIS, quad, PETSC_FALSE, &geom));
171*9566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(pointIS, &numPoints));
172*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(dimC * numPoints, &pfArray));
173028944aaSToby Isaac   for (p = 0; p < numPoints * dimC; p++) pfArray[p] = (PetscScalar) geom->v[p];
174*9566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)pointIS), dimC, dimC * numPoints, PETSC_DETERMINE, pfArray, &pushforward));
175*9566063dSJacob Faibussowitsch   PetscCall(DMFieldEvaluate(field, pushforward, type, B, D, H));
176*9566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&quad));
177*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pushforward));
178*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(pfArray));
179*9566063dSJacob Faibussowitsch   PetscCall(PetscFEGeomDestroy(&geom));
180028944aaSToby Isaac   PetscFunctionReturn(0);
181028944aaSToby Isaac }
182028944aaSToby Isaac 
183028944aaSToby Isaac PetscErrorCode DMFieldShellSetDestroy(DMField field, PetscErrorCode (*destroy)(DMField))
184028944aaSToby Isaac {
185028944aaSToby Isaac   DMField_Shell *shell = (DMField_Shell *) field->data;
186028944aaSToby Isaac 
187028944aaSToby Isaac   PetscFunctionBegin;
188028944aaSToby Isaac   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
189028944aaSToby Isaac   shell->destroy = destroy;
190028944aaSToby Isaac   PetscFunctionReturn(0);
191028944aaSToby Isaac }
192028944aaSToby Isaac 
193028944aaSToby Isaac PetscErrorCode DMFieldShellSetEvaluate(DMField field, PetscErrorCode (*evaluate)(DMField,Vec,PetscDataType,void*,void*,void*))
194028944aaSToby Isaac {
195028944aaSToby Isaac   PetscFunctionBegin;
196028944aaSToby Isaac   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
197028944aaSToby Isaac   field->ops->evaluate = evaluate;
198028944aaSToby Isaac   PetscFunctionReturn(0);
199028944aaSToby Isaac }
200028944aaSToby Isaac 
201028944aaSToby Isaac PetscErrorCode DMFieldShellSetEvaluateFE(DMField field, PetscErrorCode (*evaluateFE)(DMField,IS,PetscQuadrature,PetscDataType,void*,void*,void*))
202028944aaSToby Isaac {
203028944aaSToby Isaac   PetscFunctionBegin;
204028944aaSToby Isaac   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
205028944aaSToby Isaac   field->ops->evaluateFE = evaluateFE;
206028944aaSToby Isaac   PetscFunctionReturn(0);
207028944aaSToby Isaac }
208028944aaSToby Isaac 
209028944aaSToby Isaac PetscErrorCode DMFieldShellSetEvaluateFV(DMField field, PetscErrorCode (*evaluateFV)(DMField,IS,PetscDataType,void*,void*,void*))
210028944aaSToby Isaac {
211028944aaSToby Isaac   PetscFunctionBegin;
212028944aaSToby Isaac   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
213028944aaSToby Isaac   field->ops->evaluateFV = evaluateFV;
214028944aaSToby Isaac   PetscFunctionReturn(0);
215028944aaSToby Isaac }
216028944aaSToby Isaac 
217b7260050SToby Isaac PetscErrorCode DMFieldShellSetGetDegree(DMField field, PetscErrorCode (*getDegree)(DMField,IS,PetscInt*,PetscInt*))
218028944aaSToby Isaac {
219028944aaSToby Isaac   PetscFunctionBegin;
220028944aaSToby Isaac   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
221b7260050SToby Isaac   field->ops->getDegree = getDegree;
222028944aaSToby Isaac   PetscFunctionReturn(0);
223028944aaSToby Isaac }
224028944aaSToby Isaac 
225028944aaSToby Isaac PetscErrorCode DMFieldShellSetCreateDefaultQuadrature(DMField field, PetscErrorCode (*createDefaultQuadrature)(DMField,IS,PetscQuadrature*))
226028944aaSToby Isaac {
227028944aaSToby Isaac   PetscFunctionBegin;
228028944aaSToby Isaac   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
229028944aaSToby Isaac   field->ops->createDefaultQuadrature = createDefaultQuadrature;
230028944aaSToby Isaac   PetscFunctionReturn(0);
231028944aaSToby Isaac }
232028944aaSToby Isaac 
233028944aaSToby Isaac static PetscErrorCode DMFieldInitialize_Shell(DMField field)
234028944aaSToby Isaac {
235028944aaSToby Isaac   PetscFunctionBegin;
236028944aaSToby Isaac   field->ops->destroy                 = DMFieldDestroy_Shell;
237028944aaSToby Isaac   field->ops->evaluate                = NULL;
238028944aaSToby Isaac   field->ops->evaluateFE              = DMFieldShellEvaluateFEDefault;
239028944aaSToby Isaac   field->ops->evaluateFV              = DMFieldShellEvaluateFVDefault;
240b7260050SToby Isaac   field->ops->getDegree               = NULL;
241028944aaSToby Isaac   field->ops->createDefaultQuadrature = NULL;
242028944aaSToby Isaac   field->ops->view                    = NULL;
243028944aaSToby Isaac   PetscFunctionReturn(0);
244028944aaSToby Isaac }
245028944aaSToby Isaac 
246028944aaSToby Isaac PETSC_INTERN PetscErrorCode DMFieldCreate_Shell(DMField field)
247028944aaSToby Isaac {
248028944aaSToby Isaac   DMField_Shell *shell;
249028944aaSToby Isaac 
250028944aaSToby Isaac   PetscFunctionBegin;
251*9566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(field,&shell));
252028944aaSToby Isaac   field->data = shell;
253*9566063dSJacob Faibussowitsch   PetscCall(DMFieldInitialize_Shell(field));
254028944aaSToby Isaac   PetscFunctionReturn(0);
255028944aaSToby Isaac }
256028944aaSToby Isaac 
257028944aaSToby Isaac PetscErrorCode DMFieldCreateShell(DM dm, PetscInt numComponents, DMFieldContinuity continuity, void *ctx, DMField *field)
258028944aaSToby Isaac {
259028944aaSToby Isaac   DMField        b;
260028944aaSToby Isaac   DMField_Shell  *shell;
261028944aaSToby Isaac 
262028944aaSToby Isaac   PetscFunctionBegin;
263028944aaSToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
264028944aaSToby Isaac   if (ctx) PetscValidPointer(ctx, 4);
265028944aaSToby Isaac   PetscValidPointer(field, 5);
266*9566063dSJacob Faibussowitsch   PetscCall(DMFieldCreate(dm,numComponents,continuity,&b));
267*9566063dSJacob Faibussowitsch   PetscCall(DMFieldSetType(b,DMFIELDSHELL));
268028944aaSToby Isaac   shell = (DMField_Shell *) b->data;
269028944aaSToby Isaac   shell->ctx = ctx;
270028944aaSToby Isaac   *field = b;
271028944aaSToby Isaac   PetscFunctionReturn(0);
272028944aaSToby Isaac }
273