xref: /petsc/src/dm/field/interface/dmfield.c (revision d7cc930e14e615e9907267aaa472dd0ccceeab82)
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   NULL
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 = NULL; 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 field
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 .seealso: DMFieldType,
116 @*/
117 PetscErrorCode DMFieldSetType(DMField field,DMFieldType type)
118 {
119   PetscErrorCode ierr,(*r)(DMField);
120   PetscBool      match;
121 
122   PetscFunctionBegin;
123   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
124   PetscValidCharPointer(type,2);
125 
126   ierr = PetscObjectTypeCompare((PetscObject)field,type,&match);CHKERRQ(ierr);
127   if (match) PetscFunctionReturn(0);
128 
129   ierr = PetscFunctionListFind(DMFieldList,type,&r);CHKERRQ(ierr);
130   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested DMField type %s",type);
131   /* Destroy the previous private DMField context */
132   if (field->ops->destroy) {
133     ierr = (*(field)->ops->destroy)(field);CHKERRQ(ierr);
134   }
135   ierr = PetscMemzero(field->ops,sizeof(*field->ops));CHKERRQ(ierr);
136   ierr = PetscObjectChangeTypeName((PetscObject)field,type);CHKERRQ(ierr);
137   field->ops->create = r;
138   ierr = (*r)(field);CHKERRQ(ierr);
139   PetscFunctionReturn(0);
140 }
141 
142 /*@C
143   DMFieldGetType - Gets the DMField type name (as a string) from the DMField.
144 
145   Not Collective
146 
147   Input Parameter:
148 . field  - The DMField context
149 
150   Output Parameter:
151 . type - The DMField type name
152 
153   Level: advanced
154 
155 .seealso: DMFieldSetType()
156 @*/
157 PetscErrorCode  DMFieldGetType(DMField field, DMFieldType *type)
158 {
159   PetscErrorCode ierr;
160 
161   PetscFunctionBegin;
162   PetscValidHeaderSpecific(field, VEC_TAGGER_CLASSID,1);
163   PetscValidPointer(type,2);
164   ierr = DMFieldRegisterAll();CHKERRQ(ierr);
165   *type = ((PetscObject)field)->type_name;
166   PetscFunctionReturn(0);
167 }
168 
169 /*@
170   DMFieldGetNumComponents - Returns the number of components in the field
171 
172   Not collective
173 
174   Input Parameter:
175 . field - The DMField object
176 
177   Output Parameter:
178 . nc - The number of field components
179 
180   Level: intermediate
181 
182 .seealso: DMFieldEvaluate()
183 @*/
184 PetscErrorCode DMFieldGetNumComponents(DMField field, PetscInt *nc)
185 {
186   PetscFunctionBegin;
187   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
188   PetscValidIntPointer(nc,2);
189   *nc = field->numComponents;
190   PetscFunctionReturn(0);
191 }
192 
193 /*@
194   DMFieldGetDM - Returns the DM for the manifold over which the field is defined.
195 
196   Not collective
197 
198   Input Parameter:
199 . field - The DMField object
200 
201   Output Parameter:
202 . dm - The DM object
203 
204   Level: intermediate
205 
206 .seealso: DMFieldEvaluate()
207 @*/
208 PetscErrorCode DMFieldGetDM(DMField field, DM *dm)
209 {
210   PetscFunctionBegin;
211   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
212   PetscValidPointer(dm,2);
213   *dm = field->dm;
214   PetscFunctionReturn(0);
215 }
216 
217 /*@
218   DMFieldEvaluate - Evaluate the field and its derivatives on a set of points
219 
220   Collective on points
221 
222   Input Parameter:
223 + field - The DMField object
224 . points - The points at which to evaluate the field.  Should have size d x n,
225            where d is the coordinate dimension of the manifold and n is the number
226            of points
227 - datatype - The PetscDataType of the output arrays: either PETSC_REAL or PETSC_SCALAR.
228              If the field is complex and datatype is PETSC_REAL, the real part of the
229              field is returned.
230 
231 
232   Output Parameter:
233 + B - pointer to data of size c * n * sizeof(datatype), where c is the number of components in the field.
234       If B is not NULL, the values of the field are written in this array, varying first by component,
235       then by point.
236 . D - pointer to data of size d * c * n * sizeof(datatype).
237       If D is not NULL, the values of the field's spatial derivatives are written in this array,
238       varying first by the partial derivative component, then by field component, then by point.
239 - H - pointer to data of size d * d * c * n * sizeof(datatype).
240       If H is not NULL, the values of the field's second spatial derivatives are written in this array,
241       varying first by the second partial derivative component, then by field component, then by point.
242 
243   Level: intermediate
244 
245 .seealso: DMFieldGetDM(), DMFieldGetNumComponents(), DMFieldEvaluateFE(), DMFieldEvaluateFV()
246 @*/
247 PetscErrorCode DMFieldEvaluate(DMField field, Vec points, PetscDataType datatype, void *B, void *D, void *H)
248 {
249   PetscErrorCode ierr;
250 
251   PetscFunctionBegin;
252   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
253   PetscValidHeaderSpecific(points,VEC_CLASSID,2);
254   if (B) PetscValidPointer(B,3);
255   if (D) PetscValidPointer(D,4);
256   if (H) PetscValidPointer(H,5);
257   if (field->ops->evaluate) {
258     ierr = (*field->ops->evaluate) (field, points, datatype, B, D, H);CHKERRQ(ierr);
259   } else SETERRQ (PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Not implemented for this type");
260   PetscFunctionReturn(0);
261 }
262 
263 /*@
264   DMFieldEvaluateFE - Evaluate the field and its derivatives on a set of points mapped from
265   quadrature points on a reference point.  The derivatives are taken with respect to the
266   reference coordinates.
267 
268   Not collective
269 
270   Input Parameter:
271 + field - The DMField object
272 . cellIS - Index set for cells on which to evaluate the field
273 . points - The quadature containing the points in the reference cell at which to evaluate the field.
274 - datatype - The PetscDataType of the output arrays: either PETSC_REAL or PETSC_SCALAR.
275              If the field is complex and datatype is PETSC_REAL, the real part of the
276              field is returned.
277 
278 
279   Output Parameter:
280 + B - pointer to data of size c * n * sizeof(datatype), where c is the number of components in the field.
281       If B is not NULL, the values of the field are written in this array, varying first by component,
282       then by point.
283 . D - pointer to data of size d * c * n * sizeof(datatype).
284       If D is not NULL, the values of the field's spatial derivatives are written in this array,
285       varying first by the partial derivative component, then by field component, then by point.
286 - H - pointer to data of size d * d * c * n * sizeof(datatype).
287       If H is not NULL, the values of the field's second spatial derivatives are written in this array,
288       varying first by the second partial derivative component, then by field component, then by point.
289 
290   Level: intermediate
291 
292 .seealso: DMFieldGetNumComponents(), DMFieldEvaluate(), DMFieldEvaluateFV()
293 @*/
294 PetscErrorCode DMFieldEvaluateFE(DMField field, IS cellIS, PetscQuadrature points, PetscDataType datatype, void *B, void *D, void *H)
295 {
296   PetscErrorCode ierr;
297 
298   PetscFunctionBegin;
299   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
300   PetscValidHeaderSpecific(cellIS,IS_CLASSID,2);
301   PetscValidHeader(points,3);
302   if (B) PetscValidPointer(B,4);
303   if (D) PetscValidPointer(D,5);
304   if (H) PetscValidPointer(H,6);
305   if (field->ops->evaluateFE) {
306     ierr = (*field->ops->evaluateFE) (field, cellIS, points, datatype, B, D, H);CHKERRQ(ierr);
307   } else SETERRQ (PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Not implemented for this type");
308   PetscFunctionReturn(0);
309 }
310 
311 /*@
312   DMFieldEvaluateFV - Evaluate the mean of a field and its finite volume derivatives on a set of points.
313 
314   Not collective
315 
316   Input Parameter:
317 + field - The DMField object
318 . cellIS - Index set for cells on which to evaluate the field
319 - datatype - The PetscDataType of the output arrays: either PETSC_REAL or PETSC_SCALAR.
320              If the field is complex and datatype is PETSC_REAL, the real part of the
321              field is returned.
322 
323 
324   Output Parameter:
325 + B - pointer to data of size c * n * sizeof(datatype), where c is the number of components in the field.
326       If B is not NULL, the values of the field are written in this array, varying first by component,
327       then by point.
328 . D - pointer to data of size d * c * n * sizeof(datatype).
329       If D is not NULL, the values of the field's spatial derivatives are written in this array,
330       varying first by the partial derivative component, then by field component, then by point.
331 - H - pointer to data of size d * d * c * n * sizeof(datatype).
332       If H is not NULL, the values of the field's second spatial derivatives are written in this array,
333       varying first by the second partial derivative component, then by field component, then by point.
334 
335   Level: intermediate
336 
337 .seealso: DMFieldGetNumComponents(), DMFieldEvaluate(), DMFieldEvaluateFE()
338 @*/
339 PetscErrorCode DMFieldEvaluateFV(DMField field, IS cellIS, PetscDataType datatype, void *B, void *D, void *H)
340 {
341   PetscErrorCode ierr;
342 
343   PetscFunctionBegin;
344   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
345   PetscValidHeaderSpecific(cellIS,IS_CLASSID,2);
346   if (B) PetscValidPointer(B,3);
347   if (D) PetscValidPointer(D,4);
348   if (H) PetscValidPointer(H,5);
349   if (field->ops->evaluateFV) {
350     ierr = (*field->ops->evaluateFV) (field, cellIS, datatype, B, D, H);CHKERRQ(ierr);
351   } else SETERRQ (PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Not implemented for this type");
352   PetscFunctionReturn(0);
353 }
354 
355 /*@
356   DMFieldGetDegree - Get the polynomial degree of a field when pulled back onto the
357   reference element
358 
359   Not collective
360 
361   Input Arguments:
362 + field - the DMField object
363 - cellIS - the index set of points over which we want know the invariance
364 
365   Output Arguments:
366 + minDegree - the degree of the largest polynomial space contained in the field on each element
367 - maxDegree - the largest degree of the smallest polynomial space containing the field on any element
368 
369   Level: intermediate
370 
371 .seealso: DMFieldEvaluateFE()
372 @*/
373 PetscErrorCode DMFieldGetDegree(DMField field, IS cellIS, PetscInt *minDegree, PetscInt *maxDegree)
374 {
375   PetscErrorCode ierr;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
379   PetscValidHeaderSpecific(cellIS,IS_CLASSID,2);
380   if (minDegree) PetscValidPointer(minDegree,3);
381   if (maxDegree) PetscValidPointer(maxDegree,4);
382 
383   if (minDegree) *minDegree = -1;
384   if (maxDegree) *maxDegree = PETSC_MAX_INT;
385 
386   if (field->ops->getDegree) {
387     ierr = (*field->ops->getDegree) (field,cellIS,minDegree,maxDegree);CHKERRQ(ierr);
388   }
389   PetscFunctionReturn(0);
390 }
391 
392 /*@
393   DMFieldCreateDefaultQuadrature - Creates a quadrature sufficient to integrate the field on the selected
394   points via pullback onto the reference element
395 
396   Not collective
397 
398   Input Arguments:
399 + field - the DMField object
400 - pointIS - the index set of points over which we wish to integrate the field
401 
402   Output Arguments:
403 . quad - a PetscQuadrature object
404 
405   Level: developer
406 
407 .seealso: DMFieldEvaluteFE(), DMFieldGetDegree()
408 @*/
409 PetscErrorCode DMFieldCreateDefaultQuadrature(DMField field, IS pointIS, PetscQuadrature *quad)
410 {
411   PetscErrorCode ierr;
412 
413   PetscFunctionBegin;
414   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
415   PetscValidHeaderSpecific(pointIS,IS_CLASSID,2);
416   PetscValidPointer(quad,3);
417 
418   *quad = NULL;
419   if (field->ops->createDefaultQuadrature) {
420     ierr = (*field->ops->createDefaultQuadrature)(field, pointIS, quad);CHKERRQ(ierr);
421   }
422   PetscFunctionReturn(0);
423 }
424 
425 /*@C
426   DMFieldCreateFEGeom - Compute and create the geometric factors of a coordinate field
427 
428   Not collective
429 
430   Input Arguments:
431 + field - the DMField object
432 . pointIS - the index set of points over which we wish to integrate the field
433 . quad - the quadrature points at which to evaluate the geometric factors
434 - faceData - whether additional data for facets (the normal vectors and adjacent cells) should
435   be calculated
436 
437   Output Arguments:
438 . geom - the geometric factors
439 
440   Level: developer
441 
442 .seealso: DMFieldEvaluateFE(), DMFieldCreateDefaulteQuadrature(), DMFieldGetDegree()
443 @*/
444 PetscErrorCode DMFieldCreateFEGeom(DMField field, IS pointIS, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom)
445 {
446   PetscInt       dim, dE;
447   PetscInt       nPoints;
448   PetscInt       maxDegree;
449   PetscFEGeom    *g;
450   PetscErrorCode ierr;
451 
452   PetscFunctionBegin;
453   PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1);
454   PetscValidHeaderSpecific(pointIS,IS_CLASSID,2);
455   PetscValidHeader(quad,3);
456   ierr = ISGetLocalSize(pointIS,&nPoints);CHKERRQ(ierr);
457   dE = field->numComponents;
458   ierr = PetscFEGeomCreate(quad,nPoints,dE,faceData,&g);CHKERRQ(ierr);
459   ierr = DMFieldEvaluateFE(field,pointIS,quad,PETSC_REAL,g->v,g->J,NULL);CHKERRQ(ierr);
460   dim = g->dim;
461   if (dE > dim) {
462     /* space out J and make square Jacobians */
463     PetscInt  i, j, k, N = g->numPoints * g->numCells;
464 
465     for (i = N-1; i >= 0; i--) {
466       PetscReal   J[9];
467 
468       for (j = 0; j < dE; j++) {
469         for (k = 0; k < dim; k++) {
470           J[j*dE + k] = g->J[i*dE*dim + j*dim + k];
471         }
472       }
473       switch (dim) {
474       case 0:
475         for (j = 0; j < dE; j++) {
476           for (k = 0; k < dE; k++) {
477             J[j * dE + k] = (j == k) ? 1. : 0.;
478           }
479         }
480         break;
481       case 1:
482         if (dE == 2) {
483           PetscReal norm = PetscSqrtReal(J[0] * J[0] + J[2] * J[2]);
484 
485           J[1] = -J[2] / norm;
486           J[3] =  J[0] / norm;
487         } else {
488           PetscReal inorm = 1./PetscSqrtReal(J[0] * J[0] + J[3] * J[3] + J[6] * J[6]);
489           PetscReal x = J[0] * inorm;
490           PetscReal y = J[3] * inorm;
491           PetscReal z = J[6] * inorm;
492 
493           if (x > 0.) {
494             PetscReal inv1pX   = 1./ (1. + x);
495 
496             J[1] = -y;              J[2] = -z;
497             J[4] = 1. - y*y*inv1pX; J[5] =     -y*z*inv1pX;
498             J[7] =     -y*z*inv1pX; J[8] = 1. - z*z*inv1pX;
499           } else {
500             PetscReal inv1mX   = 1./ (1. - x);
501 
502             J[1] = z;               J[2] = y;
503             J[4] =     -y*z*inv1mX; J[5] = 1. - y*y*inv1mX;
504             J[7] = 1. - z*z*inv1mX; J[8] =     -y*z*inv1mX;
505           }
506         }
507         break;
508       case 2:
509         {
510           PetscReal inorm;
511 
512           J[2] = J[3] * J[7] - J[6] * J[4];
513           J[5] = J[6] * J[1] - J[0] * J[7];
514           J[8] = J[0] * J[4] - J[3] * J[1];
515 
516           inorm = 1./ PetscSqrtReal(J[2]*J[2] + J[5]*J[5] + J[8]*J[8]);
517 
518           J[2] *= inorm;
519           J[5] *= inorm;
520           J[8] *= inorm;
521         }
522         break;
523       }
524       for (j = 0; j < dE*dE; j++) {
525         g->J[i*dE*dE + j] = J[j];
526       }
527     }
528   }
529   ierr = PetscFEGeomComplete(g);CHKERRQ(ierr);
530   ierr = DMFieldGetDegree(field,pointIS,NULL,&maxDegree);CHKERRQ(ierr);
531   g->isAffine = (maxDegree <= 1) ? PETSC_TRUE : PETSC_FALSE;
532   if (faceData) {
533     if (!field->ops->computeFaceData) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "DMField implementation does not compute face data\n");
534     ierr = (*field->ops->computeFaceData) (field, pointIS, quad, g);CHKERRQ(ierr);
535   }
536   *geom = g;
537   PetscFunctionReturn(0);
538 }
539