xref: /petsc/src/dm/field/interface/dmfield.c (revision 55e7fe800d976e85ed2b5cd8bfdef564daa37bd9)
1 #include <petsc/private/dmfieldimpl.h> /*I "petscdmfield.h" I*/
2 #include <petsc/private/petscfeimpl.h> /*I "petscdmfield.h" I*/
3 #include <petscdmplex.h>
4 
5 const char *const DMFieldContinuities[] = {
6   "VERTEX",
7   "EDGE",
8   "FACET",
9   "CELL",
10   0
11 };
12 
13 PETSC_INTERN PetscErrorCode DMFieldCreate(DM dm,PetscInt numComponents,DMFieldContinuity continuity,DMField *field)
14 {
15   PetscErrorCode ierr;
16   DMField        b;
17 
18   PetscFunctionBegin;
19   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
20   PetscValidPointer(field,2);
21   ierr = DMFieldInitializePackage();CHKERRQ(ierr);
22 
23   ierr = PetscHeaderCreate(b,DMFIELD_CLASSID,"DMField","Field over DM","DM",PetscObjectComm((PetscObject)dm),DMFieldDestroy,DMFieldView);CHKERRQ(ierr);
24   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
25   b->dm = dm;
26   b->continuity = continuity;
27   b->numComponents = numComponents;
28   *field = b;
29   PetscFunctionReturn(0);
30 }
31 
32 /*@
33    DMFieldDestroy - destroy a DMField
34 
35    Collective
36 
37    Input Arguments:
38 .  field - address of DMField
39 
40    Level: advanced
41 
42 .seealso: DMFieldCreate()
43 @*/
44 PetscErrorCode DMFieldDestroy(DMField *field)
45 {
46   PetscErrorCode ierr;
47 
48   PetscFunctionBegin;
49   if (!*field) PetscFunctionReturn(0);
50   PetscValidHeaderSpecific((*field),DMFIELD_CLASSID,1);
51   if (--((PetscObject)(*field))->refct > 0) {*field = 0; PetscFunctionReturn(0);}
52   if ((*field)->ops->destroy) {ierr = (*(*field)->ops->destroy)(*field);CHKERRQ(ierr);}
53   ierr = DMDestroy(&((*field)->dm));CHKERRQ(ierr);
54   ierr = PetscHeaderDestroy(field);CHKERRQ(ierr);
55   PetscFunctionReturn(0);
56 }
57 
58 /*@C
59    DMFieldView - view a DMField
60 
61    Collective
62 
63    Input Arguments:
64 +  field - DMField
65 -  viewer - viewer to display field, for example PETSC_VIEWER_STDOUT_WORLD
66 
67    Level: advanced
68 
69 .seealso: DMFieldCreate()
70 @*/
71 PetscErrorCode DMFieldView(DMField field,PetscViewer viewer)
72 {
73   PetscErrorCode    ierr;
74   PetscBool         iascii;
75 
76   PetscFunctionBegin;
77   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
78   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)field),&viewer);CHKERRQ(ierr);}
79   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
80   PetscCheckSameComm(field,1,viewer,2);
81   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
82   if (iascii) {
83     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)field,viewer);CHKERRQ(ierr);
84     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
85     ierr = PetscViewerASCIIPrintf(viewer,"%D components\n",field->numComponents);CHKERRQ(ierr);
86     ierr = PetscViewerASCIIPrintf(viewer,"%s continuity\n",DMFieldContinuities[field->continuity]);CHKERRQ(ierr);
87     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_DEFAULT);CHKERRQ(ierr);
88     ierr = DMView(field->dm,viewer);CHKERRQ(ierr);
89     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
90   }
91   if (field->ops->view) {ierr = (*field->ops->view)(field,viewer);CHKERRQ(ierr);}
92   if (iascii) {
93     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
94   }
95   PetscFunctionReturn(0);
96 }
97 
98 /*@C
99    DMFieldSetType - set the DMField implementation
100 
101    Collective on DMField
102 
103    Input Parameters:
104 +  field - the DMField context
105 -  type - a known method
106 
107    Notes:
108    See "include/petscvec.h" for available methods (for instance)
109 +    DMFIELDDA    - a field defined only by its values at the corners of a DMDA
110 .    DMFIELDDS    - a field defined by a discretization over a mesh set with DMSetField()
111 -    DMFIELDSHELL - a field defined by arbitrary callbacks
112 
113   Level: advanced
114 
115 .keywords: DMField, set, type
116 
117 .seealso: DMFieldType,
118 @*/
119 PetscErrorCode DMFieldSetType(DMField field,DMFieldType type)
120 {
121   PetscErrorCode ierr,(*r)(DMField);
122   PetscBool      match;
123 
124   PetscFunctionBegin;
125   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
126   PetscValidCharPointer(type,2);
127 
128   ierr = PetscObjectTypeCompare((PetscObject)field,type,&match);CHKERRQ(ierr);
129   if (match) PetscFunctionReturn(0);
130 
131   ierr = PetscFunctionListFind(DMFieldList,type,&r);CHKERRQ(ierr);
132   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested DMField type %s",type);
133   /* Destroy the previous private DMField context */
134   if (field->ops->destroy) {
135     ierr = (*(field)->ops->destroy)(field);CHKERRQ(ierr);
136   }
137   ierr = PetscMemzero(field->ops,sizeof(*field->ops));CHKERRQ(ierr);
138   ierr = PetscObjectChangeTypeName((PetscObject)field,type);CHKERRQ(ierr);
139   field->ops->create = r;
140   ierr = (*r)(field);CHKERRQ(ierr);
141   PetscFunctionReturn(0);
142 }
143 
144 /*@C
145   DMFieldGetType - Gets the DMField type name (as a string) from the DMField.
146 
147   Not Collective
148 
149   Input Parameter:
150 . field  - The DMField context
151 
152   Output Parameter:
153 . type - The DMField type name
154 
155   Level: advanced
156 
157 .keywords: DMField, get, type, name
158 .seealso: DMFieldSetType()
159 @*/
160 PetscErrorCode  DMFieldGetType(DMField field, DMFieldType *type)
161 {
162   PetscErrorCode ierr;
163 
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(field, VEC_TAGGER_CLASSID,1);
166   PetscValidPointer(type,2);
167   ierr = DMFieldRegisterAll();CHKERRQ(ierr);
168   *type = ((PetscObject)field)->type_name;
169   PetscFunctionReturn(0);
170 }
171 
172 /*@
173   DMFieldGetNumComponents - Returns the number of components in the field
174 
175   Not collective
176 
177   Input Parameter:
178 . field - The DMField object
179 
180   Output Parameter:
181 . nc - The number of field components
182 
183   Level: intermediate
184 
185 .seealso: DMFieldEvaluate()
186 @*/
187 PetscErrorCode DMFieldGetNumComponents(DMField field, PetscInt *nc)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
191   PetscValidIntPointer(nc,2);
192   *nc = field->numComponents;
193   PetscFunctionReturn(0);
194 }
195 
196 /*@
197   DMFieldGetDM - Returns the DM for the manifold over which the field is defined.
198 
199   Not collective
200 
201   Input Parameter:
202 . field - The DMField object
203 
204   Output Parameter:
205 . dm - The DM object
206 
207   Level: intermediate
208 
209 .seealso: DMFieldEvaluate()
210 @*/
211 PetscErrorCode DMFieldGetDM(DMField field, DM *dm)
212 {
213   PetscFunctionBegin;
214   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
215   PetscValidPointer(dm,2);
216   *dm = field->dm;
217   PetscFunctionReturn(0);
218 }
219 
220 /*@
221   DMFieldEvaluate - Evaluate the field and its derivatives on a set of points
222 
223   Collective on Vec
224 
225   Input Parameter:
226 + field - The DMField object
227 . points - The points at which to evaluate the field.  Should have size d x n,
228            where d is the coordinate dimension of the manifold and n is the number
229            of points
230 - datatype - The PetscDataType of the output arrays: either PETSC_REAL or PETSC_SCALAR.
231              If the field is complex and datatype is PETSC_REAL, the real part of the
232              field is returned.
233 
234 
235   Output Parameter:
236 + B - pointer to data of size c * n * sizeof(datatype), where c is the number of components in the field.
237       If B is not NULL, the values of the field are written in this array, varying first by component,
238       then by point.
239 . D - pointer to data of size d * c * n * sizeof(datatype).
240       If D is not NULL, the values of the field's spatial derivatives are written in this array,
241       varying first by the partial derivative component, then by field component, then by point.
242 - H - pointer to data of size d * d * c * n * sizeof(datatype).
243       If H is not NULL, the values of the field's second spatial derivatives are written in this array,
244       varying first by the second partial derivative component, then by field component, then by point.
245 
246   Level: intermediate
247 
248 .seealso: DMFieldGetDM(), DMFieldGetNumComponents(), DMFieldEvaluateFE(), DMFieldEvaluateFV()
249 @*/
250 PetscErrorCode DMFieldEvaluate(DMField field, Vec points, PetscDataType datatype, void *B, void *D, void *H)
251 {
252   PetscErrorCode ierr;
253 
254   PetscFunctionBegin;
255   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
256   PetscValidHeaderSpecific(points,VEC_CLASSID,2);
257   if (B) PetscValidPointer(B,3);
258   if (D) PetscValidPointer(D,4);
259   if (H) PetscValidPointer(H,5);
260   if (field->ops->evaluate) {
261     ierr = (*field->ops->evaluate) (field, points, datatype, B, D, H);CHKERRQ(ierr);
262   } else SETERRQ (PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Not implemented for this type");
263   PetscFunctionReturn(0);
264 }
265 
266 /*@
267   DMFieldEvaluateFE - Evaluate the field and its derivatives on a set of points mapped from
268   quadrature points on a reference point.  The derivatives are taken with respect to the
269   reference coordinates.
270 
271   Not collective
272 
273   Input Parameter:
274 + field - The DMField object
275 . cellIS - Index set for cells on which to evaluate the field
276 . points - The quadature containing the points in the reference cell at which to evaluate the field.
277 - datatype - The PetscDataType of the output arrays: either PETSC_REAL or PETSC_SCALAR.
278              If the field is complex and datatype is PETSC_REAL, the real part of the
279              field is returned.
280 
281 
282   Output Parameter:
283 + B - pointer to data of size c * n * sizeof(datatype), where c is the number of components in the field.
284       If B is not NULL, the values of the field are written in this array, varying first by component,
285       then by point.
286 . D - pointer to data of size d * c * n * sizeof(datatype).
287       If D is not NULL, the values of the field's spatial derivatives are written in this array,
288       varying first by the partial derivative component, then by field component, then by point.
289 - H - pointer to data of size d * d * c * n * sizeof(datatype).
290       If H is not NULL, the values of the field's second spatial derivatives are written in this array,
291       varying first by the second partial derivative component, then by field component, then by point.
292 
293   Level: intermediate
294 
295 .seealso: DMFieldGetNumComponents(), DMFieldEvaluate(), DMFieldEvaluateFV()
296 @*/
297 PetscErrorCode DMFieldEvaluateFE(DMField field, IS cellIS, PetscQuadrature points, PetscDataType datatype, void *B, void *D, void *H)
298 {
299   PetscErrorCode ierr;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
303   PetscValidHeaderSpecific(cellIS,IS_CLASSID,2);
304   PetscValidHeader(points,3);
305   if (B) PetscValidPointer(B,4);
306   if (D) PetscValidPointer(D,5);
307   if (H) PetscValidPointer(H,6);
308   if (field->ops->evaluateFE) {
309     ierr = (*field->ops->evaluateFE) (field, cellIS, points, datatype, B, D, H);CHKERRQ(ierr);
310   } else SETERRQ (PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Not implemented for this type");
311   PetscFunctionReturn(0);
312 }
313 
314 /*@
315   DMFieldEvaluateFV - Evaluate the mean of a field and its finite volume derivatives on a set of points.
316 
317   Not collective
318 
319   Input Parameter:
320 + field - The DMField object
321 . cellIS - Index set for cells on which to evaluate the field
322 - datatype - The PetscDataType of the output arrays: either PETSC_REAL or PETSC_SCALAR.
323              If the field is complex and datatype is PETSC_REAL, the real part of the
324              field is returned.
325 
326 
327   Output Parameter:
328 + B - pointer to data of size c * n * sizeof(datatype), where c is the number of components in the field.
329       If B is not NULL, the values of the field are written in this array, varying first by component,
330       then by point.
331 . D - pointer to data of size d * c * n * sizeof(datatype).
332       If D is not NULL, the values of the field's spatial derivatives are written in this array,
333       varying first by the partial derivative component, then by field component, then by point.
334 - H - pointer to data of size d * d * c * n * sizeof(datatype).
335       If H is not NULL, the values of the field's second spatial derivatives are written in this array,
336       varying first by the second partial derivative component, then by field component, then by point.
337 
338   Level: intermediate
339 
340 .seealso: DMFieldGetNumComponents(), DMFieldEvaluate(), DMFieldEvaluateFE()
341 @*/
342 PetscErrorCode DMFieldEvaluateFV(DMField field, IS cellIS, PetscDataType datatype, void *B, void *D, void *H)
343 {
344   PetscErrorCode ierr;
345 
346   PetscFunctionBegin;
347   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
348   PetscValidHeaderSpecific(cellIS,IS_CLASSID,2);
349   if (B) PetscValidPointer(B,3);
350   if (D) PetscValidPointer(D,4);
351   if (H) PetscValidPointer(H,5);
352   if (field->ops->evaluateFV) {
353     ierr = (*field->ops->evaluateFV) (field, cellIS, datatype, B, D, H);CHKERRQ(ierr);
354   } else SETERRQ (PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Not implemented for this type");
355   PetscFunctionReturn(0);
356 }
357 
358 /*@
359   DMFieldGetDegree - Get the polynomial degree of a field when pulled back onto the
360   reference element
361 
362   Not collective
363 
364   Input Arguments:
365 + field - the DMField object
366 - cellIS - the index set of points over which we want know the invariance
367 
368   Output Arguments:
369 + minDegree - the degree of the largest polynomial space contained in the field on each element
370 - maxDegree - the largest degree of the smallest polynomial space containing the field on any element
371 
372   Level: intermediate
373 
374 .seealso: DMFieldEvaluateFE()
375 @*/
376 PetscErrorCode DMFieldGetDegree(DMField field, IS cellIS, PetscInt *minDegree, PetscInt *maxDegree)
377 {
378   PetscErrorCode ierr;
379 
380   PetscFunctionBegin;
381   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
382   PetscValidHeaderSpecific(cellIS,IS_CLASSID,2);
383   if (minDegree) PetscValidPointer(minDegree,3);
384   if (maxDegree) PetscValidPointer(maxDegree,4);
385 
386   if (minDegree) *minDegree = -1;
387   if (maxDegree) *maxDegree = PETSC_MAX_INT;
388 
389   if (field->ops->getDegree) {
390     ierr = (*field->ops->getDegree) (field,cellIS,minDegree,maxDegree);CHKERRQ(ierr);
391   }
392   PetscFunctionReturn(0);
393 }
394 
395 /*@
396   DMFieldCreateDefaultQuadrature - Creates a quadrature sufficient to integrate the field on the selected
397   points via pullback onto the reference element
398 
399   Not collective
400 
401   Input Arguments:
402 + field - the DMField object
403 - pointIS - the index set of points over which we wish to integrate the field
404 
405   Output Arguments:
406 . quad - a PetscQuadrature object
407 
408   Level: developer
409 
410 .seealso: DMFieldEvaluteFE(), DMFieldGetDegree()
411 @*/
412 PetscErrorCode DMFieldCreateDefaultQuadrature(DMField field, IS pointIS, PetscQuadrature *quad)
413 {
414   PetscErrorCode ierr;
415 
416   PetscFunctionBegin;
417   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
418   PetscValidHeaderSpecific(pointIS,IS_CLASSID,2);
419   PetscValidPointer(quad,3);
420 
421   *quad = NULL;
422   if (field->ops->createDefaultQuadrature) {
423     ierr = (*field->ops->createDefaultQuadrature)(field, pointIS, quad);CHKERRQ(ierr);
424   }
425   PetscFunctionReturn(0);
426 }
427 
428 /*@C
429   DMFieldCreateFEGeom - Compute and create the geometric factors of a coordinate field
430 
431   Not collective
432 
433   Input Arguments:
434 + field - the DMField object
435 . pointIS - the index set of points over which we wish to integrate the field
436 . quad - the quadrature points at which to evaluate the geometric factors
437 - faceData - whether additional data for facets (the normal vectors and adjacent cells) should
438   be calculated
439 
440   Output Arguments:
441 . geom - the geometric factors
442 
443   Level: developer
444 
445 .seealso: DMFieldEvaluateFE(), DMFieldCreateDefaulteQuadrature(), DMFieldGetDegree()
446 @*/
447 PetscErrorCode DMFieldCreateFEGeom(DMField field, IS pointIS, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom)
448 {
449   PetscInt       dim, dE;
450   PetscInt       nPoints;
451   PetscInt       maxDegree;
452   PetscFEGeom    *g;
453   PetscErrorCode ierr;
454 
455   PetscFunctionBegin;
456   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
457   PetscValidHeaderSpecific(pointIS,IS_CLASSID,2);
458   PetscValidHeader(quad,3);
459   ierr = ISGetLocalSize(pointIS,&nPoints);CHKERRQ(ierr);
460   dE = field->numComponents;
461   ierr = PetscFEGeomCreate(quad,nPoints,dE,faceData,&g);CHKERRQ(ierr);
462   ierr = DMFieldEvaluateFE(field,pointIS,quad,PETSC_REAL,g->v,g->J,NULL);CHKERRQ(ierr);
463   dim = g->dim;
464   if (dE > dim) {
465     /* space out J and make square Jacobians */
466     PetscInt  i, j, k, N = g->numPoints * g->numCells;
467 
468     for (i = N-1; i >= 0; i--) {
469       PetscReal   J[9];
470 
471       for (j = 0; j < dE; j++) {
472         for (k = 0; k < dim; k++) {
473           J[j*dE + k] = g->J[i*dE*dim + j*dim + k];
474         }
475       }
476       switch (dim) {
477       case 0:
478         for (j = 0; j < dE; j++) {
479           for (k = 0; k < dE; k++) {
480             J[j * dE + k] = (j == k) ? 1. : 0.;
481           }
482         }
483         break;
484       case 1:
485         if (dE == 2) {
486           PetscReal norm = PetscSqrtReal(J[0] * J[0] + J[2] * J[2]);
487 
488           J[1] = -J[2] / norm;
489           J[3] =  J[0] / norm;
490         } else {
491           PetscReal inorm = 1./PetscSqrtReal(J[0] * J[0] + J[3] * J[3] + J[6] * J[6]);
492           PetscReal x = J[0] * inorm;
493           PetscReal y = J[3] * inorm;
494           PetscReal z = J[6] * inorm;
495 
496           if (x > 0.) {
497             PetscReal inv1pX   = 1./ (1. + x);
498 
499             J[1] = -y;              J[2] = -z;
500             J[4] = 1. - y*y*inv1pX; J[5] =     -y*z*inv1pX;
501             J[7] =     -y*z*inv1pX; J[8] = 1. - z*z*inv1pX;
502           } else {
503             PetscReal inv1mX   = 1./ (1. - x);
504 
505             J[1] = z;               J[2] = y;
506             J[4] =     -y*z*inv1mX; J[5] = 1. - y*y*inv1mX;
507             J[7] = 1. - z*z*inv1mX; J[8] =     -y*z*inv1mX;
508           }
509         }
510         break;
511       case 2:
512         {
513           PetscReal inorm;
514 
515           J[2] = J[3] * J[7] - J[6] * J[4];
516           J[5] = J[6] * J[1] - J[0] * J[7];
517           J[8] = J[0] * J[4] - J[3] * J[1];
518 
519           inorm = 1./ PetscSqrtReal(J[2]*J[2] + J[5]*J[5] + J[8]*J[8]);
520 
521           J[2] *= inorm;
522           J[5] *= inorm;
523           J[8] *= inorm;
524         }
525         break;
526       }
527       for (j = 0; j < dE*dE; j++) {
528         g->J[i*dE*dE + j] = J[j];
529       }
530     }
531   }
532   ierr = PetscFEGeomComplete(g);CHKERRQ(ierr);
533   ierr = DMFieldGetDegree(field,pointIS,NULL,&maxDegree);CHKERRQ(ierr);
534   g->isAffine = (maxDegree <= 1) ? PETSC_TRUE : PETSC_FALSE;
535   if (faceData) {
536     if (!field->ops->computeFaceData) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "DMField implementation does not compute face data\n");
537     ierr = (*field->ops->computeFaceData) (field, pointIS, quad, g);CHKERRQ(ierr);
538   }
539   *geom = g;
540   PetscFunctionReturn(0);
541 }
542