120cf1dd8SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
220cf1dd8SToby Isaac #include <petscdmplex.h>
320cf1dd8SToby Isaac
420cf1dd8SToby Isaac PetscClassId PETSCDUALSPACE_CLASSID = 0;
520cf1dd8SToby Isaac
6ead873ccSMatthew G. Knepley PetscLogEvent PETSCDUALSPACE_SetUp;
7ead873ccSMatthew G. Knepley
820cf1dd8SToby Isaac PetscFunctionList PetscDualSpaceList = NULL;
920cf1dd8SToby Isaac PetscBool PetscDualSpaceRegisterAllCalled = PETSC_FALSE;
1020cf1dd8SToby Isaac
116f905325SMatthew G. Knepley /*
126f905325SMatthew G. Knepley PetscDualSpaceLatticePointLexicographic_Internal - Returns all tuples of size 'len' with nonnegative integers that sum up to at most 'max'.
136f905325SMatthew G. Knepley Ordering is lexicographic with lowest index as least significant in ordering.
14b4457527SToby Isaac e.g. for len == 2 and max == 2, this will return, in order, {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {0,2}.
156f905325SMatthew G. Knepley
166f905325SMatthew G. Knepley Input Parameters:
176f905325SMatthew G. Knepley + len - The length of the tuple
186f905325SMatthew G. Knepley . max - The maximum sum
196f905325SMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition
206f905325SMatthew G. Knepley
216f905325SMatthew G. Knepley Output Parameter:
2220f4b53cSBarry Smith . tup - A tuple of `len` integers whose sum is at most `max`
236f905325SMatthew G. Knepley
246f905325SMatthew G. Knepley Level: developer
256f905325SMatthew G. Knepley
26dce8aebaSBarry Smith .seealso: `PetscDualSpaceType`, `PetscDualSpaceTensorPointLexicographic_Internal()`
276f905325SMatthew G. Knepley */
PetscDualSpaceLatticePointLexicographic_Internal(PetscInt len,PetscInt max,PetscInt tup[])28d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceLatticePointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[])
29d71ae5a4SJacob Faibussowitsch {
306f905325SMatthew G. Knepley PetscFunctionBegin;
316f905325SMatthew G. Knepley while (len--) {
326f905325SMatthew G. Knepley max -= tup[len];
336f905325SMatthew G. Knepley if (!max) {
346f905325SMatthew G. Knepley tup[len] = 0;
356f905325SMatthew G. Knepley break;
366f905325SMatthew G. Knepley }
376f905325SMatthew G. Knepley }
386f905325SMatthew G. Knepley tup[++len]++;
393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
406f905325SMatthew G. Knepley }
416f905325SMatthew G. Knepley
426f905325SMatthew G. Knepley /*
436f905325SMatthew G. Knepley PetscDualSpaceTensorPointLexicographic_Internal - Returns all tuples of size 'len' with nonnegative integers that are all less than or equal to 'max'.
446f905325SMatthew G. Knepley Ordering is lexicographic with lowest index as least significant in ordering.
456f905325SMatthew G. Knepley e.g. for len == 2 and max == 2, this will return, in order, {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0,2}, {1,2}, {2,2}.
466f905325SMatthew G. Knepley
476f905325SMatthew G. Knepley Input Parameters:
486f905325SMatthew G. Knepley + len - The length of the tuple
496f905325SMatthew G. Knepley . max - The maximum value
506f905325SMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition
516f905325SMatthew G. Knepley
526f905325SMatthew G. Knepley Output Parameter:
5320f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max`
546f905325SMatthew G. Knepley
556f905325SMatthew G. Knepley Level: developer
566f905325SMatthew G. Knepley
57dce8aebaSBarry Smith .seealso: `PetscDualSpaceType`, `PetscDualSpaceLatticePointLexicographic_Internal()`
586f905325SMatthew G. Knepley */
PetscDualSpaceTensorPointLexicographic_Internal(PetscInt len,PetscInt max,PetscInt tup[])59d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTensorPointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[])
60d71ae5a4SJacob Faibussowitsch {
616f905325SMatthew G. Knepley PetscInt i;
626f905325SMatthew G. Knepley
636f905325SMatthew G. Knepley PetscFunctionBegin;
646f905325SMatthew G. Knepley for (i = 0; i < len; i++) {
656f905325SMatthew G. Knepley if (tup[i] < max) {
666f905325SMatthew G. Knepley break;
676f905325SMatthew G. Knepley } else {
686f905325SMatthew G. Knepley tup[i] = 0;
696f905325SMatthew G. Knepley }
706f905325SMatthew G. Knepley }
716f905325SMatthew G. Knepley tup[i]++;
723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
736f905325SMatthew G. Knepley }
746f905325SMatthew G. Knepley
7520cf1dd8SToby Isaac /*@C
76dce8aebaSBarry Smith PetscDualSpaceRegister - Adds a new `PetscDualSpaceType`
7720cf1dd8SToby Isaac
78cc4c1da9SBarry Smith Not Collective, No Fortran Support
7920cf1dd8SToby Isaac
8020cf1dd8SToby Isaac Input Parameters:
812fe279fdSBarry Smith + sname - The name of a new user-defined creation routine
822fe279fdSBarry Smith - function - The creation routine
8320cf1dd8SToby Isaac
8460225df5SJacob Faibussowitsch Example Usage:
8520cf1dd8SToby Isaac .vb
8620cf1dd8SToby Isaac PetscDualSpaceRegister("my_space", MyPetscDualSpaceCreate);
8720cf1dd8SToby Isaac .ve
8820cf1dd8SToby Isaac
8920cf1dd8SToby Isaac Then, your PetscDualSpace type can be chosen with the procedural interface via
9020cf1dd8SToby Isaac .vb
9120cf1dd8SToby Isaac PetscDualSpaceCreate(MPI_Comm, PetscDualSpace *);
9220cf1dd8SToby Isaac PetscDualSpaceSetType(PetscDualSpace, "my_dual_space");
9320cf1dd8SToby Isaac .ve
9420cf1dd8SToby Isaac or at runtime via the option
9520cf1dd8SToby Isaac .vb
9620cf1dd8SToby Isaac -petscdualspace_type my_dual_space
9720cf1dd8SToby Isaac .ve
9820cf1dd8SToby Isaac
9920cf1dd8SToby Isaac Level: advanced
10020cf1dd8SToby Isaac
101dce8aebaSBarry Smith Note:
102dce8aebaSBarry Smith `PetscDualSpaceRegister()` may be called multiple times to add several user-defined `PetscDualSpace`
10320cf1dd8SToby Isaac
104dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceType`, `PetscDualSpaceRegisterAll()`, `PetscDualSpaceRegisterDestroy()`
10520cf1dd8SToby Isaac @*/
PetscDualSpaceRegister(const char sname[],PetscErrorCode (* function)(PetscDualSpace))106d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceRegister(const char sname[], PetscErrorCode (*function)(PetscDualSpace))
107d71ae5a4SJacob Faibussowitsch {
10820cf1dd8SToby Isaac PetscFunctionBegin;
1099566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&PetscDualSpaceList, sname, function));
1103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
11120cf1dd8SToby Isaac }
11220cf1dd8SToby Isaac
11326a11704SBarry Smith /*@C
114dce8aebaSBarry Smith PetscDualSpaceSetType - Builds a particular `PetscDualSpace` based on its `PetscDualSpaceType`
11520cf1dd8SToby Isaac
11620f4b53cSBarry Smith Collective
11720cf1dd8SToby Isaac
11820cf1dd8SToby Isaac Input Parameters:
119dce8aebaSBarry Smith + sp - The `PetscDualSpace` object
12020cf1dd8SToby Isaac - name - The kind of space
12120cf1dd8SToby Isaac
12220cf1dd8SToby Isaac Options Database Key:
12320cf1dd8SToby Isaac . -petscdualspace_type <type> - Sets the PetscDualSpace type; use -help for a list of available types
12420cf1dd8SToby Isaac
12520cf1dd8SToby Isaac Level: intermediate
12620cf1dd8SToby Isaac
127dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceType`, `PetscDualSpaceGetType()`, `PetscDualSpaceCreate()`
12820cf1dd8SToby Isaac @*/
PetscDualSpaceSetType(PetscDualSpace sp,PetscDualSpaceType name)129d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetType(PetscDualSpace sp, PetscDualSpaceType name)
130d71ae5a4SJacob Faibussowitsch {
13120cf1dd8SToby Isaac PetscErrorCode (*r)(PetscDualSpace);
13220cf1dd8SToby Isaac PetscBool match;
13320cf1dd8SToby Isaac
13420cf1dd8SToby Isaac PetscFunctionBegin;
13520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
1369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)sp, name, &match));
1373ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS);
13820cf1dd8SToby Isaac
1399566063dSJacob Faibussowitsch if (!PetscDualSpaceRegisterAllCalled) PetscCall(PetscDualSpaceRegisterAll());
1409566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(PetscDualSpaceList, name, &r));
14128b400f6SJacob Faibussowitsch PetscCheck(r, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDualSpace type: %s", name);
14220cf1dd8SToby Isaac
143dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, destroy);
14420cf1dd8SToby Isaac sp->ops->destroy = NULL;
145dbbe0bcdSBarry Smith
1469566063dSJacob Faibussowitsch PetscCall((*r)(sp));
1479566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)sp, name));
1483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
14920cf1dd8SToby Isaac }
15020cf1dd8SToby Isaac
15126a11704SBarry Smith /*@C
152dce8aebaSBarry Smith PetscDualSpaceGetType - Gets the `PetscDualSpaceType` name (as a string) from the object.
15320cf1dd8SToby Isaac
15420cf1dd8SToby Isaac Not Collective
15520cf1dd8SToby Isaac
15620cf1dd8SToby Isaac Input Parameter:
157dce8aebaSBarry Smith . sp - The `PetscDualSpace`
15820cf1dd8SToby Isaac
15920cf1dd8SToby Isaac Output Parameter:
160dce8aebaSBarry Smith . name - The `PetscDualSpaceType` name
16120cf1dd8SToby Isaac
16220cf1dd8SToby Isaac Level: intermediate
16320cf1dd8SToby Isaac
164dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceType`, `PetscDualSpaceSetType()`, `PetscDualSpaceCreate()`
16520cf1dd8SToby Isaac @*/
PetscDualSpaceGetType(PetscDualSpace sp,PetscDualSpaceType * name)166d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetType(PetscDualSpace sp, PetscDualSpaceType *name)
167d71ae5a4SJacob Faibussowitsch {
16820cf1dd8SToby Isaac PetscFunctionBegin;
16920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
1704f572ea9SToby Isaac PetscAssertPointer(name, 2);
17148a46eb9SPierre Jolivet if (!PetscDualSpaceRegisterAllCalled) PetscCall(PetscDualSpaceRegisterAll());
17220cf1dd8SToby Isaac *name = ((PetscObject)sp)->type_name;
1733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
17420cf1dd8SToby Isaac }
17520cf1dd8SToby Isaac
PetscDualSpaceView_ASCII(PetscDualSpace sp,PetscViewer v)176d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDualSpaceView_ASCII(PetscDualSpace sp, PetscViewer v)
177d71ae5a4SJacob Faibussowitsch {
178221d6281SMatthew G. Knepley PetscViewerFormat format;
179221d6281SMatthew G. Knepley PetscInt pdim, f;
180221d6281SMatthew G. Knepley
181221d6281SMatthew G. Knepley PetscFunctionBegin;
1829566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &pdim));
1839566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)sp, v));
1849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v));
1852dce792eSToby Isaac if (sp->k != 0 && sp->k != PETSC_FORM_DEGREE_UNDEFINED) {
18663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual space for %" PetscInt_FMT "-forms %swith %" PetscInt_FMT " components, size %" PetscInt_FMT "\n", PetscAbsInt(sp->k), sp->k < 0 ? "(stored in dual form) " : "", sp->Nc, pdim));
187b4457527SToby Isaac } else {
18863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual space with %" PetscInt_FMT " components, size %" PetscInt_FMT "\n", sp->Nc, pdim));
189b4457527SToby Isaac }
190dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, view, v);
1919566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(v, &format));
192221d6281SMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v));
194221d6281SMatthew G. Knepley for (f = 0; f < pdim; ++f) {
19563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual basis vector %" PetscInt_FMT "\n", f));
1969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v));
1979566063dSJacob Faibussowitsch PetscCall(PetscQuadratureView(sp->functional[f], v));
1989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v));
199221d6281SMatthew G. Knepley }
2009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v));
201221d6281SMatthew G. Knepley }
2029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v));
2033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
204221d6281SMatthew G. Knepley }
205221d6281SMatthew G. Knepley
20626a11704SBarry Smith /*@C
207dce8aebaSBarry Smith PetscDualSpaceViewFromOptions - View a `PetscDualSpace` based on values in the options database
208fe2efc57SMark
20920f4b53cSBarry Smith Collective
210fe2efc57SMark
211fe2efc57SMark Input Parameters:
212dce8aebaSBarry Smith + A - the `PetscDualSpace` object
213dce8aebaSBarry Smith . obj - Optional object, provides the options prefix
214dce8aebaSBarry Smith - name - command line option name
215fe2efc57SMark
216fe2efc57SMark Level: intermediate
217dce8aebaSBarry Smith
21820f4b53cSBarry Smith Note:
21920f4b53cSBarry Smith See `PetscObjectViewFromOptions()` for possible command line values
22020f4b53cSBarry Smith
221db781477SPatrick Sanan .seealso: `PetscDualSpace`, `PetscDualSpaceView()`, `PetscObjectViewFromOptions()`, `PetscDualSpaceCreate()`
222fe2efc57SMark @*/
PetscDualSpaceViewFromOptions(PetscDualSpace A,PeOp PetscObject obj,const char name[])223ce78bad3SBarry Smith PetscErrorCode PetscDualSpaceViewFromOptions(PetscDualSpace A, PeOp PetscObject obj, const char name[])
224d71ae5a4SJacob Faibussowitsch {
225fe2efc57SMark PetscFunctionBegin;
226fe2efc57SMark PetscValidHeaderSpecific(A, PETSCDUALSPACE_CLASSID, 1);
2279566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
2283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
229fe2efc57SMark }
230fe2efc57SMark
23126a11704SBarry Smith /*@C
232dce8aebaSBarry Smith PetscDualSpaceView - Views a `PetscDualSpace`
23320cf1dd8SToby Isaac
23420f4b53cSBarry Smith Collective
23520cf1dd8SToby Isaac
236d8d19677SJose E. Roman Input Parameters:
237dce8aebaSBarry Smith + sp - the `PetscDualSpace` object to view
23820cf1dd8SToby Isaac - v - the viewer
23920cf1dd8SToby Isaac
240a4ce7ad1SMatthew G. Knepley Level: beginner
24120cf1dd8SToby Isaac
242dce8aebaSBarry Smith .seealso: `PetscViewer`, `PetscDualSpaceDestroy()`, `PetscDualSpace`
24320cf1dd8SToby Isaac @*/
PetscDualSpaceView(PetscDualSpace sp,PetscViewer v)244d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceView(PetscDualSpace sp, PetscViewer v)
245d71ae5a4SJacob Faibussowitsch {
2469f196a02SMartin Diehl PetscBool isascii;
24720cf1dd8SToby Isaac
24820cf1dd8SToby Isaac PetscFunctionBegin;
24920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
250d9bac1caSLisandro Dalcin if (v) PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2);
2519566063dSJacob Faibussowitsch if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sp), &v));
2529f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &isascii));
2539f196a02SMartin Diehl if (isascii) PetscCall(PetscDualSpaceView_ASCII(sp, v));
2543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
25520cf1dd8SToby Isaac }
25620cf1dd8SToby Isaac
25726a11704SBarry Smith /*@C
258dce8aebaSBarry Smith PetscDualSpaceSetFromOptions - sets parameters in a `PetscDualSpace` from the options database
25920cf1dd8SToby Isaac
26020f4b53cSBarry Smith Collective
26120cf1dd8SToby Isaac
26220cf1dd8SToby Isaac Input Parameter:
263dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to set options for
26420cf1dd8SToby Isaac
265dce8aebaSBarry Smith Options Database Keys:
2668f2aacc6SMatthew G. Knepley + -petscdualspace_order <order> - the approximation order of the space
267fe36a153SMatthew G. Knepley . -petscdualspace_form_degree <deg> - the form degree, say 0 for point evaluations, or 2 for area integrals
2688f2aacc6SMatthew G. Knepley . -petscdualspace_components <c> - the number of components, say d for a vector field
269a9c5e6deSMatthew G. Knepley . -petscdualspace_refcell <celltype> - Reference cell type name
270a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_continuity - Flag for continuous element
271a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_tensor - Flag for tensor dual space
272a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_trimmed - Flag for trimmed dual space
273a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_node_type <nodetype> - Lagrange node location type
274a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_node_endpoints - Flag for nodes that include endpoints
275a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_node_exponent - Gauss-Jacobi weight function exponent
276a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_use_moments - Use moments (where appropriate) for functionals
277a9c5e6deSMatthew G. Knepley - -petscdualspace_lagrange_moment_order <order> - Quadrature order for moment functionals
27820cf1dd8SToby Isaac
279a4ce7ad1SMatthew G. Knepley Level: intermediate
28020cf1dd8SToby Isaac
281dce8aebaSBarry Smith .seealso: `PetscDualSpaceView()`, `PetscDualSpace`, `PetscObjectSetFromOptions()`
28220cf1dd8SToby Isaac @*/
PetscDualSpaceSetFromOptions(PetscDualSpace sp)283d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetFromOptions(PetscDualSpace sp)
284d71ae5a4SJacob Faibussowitsch {
2852df84da0SMatthew G. Knepley DMPolytopeType refCell = DM_POLYTOPE_TRIANGLE;
28620cf1dd8SToby Isaac const char *defaultType;
28720cf1dd8SToby Isaac char name[256];
288f783ec47SMatthew G. Knepley PetscBool flg;
28920cf1dd8SToby Isaac
29020cf1dd8SToby Isaac PetscFunctionBegin;
29120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
29220cf1dd8SToby Isaac if (!((PetscObject)sp)->type_name) {
29320cf1dd8SToby Isaac defaultType = PETSCDUALSPACELAGRANGE;
29420cf1dd8SToby Isaac } else {
29520cf1dd8SToby Isaac defaultType = ((PetscObject)sp)->type_name;
29620cf1dd8SToby Isaac }
2979566063dSJacob Faibussowitsch if (!PetscSpaceRegisterAllCalled) PetscCall(PetscSpaceRegisterAll());
29820cf1dd8SToby Isaac
299d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)sp);
3009566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-petscdualspace_type", "Dual space", "PetscDualSpaceSetType", PetscDualSpaceList, defaultType, name, 256, &flg));
30120cf1dd8SToby Isaac if (flg) {
3029566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, name));
30320cf1dd8SToby Isaac } else if (!((PetscObject)sp)->type_name) {
3049566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, defaultType));
30520cf1dd8SToby Isaac }
3069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_order", "The approximation order", "PetscDualSpaceSetOrder", sp->order, &sp->order, NULL, 0));
3079566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-petscdualspace_form_degree", "The form degree of the dofs", "PetscDualSpaceSetFormDegree", sp->k, &sp->k, NULL));
3089566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_components", "The number of components", "PetscDualSpaceSetNumComponents", sp->Nc, &sp->Nc, NULL, 1));
309dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, setfromoptions, PetscOptionsObject);
3109566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-petscdualspace_refcell", "Reference cell shape", "PetscDualSpaceSetReferenceCell", DMPolytopeTypes, (PetscEnum)refCell, (PetscEnum *)&refCell, &flg));
311063ee4adSMatthew G. Knepley if (flg) {
312063ee4adSMatthew G. Knepley DM K;
313063ee4adSMatthew G. Knepley
3149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, refCell, &K));
3159566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(sp, K));
3169566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K));
317063ee4adSMatthew G. Knepley }
318063ee4adSMatthew G. Knepley
31920cf1dd8SToby Isaac /* process any options handlers added with PetscObjectAddOptionsHandler() */
320dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)sp, PetscOptionsObject));
321d0609cedSBarry Smith PetscOptionsEnd();
322063ee4adSMatthew G. Knepley sp->setfromoptionscalled = PETSC_TRUE;
3233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
32420cf1dd8SToby Isaac }
32520cf1dd8SToby Isaac
32626a11704SBarry Smith /*@C
327dce8aebaSBarry Smith PetscDualSpaceSetUp - Construct a basis for a `PetscDualSpace`
32820cf1dd8SToby Isaac
32920f4b53cSBarry Smith Collective
33020cf1dd8SToby Isaac
33120cf1dd8SToby Isaac Input Parameter:
332dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to setup
33320cf1dd8SToby Isaac
334a4ce7ad1SMatthew G. Knepley Level: intermediate
33520cf1dd8SToby Isaac
336dce8aebaSBarry Smith .seealso: `PetscDualSpaceView()`, `PetscDualSpaceDestroy()`, `PetscDualSpace`
33720cf1dd8SToby Isaac @*/
PetscDualSpaceSetUp(PetscDualSpace sp)338d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetUp(PetscDualSpace sp)
339d71ae5a4SJacob Faibussowitsch {
34020cf1dd8SToby Isaac PetscFunctionBegin;
34120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
3423ba16761SJacob Faibussowitsch if (sp->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3439566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PETSCDUALSPACE_SetUp, sp, 0, 0, 0));
34420cf1dd8SToby Isaac sp->setupcalled = PETSC_TRUE;
345dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, setup);
3469566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PETSCDUALSPACE_SetUp, sp, 0, 0, 0));
3479566063dSJacob Faibussowitsch if (sp->setfromoptionscalled) PetscCall(PetscDualSpaceViewFromOptions(sp, NULL, "-petscdualspace_view"));
3483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
34920cf1dd8SToby Isaac }
35020cf1dd8SToby Isaac
PetscDualSpaceClearDMData_Internal(PetscDualSpace sp,DM dm)351d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDualSpaceClearDMData_Internal(PetscDualSpace sp, DM dm)
352d71ae5a4SJacob Faibussowitsch {
353b4457527SToby Isaac PetscInt pStart = -1, pEnd = -1, depth = -1;
354b4457527SToby Isaac
355b4457527SToby Isaac PetscFunctionBegin;
3563ba16761SJacob Faibussowitsch if (!dm) PetscFunctionReturn(PETSC_SUCCESS);
3579566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
359b4457527SToby Isaac
360b4457527SToby Isaac if (sp->pointSpaces) {
361b4457527SToby Isaac PetscInt i;
362b4457527SToby Isaac
363f4f49eeaSPierre Jolivet for (i = 0; i < pEnd - pStart; i++) PetscCall(PetscDualSpaceDestroy(&sp->pointSpaces[i]));
364b4457527SToby Isaac }
3659566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->pointSpaces));
366b4457527SToby Isaac
367b4457527SToby Isaac if (sp->heightSpaces) {
368b4457527SToby Isaac PetscInt i;
369b4457527SToby Isaac
370f4f49eeaSPierre Jolivet for (i = 0; i <= depth; i++) PetscCall(PetscDualSpaceDestroy(&sp->heightSpaces[i]));
371b4457527SToby Isaac }
3729566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->heightSpaces));
373b4457527SToby Isaac
374f4f49eeaSPierre Jolivet PetscCall(PetscSectionDestroy(&sp->pointSection));
375f4f49eeaSPierre Jolivet PetscCall(PetscSectionDestroy(&sp->intPointSection));
376f4f49eeaSPierre Jolivet PetscCall(PetscQuadratureDestroy(&sp->intNodes));
377f4f49eeaSPierre Jolivet PetscCall(VecDestroy(&sp->intDofValues));
378f4f49eeaSPierre Jolivet PetscCall(VecDestroy(&sp->intNodeValues));
379f4f49eeaSPierre Jolivet PetscCall(MatDestroy(&sp->intMat));
380f4f49eeaSPierre Jolivet PetscCall(PetscQuadratureDestroy(&sp->allNodes));
381f4f49eeaSPierre Jolivet PetscCall(VecDestroy(&sp->allDofValues));
382f4f49eeaSPierre Jolivet PetscCall(VecDestroy(&sp->allNodeValues));
383f4f49eeaSPierre Jolivet PetscCall(MatDestroy(&sp->allMat));
3849566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->numDof));
3853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
386b4457527SToby Isaac }
387b4457527SToby Isaac
38826a11704SBarry Smith /*@C
389dce8aebaSBarry Smith PetscDualSpaceDestroy - Destroys a `PetscDualSpace` object
39020cf1dd8SToby Isaac
39120f4b53cSBarry Smith Collective
39220cf1dd8SToby Isaac
39320cf1dd8SToby Isaac Input Parameter:
394dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to destroy
39520cf1dd8SToby Isaac
396a4ce7ad1SMatthew G. Knepley Level: beginner
39720cf1dd8SToby Isaac
398dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceView()`, `PetscDualSpace()`, `PetscDualSpaceCreate()`
39920cf1dd8SToby Isaac @*/
PetscDualSpaceDestroy(PetscDualSpace * sp)400d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceDestroy(PetscDualSpace *sp)
401d71ae5a4SJacob Faibussowitsch {
40220cf1dd8SToby Isaac PetscInt dim, f;
403b4457527SToby Isaac DM dm;
40420cf1dd8SToby Isaac
40520cf1dd8SToby Isaac PetscFunctionBegin;
4063ba16761SJacob Faibussowitsch if (!*sp) PetscFunctionReturn(PETSC_SUCCESS);
407f4f49eeaSPierre Jolivet PetscValidHeaderSpecific(*sp, PETSCDUALSPACE_CLASSID, 1);
40820cf1dd8SToby Isaac
409f4f49eeaSPierre Jolivet if (--((PetscObject)*sp)->refct > 0) {
4109371c9d4SSatish Balay *sp = NULL;
4113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4129371c9d4SSatish Balay }
413f4f49eeaSPierre Jolivet ((PetscObject)*sp)->refct = 0;
41420cf1dd8SToby Isaac
4159566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(*sp, &dim));
416b4457527SToby Isaac dm = (*sp)->dm;
417b4457527SToby Isaac
418f4f49eeaSPierre Jolivet PetscTryTypeMethod(*sp, destroy);
4199566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceClearDMData_Internal(*sp, dm));
420b4457527SToby Isaac
42148a46eb9SPierre Jolivet for (f = 0; f < dim; ++f) PetscCall(PetscQuadratureDestroy(&(*sp)->functional[f]));
4229566063dSJacob Faibussowitsch PetscCall(PetscFree((*sp)->functional));
4239566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*sp)->dm));
4249566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(sp));
4253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
42620cf1dd8SToby Isaac }
42720cf1dd8SToby Isaac
42826a11704SBarry Smith /*@C
429dce8aebaSBarry Smith PetscDualSpaceCreate - Creates an empty `PetscDualSpace` object. The type can then be set with `PetscDualSpaceSetType()`.
43020cf1dd8SToby Isaac
431d083f849SBarry Smith Collective
43220cf1dd8SToby Isaac
43320cf1dd8SToby Isaac Input Parameter:
434dce8aebaSBarry Smith . comm - The communicator for the `PetscDualSpace` object
43520cf1dd8SToby Isaac
43620cf1dd8SToby Isaac Output Parameter:
437dce8aebaSBarry Smith . sp - The `PetscDualSpace` object
43820cf1dd8SToby Isaac
43920cf1dd8SToby Isaac Level: beginner
44020cf1dd8SToby Isaac
441dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetType()`, `PETSCDUALSPACELAGRANGE`
44220cf1dd8SToby Isaac @*/
PetscDualSpaceCreate(MPI_Comm comm,PetscDualSpace * sp)443d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreate(MPI_Comm comm, PetscDualSpace *sp)
444d71ae5a4SJacob Faibussowitsch {
44520cf1dd8SToby Isaac PetscDualSpace s;
44620cf1dd8SToby Isaac
44720cf1dd8SToby Isaac PetscFunctionBegin;
4484f572ea9SToby Isaac PetscAssertPointer(sp, 2);
4499566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(FECitation, &FEcite));
4509566063dSJacob Faibussowitsch PetscCall(PetscFEInitializePackage());
45120cf1dd8SToby Isaac
4529566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(s, PETSCDUALSPACE_CLASSID, "PetscDualSpace", "Dual Space", "PetscDualSpace", comm, PetscDualSpaceDestroy, PetscDualSpaceView));
45320cf1dd8SToby Isaac s->order = 0;
45420cf1dd8SToby Isaac s->Nc = 1;
4554bee2e38SMatthew G. Knepley s->k = 0;
456b4457527SToby Isaac s->spdim = -1;
457b4457527SToby Isaac s->spintdim = -1;
458b4457527SToby Isaac s->uniform = PETSC_TRUE;
45920cf1dd8SToby Isaac s->setupcalled = PETSC_FALSE;
46020cf1dd8SToby Isaac *sp = s;
4613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
46220cf1dd8SToby Isaac }
46320cf1dd8SToby Isaac
46426a11704SBarry Smith /*@C
465dce8aebaSBarry Smith PetscDualSpaceDuplicate - Creates a duplicate `PetscDualSpace` object that is not setup.
46620cf1dd8SToby Isaac
46720f4b53cSBarry Smith Collective
46820cf1dd8SToby Isaac
46920cf1dd8SToby Isaac Input Parameter:
470dce8aebaSBarry Smith . sp - The original `PetscDualSpace`
47120cf1dd8SToby Isaac
47220cf1dd8SToby Isaac Output Parameter:
473dce8aebaSBarry Smith . spNew - The duplicate `PetscDualSpace`
47420cf1dd8SToby Isaac
47520cf1dd8SToby Isaac Level: beginner
47620cf1dd8SToby Isaac
477dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`, `PetscDualSpaceSetType()`
47820cf1dd8SToby Isaac @*/
PetscDualSpaceDuplicate(PetscDualSpace sp,PetscDualSpace * spNew)479d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceDuplicate(PetscDualSpace sp, PetscDualSpace *spNew)
480d71ae5a4SJacob Faibussowitsch {
481b4457527SToby Isaac DM dm;
482b4457527SToby Isaac PetscDualSpaceType type;
483b4457527SToby Isaac const char *name;
48420cf1dd8SToby Isaac
48520cf1dd8SToby Isaac PetscFunctionBegin;
48620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
4874f572ea9SToby Isaac PetscAssertPointer(spNew, 2);
4889566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(PetscObjectComm((PetscObject)sp), spNew));
4892dce792eSToby Isaac name = ((PetscObject)sp)->name;
4903a7d0413SPierre Jolivet if (name) PetscCall(PetscObjectSetName((PetscObject)*spNew, name));
4919566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetType(sp, &type));
4929566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(*spNew, type));
4939566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm));
4949566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(*spNew, dm));
495b4457527SToby Isaac
496b4457527SToby Isaac (*spNew)->order = sp->order;
497b4457527SToby Isaac (*spNew)->k = sp->k;
498b4457527SToby Isaac (*spNew)->Nc = sp->Nc;
499b4457527SToby Isaac (*spNew)->uniform = sp->uniform;
500dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, duplicate, *spNew);
5013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
50220cf1dd8SToby Isaac }
50320cf1dd8SToby Isaac
50426a11704SBarry Smith /*@C
505dce8aebaSBarry Smith PetscDualSpaceGetDM - Get the `DM` representing the reference cell of a `PetscDualSpace`
50620cf1dd8SToby Isaac
50720f4b53cSBarry Smith Not Collective
50820cf1dd8SToby Isaac
50920cf1dd8SToby Isaac Input Parameter:
510dce8aebaSBarry Smith . sp - The `PetscDualSpace`
51120cf1dd8SToby Isaac
51220cf1dd8SToby Isaac Output Parameter:
513dce8aebaSBarry Smith . dm - The reference cell, that is a `DM` that consists of a single cell
51420cf1dd8SToby Isaac
51520cf1dd8SToby Isaac Level: intermediate
51620cf1dd8SToby Isaac
517dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetDM()`, `PetscDualSpaceCreate()`
51820cf1dd8SToby Isaac @*/
PetscDualSpaceGetDM(PetscDualSpace sp,DM * dm)519d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDM(PetscDualSpace sp, DM *dm)
520d71ae5a4SJacob Faibussowitsch {
52120cf1dd8SToby Isaac PetscFunctionBegin;
52220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
5234f572ea9SToby Isaac PetscAssertPointer(dm, 2);
52420cf1dd8SToby Isaac *dm = sp->dm;
5253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
52620cf1dd8SToby Isaac }
52720cf1dd8SToby Isaac
52826a11704SBarry Smith /*@C
529dce8aebaSBarry Smith PetscDualSpaceSetDM - Get the `DM` representing the reference cell
53020cf1dd8SToby Isaac
53120f4b53cSBarry Smith Not Collective
53220cf1dd8SToby Isaac
53320cf1dd8SToby Isaac Input Parameters:
534dce8aebaSBarry Smith + sp - The `PetscDual`Space
53520cf1dd8SToby Isaac - dm - The reference cell
53620cf1dd8SToby Isaac
53720cf1dd8SToby Isaac Level: intermediate
53820cf1dd8SToby Isaac
539dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `DM`, `PetscDualSpaceGetDM()`, `PetscDualSpaceCreate()`
54020cf1dd8SToby Isaac @*/
PetscDualSpaceSetDM(PetscDualSpace sp,DM dm)541d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetDM(PetscDualSpace sp, DM dm)
542d71ae5a4SJacob Faibussowitsch {
54320cf1dd8SToby Isaac PetscFunctionBegin;
54420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
54520cf1dd8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
54628b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change DM after dualspace is set up");
5479566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm));
54848a46eb9SPierre Jolivet if (sp->dm && sp->dm != dm) PetscCall(PetscDualSpaceClearDMData_Internal(sp, sp->dm));
5499566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sp->dm));
55020cf1dd8SToby Isaac sp->dm = dm;
5513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
55220cf1dd8SToby Isaac }
55320cf1dd8SToby Isaac
55426a11704SBarry Smith /*@C
55520cf1dd8SToby Isaac PetscDualSpaceGetOrder - Get the order of the dual space
55620cf1dd8SToby Isaac
55720f4b53cSBarry Smith Not Collective
55820cf1dd8SToby Isaac
55920cf1dd8SToby Isaac Input Parameter:
560dce8aebaSBarry Smith . sp - The `PetscDualSpace`
56120cf1dd8SToby Isaac
56220cf1dd8SToby Isaac Output Parameter:
56320cf1dd8SToby Isaac . order - The order
56420cf1dd8SToby Isaac
56520cf1dd8SToby Isaac Level: intermediate
56620cf1dd8SToby Isaac
567dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetOrder()`, `PetscDualSpaceCreate()`
56820cf1dd8SToby Isaac @*/
PetscDualSpaceGetOrder(PetscDualSpace sp,PetscInt * order)569d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetOrder(PetscDualSpace sp, PetscInt *order)
570d71ae5a4SJacob Faibussowitsch {
57120cf1dd8SToby Isaac PetscFunctionBegin;
57220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
5734f572ea9SToby Isaac PetscAssertPointer(order, 2);
57420cf1dd8SToby Isaac *order = sp->order;
5753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
57620cf1dd8SToby Isaac }
57720cf1dd8SToby Isaac
57826a11704SBarry Smith /*@C
57920cf1dd8SToby Isaac PetscDualSpaceSetOrder - Set the order of the dual space
58020cf1dd8SToby Isaac
58120f4b53cSBarry Smith Not Collective
58220cf1dd8SToby Isaac
58320cf1dd8SToby Isaac Input Parameters:
584dce8aebaSBarry Smith + sp - The `PetscDualSpace`
58520cf1dd8SToby Isaac - order - The order
58620cf1dd8SToby Isaac
58720cf1dd8SToby Isaac Level: intermediate
58820cf1dd8SToby Isaac
589dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetOrder()`, `PetscDualSpaceCreate()`
59020cf1dd8SToby Isaac @*/
PetscDualSpaceSetOrder(PetscDualSpace sp,PetscInt order)591d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetOrder(PetscDualSpace sp, PetscInt order)
592d71ae5a4SJacob Faibussowitsch {
59320cf1dd8SToby Isaac PetscFunctionBegin;
59420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
59528b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change order after dualspace is set up");
59620cf1dd8SToby Isaac sp->order = order;
5973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
59820cf1dd8SToby Isaac }
59920cf1dd8SToby Isaac
60026a11704SBarry Smith /*@C
60120cf1dd8SToby Isaac PetscDualSpaceGetNumComponents - Return the number of components for this space
60220cf1dd8SToby Isaac
60320cf1dd8SToby Isaac Input Parameter:
604dce8aebaSBarry Smith . sp - The `PetscDualSpace`
60520cf1dd8SToby Isaac
60620cf1dd8SToby Isaac Output Parameter:
60720cf1dd8SToby Isaac . Nc - The number of components
60820cf1dd8SToby Isaac
60920cf1dd8SToby Isaac Level: intermediate
61020cf1dd8SToby Isaac
611dce8aebaSBarry Smith Note:
612dce8aebaSBarry Smith A vector space, for example, will have d components, where d is the spatial dimension
613dce8aebaSBarry Smith
614db781477SPatrick Sanan .seealso: `PetscDualSpaceSetNumComponents()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()`, `PetscDualSpace`
61520cf1dd8SToby Isaac @*/
PetscDualSpaceGetNumComponents(PetscDualSpace sp,PetscInt * Nc)616d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetNumComponents(PetscDualSpace sp, PetscInt *Nc)
617d71ae5a4SJacob Faibussowitsch {
61820cf1dd8SToby Isaac PetscFunctionBegin;
61920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
6204f572ea9SToby Isaac PetscAssertPointer(Nc, 2);
62120cf1dd8SToby Isaac *Nc = sp->Nc;
6223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
62320cf1dd8SToby Isaac }
62420cf1dd8SToby Isaac
62526a11704SBarry Smith /*@C
62620cf1dd8SToby Isaac PetscDualSpaceSetNumComponents - Set the number of components for this space
62720cf1dd8SToby Isaac
62820cf1dd8SToby Isaac Input Parameters:
629dce8aebaSBarry Smith + sp - The `PetscDualSpace`
63060225df5SJacob Faibussowitsch - Nc - The number of components
63120cf1dd8SToby Isaac
63220cf1dd8SToby Isaac Level: intermediate
63320cf1dd8SToby Isaac
634db781477SPatrick Sanan .seealso: `PetscDualSpaceGetNumComponents()`, `PetscDualSpaceCreate()`, `PetscDualSpace`
63520cf1dd8SToby Isaac @*/
PetscDualSpaceSetNumComponents(PetscDualSpace sp,PetscInt Nc)636d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetNumComponents(PetscDualSpace sp, PetscInt Nc)
637d71ae5a4SJacob Faibussowitsch {
63820cf1dd8SToby Isaac PetscFunctionBegin;
63920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
64028b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up");
64120cf1dd8SToby Isaac sp->Nc = Nc;
6423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
64320cf1dd8SToby Isaac }
64420cf1dd8SToby Isaac
64526a11704SBarry Smith /*@C
64620cf1dd8SToby Isaac PetscDualSpaceGetFunctional - Get the i-th basis functional in the dual space
64720cf1dd8SToby Isaac
64820f4b53cSBarry Smith Not Collective
64920cf1dd8SToby Isaac
65020cf1dd8SToby Isaac Input Parameters:
651dce8aebaSBarry Smith + sp - The `PetscDualSpace`
65220cf1dd8SToby Isaac - i - The basis number
65320cf1dd8SToby Isaac
65420cf1dd8SToby Isaac Output Parameter:
65520cf1dd8SToby Isaac . functional - The basis functional
65620cf1dd8SToby Isaac
65720cf1dd8SToby Isaac Level: intermediate
65820cf1dd8SToby Isaac
659dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()`
66020cf1dd8SToby Isaac @*/
PetscDualSpaceGetFunctional(PetscDualSpace sp,PetscInt i,PetscQuadrature * functional)661d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetFunctional(PetscDualSpace sp, PetscInt i, PetscQuadrature *functional)
662d71ae5a4SJacob Faibussowitsch {
66320cf1dd8SToby Isaac PetscInt dim;
66420cf1dd8SToby Isaac
66520cf1dd8SToby Isaac PetscFunctionBegin;
66620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
6674f572ea9SToby Isaac PetscAssertPointer(functional, 3);
6689566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &dim));
66963a3b9bcSJacob Faibussowitsch PetscCheck(!(i < 0) && !(i >= dim), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Functional index %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", i, dim);
67020cf1dd8SToby Isaac *functional = sp->functional[i];
6713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
67220cf1dd8SToby Isaac }
67320cf1dd8SToby Isaac
67426a11704SBarry Smith /*@C
67520cf1dd8SToby Isaac PetscDualSpaceGetDimension - Get the dimension of the dual space, i.e. the number of basis functionals
67620cf1dd8SToby Isaac
67720f4b53cSBarry Smith Not Collective
67820cf1dd8SToby Isaac
67920cf1dd8SToby Isaac Input Parameter:
680dce8aebaSBarry Smith . sp - The `PetscDualSpace`
68120cf1dd8SToby Isaac
68220cf1dd8SToby Isaac Output Parameter:
68320cf1dd8SToby Isaac . dim - The dimension
68420cf1dd8SToby Isaac
68520cf1dd8SToby Isaac Level: intermediate
68620cf1dd8SToby Isaac
687dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()`
68820cf1dd8SToby Isaac @*/
PetscDualSpaceGetDimension(PetscDualSpace sp,PetscInt * dim)689d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDimension(PetscDualSpace sp, PetscInt *dim)
690d71ae5a4SJacob Faibussowitsch {
69120cf1dd8SToby Isaac PetscFunctionBegin;
69220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
6934f572ea9SToby Isaac PetscAssertPointer(dim, 2);
694b4457527SToby Isaac if (sp->spdim < 0) {
695b4457527SToby Isaac PetscSection section;
696b4457527SToby Isaac
6979566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion));
698ac530a7eSPierre Jolivet if (section) PetscCall(PetscSectionGetStorageSize(section, &sp->spdim));
699ac530a7eSPierre Jolivet else sp->spdim = 0;
700b4457527SToby Isaac }
701b4457527SToby Isaac *dim = sp->spdim;
7023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
70320cf1dd8SToby Isaac }
70420cf1dd8SToby Isaac
70526a11704SBarry Smith /*@C
706b4457527SToby Isaac PetscDualSpaceGetInteriorDimension - Get the interior dimension of the dual space, i.e. the number of basis functionals assigned to the interior of the reference domain
707b4457527SToby Isaac
70820f4b53cSBarry Smith Not Collective
709b4457527SToby Isaac
710b4457527SToby Isaac Input Parameter:
711dce8aebaSBarry Smith . sp - The `PetscDualSpace`
712b4457527SToby Isaac
713b4457527SToby Isaac Output Parameter:
71460225df5SJacob Faibussowitsch . intdim - The dimension
715b4457527SToby Isaac
716b4457527SToby Isaac Level: intermediate
717b4457527SToby Isaac
718dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()`
719b4457527SToby Isaac @*/
PetscDualSpaceGetInteriorDimension(PetscDualSpace sp,PetscInt * intdim)720d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetInteriorDimension(PetscDualSpace sp, PetscInt *intdim)
721d71ae5a4SJacob Faibussowitsch {
722b4457527SToby Isaac PetscFunctionBegin;
723b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
7244f572ea9SToby Isaac PetscAssertPointer(intdim, 2);
725b4457527SToby Isaac if (sp->spintdim < 0) {
726b4457527SToby Isaac PetscSection section;
727b4457527SToby Isaac
7289566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion));
729ac530a7eSPierre Jolivet if (section) PetscCall(PetscSectionGetConstrainedStorageSize(section, &sp->spintdim));
730ac530a7eSPierre Jolivet else sp->spintdim = 0;
731b4457527SToby Isaac }
732b4457527SToby Isaac *intdim = sp->spintdim;
7333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
734b4457527SToby Isaac }
735b4457527SToby Isaac
73626a11704SBarry Smith /*@C
737b4457527SToby Isaac PetscDualSpaceGetUniform - Whether this dual space is uniform
738b4457527SToby Isaac
73920f4b53cSBarry Smith Not Collective
740b4457527SToby Isaac
7412fe279fdSBarry Smith Input Parameter:
742b4457527SToby Isaac . sp - A dual space
743b4457527SToby Isaac
7442fe279fdSBarry Smith Output Parameter:
745dce8aebaSBarry Smith . uniform - `PETSC_TRUE` if (a) the dual space is the same for each point in a stratum of the reference `DMPLEX`, and
746dce8aebaSBarry Smith (b) every symmetry of each point in the reference `DMPLEX` is also a symmetry of the point's dual space.
747b4457527SToby Isaac
748b4457527SToby Isaac Level: advanced
749b4457527SToby Isaac
750dce8aebaSBarry Smith Note:
751dce8aebaSBarry Smith All of the usual spaces on simplex or tensor-product elements will be uniform, only reference cells
752b4457527SToby Isaac with non-uniform strata (like trianguar-prisms) or anisotropic hp dual spaces will not be uniform.
753b4457527SToby Isaac
754dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetPointSubspace()`, `PetscDualSpaceGetSymmetries()`
755b4457527SToby Isaac @*/
PetscDualSpaceGetUniform(PetscDualSpace sp,PetscBool * uniform)756d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetUniform(PetscDualSpace sp, PetscBool *uniform)
757d71ae5a4SJacob Faibussowitsch {
758b4457527SToby Isaac PetscFunctionBegin;
759b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
7604f572ea9SToby Isaac PetscAssertPointer(uniform, 2);
761b4457527SToby Isaac *uniform = sp->uniform;
7623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
763b4457527SToby Isaac }
764b4457527SToby Isaac
76526a11704SBarry Smith /*@CC
76620cf1dd8SToby Isaac PetscDualSpaceGetNumDof - Get the number of degrees of freedom for each spatial (topological) dimension
76720cf1dd8SToby Isaac
76820f4b53cSBarry Smith Not Collective
76920cf1dd8SToby Isaac
77020cf1dd8SToby Isaac Input Parameter:
771dce8aebaSBarry Smith . sp - The `PetscDualSpace`
77220cf1dd8SToby Isaac
77320cf1dd8SToby Isaac Output Parameter:
77420cf1dd8SToby Isaac . numDof - An array of length dim+1 which holds the number of dofs for each dimension
77520cf1dd8SToby Isaac
77620cf1dd8SToby Isaac Level: intermediate
77720cf1dd8SToby Isaac
778f13dfd9eSBarry Smith Note:
779f13dfd9eSBarry Smith Do not free `numDof`
780f13dfd9eSBarry Smith
781dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()`
78220cf1dd8SToby Isaac @*/
PetscDualSpaceGetNumDof(PetscDualSpace sp,const PetscInt * numDof[])783f13dfd9eSBarry Smith PetscErrorCode PetscDualSpaceGetNumDof(PetscDualSpace sp, const PetscInt *numDof[])
784d71ae5a4SJacob Faibussowitsch {
78520cf1dd8SToby Isaac PetscFunctionBegin;
78620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
7874f572ea9SToby Isaac PetscAssertPointer(numDof, 2);
78828b400f6SJacob Faibussowitsch PetscCheck(sp->uniform, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "A non-uniform space does not have a fixed number of dofs for each height");
789b4457527SToby Isaac if (!sp->numDof) {
790b4457527SToby Isaac DM dm;
791b4457527SToby Isaac PetscInt depth, d;
792b4457527SToby Isaac PetscSection section;
793b4457527SToby Isaac
7949566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm));
7959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
796f4f49eeaSPierre Jolivet PetscCall(PetscCalloc1(depth + 1, &sp->numDof));
7979566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion));
798b4457527SToby Isaac for (d = 0; d <= depth; d++) {
799b4457527SToby Isaac PetscInt dStart, dEnd;
800b4457527SToby Isaac
8019566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd));
802b4457527SToby Isaac if (dEnd <= dStart) continue;
803f4f49eeaSPierre Jolivet PetscCall(PetscSectionGetDof(section, dStart, &sp->numDof[d]));
804b4457527SToby Isaac }
805b4457527SToby Isaac }
806b4457527SToby Isaac *numDof = sp->numDof;
80708401ef6SPierre Jolivet PetscCheck(*numDof, PetscObjectComm((PetscObject)sp), PETSC_ERR_LIB, "Empty numDof[] returned from dual space implementation");
8083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
80920cf1dd8SToby Isaac }
81020cf1dd8SToby Isaac
811b4457527SToby Isaac /* create the section of the right size and set a permutation for topological ordering */
PetscDualSpaceSectionCreate_Internal(PetscDualSpace sp,PetscSection * topSection)812d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSectionCreate_Internal(PetscDualSpace sp, PetscSection *topSection)
813d71ae5a4SJacob Faibussowitsch {
814b4457527SToby Isaac DM dm;
815b4457527SToby Isaac PetscInt pStart, pEnd, cStart, cEnd, c, depth, count, i;
816b4457527SToby Isaac PetscInt *seen, *perm;
817b4457527SToby Isaac PetscSection section;
818b4457527SToby Isaac
819b4457527SToby Isaac PetscFunctionBegin;
820b4457527SToby Isaac dm = sp->dm;
8219566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion));
8229566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd));
8249566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &seen));
8259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &perm));
8269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
8279566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
828b4457527SToby Isaac for (c = cStart, count = 0; c < cEnd; c++) {
829b4457527SToby Isaac PetscInt closureSize = -1, e;
830b4457527SToby Isaac PetscInt *closure = NULL;
831b4457527SToby Isaac
832b4457527SToby Isaac perm[count++] = c;
833b4457527SToby Isaac seen[c - pStart] = 1;
8349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
835b4457527SToby Isaac for (e = 0; e < closureSize; e++) {
836b4457527SToby Isaac PetscInt point = closure[2 * e];
837b4457527SToby Isaac
838b4457527SToby Isaac if (seen[point - pStart]) continue;
839b4457527SToby Isaac perm[count++] = point;
840b4457527SToby Isaac seen[point - pStart] = 1;
841b4457527SToby Isaac }
8429566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
843b4457527SToby Isaac }
8441dca8a05SBarry Smith PetscCheck(count == pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad topological ordering");
8459371c9d4SSatish Balay for (i = 0; i < pEnd - pStart; i++)
8469371c9d4SSatish Balay if (perm[i] != i) break;
847b4457527SToby Isaac if (i < pEnd - pStart) {
848b4457527SToby Isaac IS permIS;
849b4457527SToby Isaac
8509566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pEnd - pStart, perm, PETSC_OWN_POINTER, &permIS));
8519566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(permIS));
8529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(section, permIS));
8539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS));
854b4457527SToby Isaac } else {
8559566063dSJacob Faibussowitsch PetscCall(PetscFree(perm));
856b4457527SToby Isaac }
8579566063dSJacob Faibussowitsch PetscCall(PetscFree(seen));
858b4457527SToby Isaac *topSection = section;
8593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
860b4457527SToby Isaac }
861b4457527SToby Isaac
862b4457527SToby Isaac /* mark boundary points and set up */
PetscDualSpaceSectionSetUp_Internal(PetscDualSpace sp,PetscSection section)863d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSectionSetUp_Internal(PetscDualSpace sp, PetscSection section)
864d71ae5a4SJacob Faibussowitsch {
865b4457527SToby Isaac DM dm;
866b4457527SToby Isaac DMLabel boundary;
867b4457527SToby Isaac PetscInt pStart, pEnd, p;
868b4457527SToby Isaac
869b4457527SToby Isaac PetscFunctionBegin;
870b4457527SToby Isaac dm = sp->dm;
8719566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "boundary", &boundary));
8729566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm));
8739566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, 1, boundary));
8749566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, boundary));
8759566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
876b4457527SToby Isaac for (p = pStart; p < pEnd; p++) {
877b4457527SToby Isaac PetscInt bval;
878b4457527SToby Isaac
8799566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(boundary, p, &bval));
880b4457527SToby Isaac if (bval == 1) {
881b4457527SToby Isaac PetscInt dof;
882b4457527SToby Isaac
8839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof));
8849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetConstraintDof(section, p, dof));
885b4457527SToby Isaac }
886b4457527SToby Isaac }
8879566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&boundary));
8889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section));
8893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
890b4457527SToby Isaac }
891b4457527SToby Isaac
89226a11704SBarry Smith /*@C
893dce8aebaSBarry Smith PetscDualSpaceGetSection - Create a `PetscSection` over the reference cell with the layout from this space
894a4ce7ad1SMatthew G. Knepley
89520f4b53cSBarry Smith Collective
896a4ce7ad1SMatthew G. Knepley
8972fe279fdSBarry Smith Input Parameter:
898dce8aebaSBarry Smith . sp - The `PetscDualSpace`
899a4ce7ad1SMatthew G. Knepley
900a4ce7ad1SMatthew G. Knepley Output Parameter:
901a4ce7ad1SMatthew G. Knepley . section - The section
902a4ce7ad1SMatthew G. Knepley
903a4ce7ad1SMatthew G. Knepley Level: advanced
904a4ce7ad1SMatthew G. Knepley
905dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscSection`, `PetscDualSpaceCreate()`, `DMPLEX`
906a4ce7ad1SMatthew G. Knepley @*/
PetscDualSpaceGetSection(PetscDualSpace sp,PetscSection * section)907d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetSection(PetscDualSpace sp, PetscSection *section)
908d71ae5a4SJacob Faibussowitsch {
909b4457527SToby Isaac PetscInt pStart, pEnd, p;
910b4457527SToby Isaac
911b4457527SToby Isaac PetscFunctionBegin;
91278f1d139SRomain Beucher if (!sp->dm) {
91378f1d139SRomain Beucher *section = NULL;
9143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
91578f1d139SRomain Beucher }
916b4457527SToby Isaac if (!sp->pointSection) {
917b4457527SToby Isaac /* mark the boundary */
918f4f49eeaSPierre Jolivet PetscCall(PetscDualSpaceSectionCreate_Internal(sp, &sp->pointSection));
9199566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(sp->dm, &pStart, &pEnd));
920b4457527SToby Isaac for (p = pStart; p < pEnd; p++) {
921b4457527SToby Isaac PetscDualSpace psp;
922b4457527SToby Isaac
9239566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, p, &psp));
924b4457527SToby Isaac if (psp) {
925b4457527SToby Isaac PetscInt dof;
926b4457527SToby Isaac
9279566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorDimension(psp, &dof));
9289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sp->pointSection, p, dof));
929b4457527SToby Isaac }
930b4457527SToby Isaac }
9319566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionSetUp_Internal(sp, sp->pointSection));
932b4457527SToby Isaac }
933b4457527SToby Isaac *section = sp->pointSection;
9343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
935b4457527SToby Isaac }
936b4457527SToby Isaac
93726a11704SBarry Smith /*@C
9382dce792eSToby Isaac PetscDualSpaceGetInteriorSection - Create a `PetscSection` over the reference cell with the layout from this space
9392dce792eSToby Isaac for interior degrees of freedom
9402dce792eSToby Isaac
9412dce792eSToby Isaac Collective
9422dce792eSToby Isaac
9432dce792eSToby Isaac Input Parameter:
9442dce792eSToby Isaac . sp - The `PetscDualSpace`
9452dce792eSToby Isaac
9462dce792eSToby Isaac Output Parameter:
9472dce792eSToby Isaac . section - The interior section
9482dce792eSToby Isaac
9492dce792eSToby Isaac Level: advanced
9502dce792eSToby Isaac
9512dce792eSToby Isaac Note:
9522dce792eSToby Isaac Most reference domains have one cell, in which case the only cell will have
9532dce792eSToby Isaac all of the interior degrees of freedom in the interior section. But
9542dce792eSToby Isaac for `PETSCDUALSPACEREFINED` there may be other mesh points in the interior,
9552dce792eSToby Isaac and this section describes their layout.
9562dce792eSToby Isaac
9572dce792eSToby Isaac .seealso: `PetscDualSpace`, `PetscSection`, `PetscDualSpaceCreate()`, `DMPLEX`
9582dce792eSToby Isaac @*/
PetscDualSpaceGetInteriorSection(PetscDualSpace sp,PetscSection * section)9592dce792eSToby Isaac PetscErrorCode PetscDualSpaceGetInteriorSection(PetscDualSpace sp, PetscSection *section)
9602dce792eSToby Isaac {
9612dce792eSToby Isaac PetscInt pStart, pEnd, p;
9622dce792eSToby Isaac
9632dce792eSToby Isaac PetscFunctionBegin;
9642dce792eSToby Isaac if (!sp->dm) {
9652dce792eSToby Isaac *section = NULL;
9662dce792eSToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
9672dce792eSToby Isaac }
9682dce792eSToby Isaac if (!sp->intPointSection) {
9692dce792eSToby Isaac PetscSection full_section;
9702dce792eSToby Isaac
9712dce792eSToby Isaac PetscCall(PetscDualSpaceGetSection(sp, &full_section));
972f4f49eeaSPierre Jolivet PetscCall(PetscDualSpaceSectionCreate_Internal(sp, &sp->intPointSection));
9732dce792eSToby Isaac PetscCall(PetscSectionGetChart(full_section, &pStart, &pEnd));
9742dce792eSToby Isaac for (p = pStart; p < pEnd; p++) {
9752dce792eSToby Isaac PetscInt dof, cdof;
9762dce792eSToby Isaac
9772dce792eSToby Isaac PetscCall(PetscSectionGetDof(full_section, p, &dof));
9782dce792eSToby Isaac PetscCall(PetscSectionGetConstraintDof(full_section, p, &cdof));
9792dce792eSToby Isaac PetscCall(PetscSectionSetDof(sp->intPointSection, p, dof - cdof));
9802dce792eSToby Isaac }
9812dce792eSToby Isaac PetscCall(PetscDualSpaceSectionSetUp_Internal(sp, sp->intPointSection));
9822dce792eSToby Isaac }
9832dce792eSToby Isaac *section = sp->intPointSection;
9842dce792eSToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
9852dce792eSToby Isaac }
9862dce792eSToby Isaac
987b4457527SToby Isaac /* this assumes that all of the point dual spaces store their interior dofs first, which is true when the point DMs
988b4457527SToby Isaac * have one cell */
PetscDualSpacePushForwardSubspaces_Internal(PetscDualSpace sp,PetscInt sStart,PetscInt sEnd)989d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushForwardSubspaces_Internal(PetscDualSpace sp, PetscInt sStart, PetscInt sEnd)
990d71ae5a4SJacob Faibussowitsch {
991b4457527SToby Isaac PetscReal *sv0, *v0, *J;
992b4457527SToby Isaac PetscSection section;
993b4457527SToby Isaac PetscInt dim, s, k;
99420cf1dd8SToby Isaac DM dm;
99520cf1dd8SToby Isaac
99620cf1dd8SToby Isaac PetscFunctionBegin;
9979566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm));
9989566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
9999566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion));
10009566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim, &sv0, dim * dim, &J));
10019566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFormDegree(sp, &k));
1002b4457527SToby Isaac for (s = sStart; s < sEnd; s++) {
1003b4457527SToby Isaac PetscReal detJ, hdetJ;
1004b4457527SToby Isaac PetscDualSpace ssp;
1005b4457527SToby Isaac PetscInt dof, off, f, sdim;
1006b4457527SToby Isaac PetscInt i, j;
1007b4457527SToby Isaac DM sdm;
100820cf1dd8SToby Isaac
10099566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, s, &ssp));
1010b4457527SToby Isaac if (!ssp) continue;
10119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, s, &dof));
10129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, s, &off));
1013b4457527SToby Isaac /* get the first vertex of the reference cell */
10149566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(ssp, &sdm));
10159566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sdm, &sdim));
10169566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(sdm, 0, sv0, NULL, NULL, &hdetJ));
10179566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, s, v0, J, NULL, &detJ));
1018b4457527SToby Isaac /* compactify Jacobian */
10199371c9d4SSatish Balay for (i = 0; i < dim; i++)
10209371c9d4SSatish Balay for (j = 0; j < sdim; j++) J[i * sdim + j] = J[i * dim + j];
1021b4457527SToby Isaac for (f = 0; f < dof; f++) {
1022b4457527SToby Isaac PetscQuadrature fn;
102320cf1dd8SToby Isaac
10249566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(ssp, f, &fn));
1025f4f49eeaSPierre Jolivet PetscCall(PetscQuadraturePushForward(fn, dim, sv0, v0, J, k, &sp->functional[off + f]));
102620cf1dd8SToby Isaac }
102720cf1dd8SToby Isaac }
10289566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, sv0, J));
10293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
103020cf1dd8SToby Isaac }
103120cf1dd8SToby Isaac
103220cf1dd8SToby Isaac /*@C
103320cf1dd8SToby Isaac PetscDualSpaceApply - Apply a functional from the dual space basis to an input function
103420cf1dd8SToby Isaac
103520cf1dd8SToby Isaac Input Parameters:
1036dce8aebaSBarry Smith + sp - The `PetscDualSpace` object
103720cf1dd8SToby Isaac . f - The basis functional index
103820cf1dd8SToby Isaac . time - The time
103920cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian) (or evaluated at the coordinates of the functional)
104020cf1dd8SToby Isaac . numComp - The number of components for the function
104120cf1dd8SToby Isaac . func - The input function
104220cf1dd8SToby Isaac - ctx - A context for the function
104320cf1dd8SToby Isaac
104420cf1dd8SToby Isaac Output Parameter:
104520cf1dd8SToby Isaac . value - numComp output values
104620cf1dd8SToby Isaac
104760225df5SJacob Faibussowitsch Calling sequence:
1048dce8aebaSBarry Smith .vb
1049*2a8381b2SBarry Smith PetscErrorCode func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt numComponents, PetscScalar values[], PetscCtx ctx)
1050dce8aebaSBarry Smith .ve
105120cf1dd8SToby Isaac
1052a4ce7ad1SMatthew G. Knepley Level: beginner
105320cf1dd8SToby Isaac
1054dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`
105520cf1dd8SToby Isaac @*/
PetscDualSpaceApply(PetscDualSpace sp,PetscInt f,PetscReal time,PetscFEGeom * cgeom,PetscInt numComp,PetscErrorCode (* func)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),PetscCtx ctx,PetscScalar * value)1056*2a8381b2SBarry Smith PetscErrorCode PetscDualSpaceApply(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFEGeom *cgeom, PetscInt numComp, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), PetscCtx ctx, PetscScalar *value)
1057d71ae5a4SJacob Faibussowitsch {
105820cf1dd8SToby Isaac PetscFunctionBegin;
105920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
10604f572ea9SToby Isaac PetscAssertPointer(cgeom, 4);
10614f572ea9SToby Isaac PetscAssertPointer(value, 8);
1062dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, apply, f, time, cgeom, numComp, func, ctx, value);
10633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
106420cf1dd8SToby Isaac }
106520cf1dd8SToby Isaac
106626a11704SBarry Smith /*@C
1067dce8aebaSBarry Smith PetscDualSpaceApplyAll - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetAllData()`
106820cf1dd8SToby Isaac
106920cf1dd8SToby Isaac Input Parameters:
1070dce8aebaSBarry Smith + sp - The `PetscDualSpace` object
1071dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetAllData()`
107220cf1dd8SToby Isaac
107320cf1dd8SToby Isaac Output Parameter:
107420cf1dd8SToby Isaac . spValue - The values of all dual space functionals
107520cf1dd8SToby Isaac
1076dce8aebaSBarry Smith Level: advanced
107720cf1dd8SToby Isaac
1078dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`
107920cf1dd8SToby Isaac @*/
PetscDualSpaceApplyAll(PetscDualSpace sp,const PetscScalar * pointEval,PetscScalar * spValue)1080d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyAll(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue)
1081d71ae5a4SJacob Faibussowitsch {
108220cf1dd8SToby Isaac PetscFunctionBegin;
108320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
1084dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyall, pointEval, spValue);
10853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
108620cf1dd8SToby Isaac }
108720cf1dd8SToby Isaac
108826a11704SBarry Smith /*@C
1089dce8aebaSBarry Smith PetscDualSpaceApplyInterior - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetInteriorData()`
1090b4457527SToby Isaac
1091b4457527SToby Isaac Input Parameters:
1092dce8aebaSBarry Smith + sp - The `PetscDualSpace` object
1093dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetInteriorData()`
1094b4457527SToby Isaac
1095b4457527SToby Isaac Output Parameter:
1096b4457527SToby Isaac . spValue - The values of interior dual space functionals
1097b4457527SToby Isaac
1098dce8aebaSBarry Smith Level: advanced
1099b4457527SToby Isaac
1100dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`
1101b4457527SToby Isaac @*/
PetscDualSpaceApplyInterior(PetscDualSpace sp,const PetscScalar * pointEval,PetscScalar * spValue)1102d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyInterior(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue)
1103d71ae5a4SJacob Faibussowitsch {
1104b4457527SToby Isaac PetscFunctionBegin;
1105b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
1106dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyint, pointEval, spValue);
11073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1108b4457527SToby Isaac }
1109b4457527SToby Isaac
1110b4457527SToby Isaac /*@C
111120cf1dd8SToby Isaac PetscDualSpaceApplyDefault - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional.
111220cf1dd8SToby Isaac
111320cf1dd8SToby Isaac Input Parameters:
1114dce8aebaSBarry Smith + sp - The `PetscDualSpace` object
111520cf1dd8SToby Isaac . f - The basis functional index
111620cf1dd8SToby Isaac . time - The time
111720cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian)
111820cf1dd8SToby Isaac . Nc - The number of components for the function
111920cf1dd8SToby Isaac . func - The input function
112020cf1dd8SToby Isaac - ctx - A context for the function
112120cf1dd8SToby Isaac
112220cf1dd8SToby Isaac Output Parameter:
112320cf1dd8SToby Isaac . value - The output value
112420cf1dd8SToby Isaac
112560225df5SJacob Faibussowitsch Calling sequence:
1126dce8aebaSBarry Smith .vb
1127*2a8381b2SBarry Smith PetscErrorCode func(PetscInt dim, PetscReal time, const PetscReal x[],PetscInt numComponents, PetscScalar values[], PetscCtx ctx)
1128dce8aebaSBarry Smith .ve
112920cf1dd8SToby Isaac
1130dce8aebaSBarry Smith Level: advanced
113120cf1dd8SToby Isaac
1132dce8aebaSBarry Smith Note:
1133dce8aebaSBarry Smith The idea is to evaluate the functional as an integral $ n(f) = \int dx n(x) . f(x) $ where both n and f have Nc components.
113420cf1dd8SToby Isaac
1135dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`
113620cf1dd8SToby Isaac @*/
PetscDualSpaceApplyDefault(PetscDualSpace sp,PetscInt f,PetscReal time,PetscFEGeom * cgeom,PetscInt Nc,PetscErrorCode (* func)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),PetscCtx ctx,PetscScalar * value)1137*2a8381b2SBarry Smith PetscErrorCode PetscDualSpaceApplyDefault(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFEGeom *cgeom, PetscInt Nc, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), PetscCtx ctx, PetscScalar *value)
1138d71ae5a4SJacob Faibussowitsch {
113920cf1dd8SToby Isaac DM dm;
114020cf1dd8SToby Isaac PetscQuadrature n;
114120cf1dd8SToby Isaac const PetscReal *points, *weights;
114220cf1dd8SToby Isaac PetscReal x[3];
114320cf1dd8SToby Isaac PetscScalar *val;
114420cf1dd8SToby Isaac PetscInt dim, dE, qNc, c, Nq, q;
114520cf1dd8SToby Isaac PetscBool isAffine;
114620cf1dd8SToby Isaac
114720cf1dd8SToby Isaac PetscFunctionBegin;
114820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
11494f572ea9SToby Isaac PetscAssertPointer(value, 8);
11509566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm));
11519566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n));
11529566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, &dim, &qNc, &Nq, &points, &weights));
115363a3b9bcSJacob Faibussowitsch PetscCheck(dim == cgeom->dim, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature spatial dimension %" PetscInt_FMT " != cell geometry dimension %" PetscInt_FMT, dim, cgeom->dim);
115463a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc);
11559566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val));
115620cf1dd8SToby Isaac *value = 0.0;
115720cf1dd8SToby Isaac isAffine = cgeom->isAffine;
115820cf1dd8SToby Isaac dE = cgeom->dimEmbed;
115920cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) {
116020cf1dd8SToby Isaac if (isAffine) {
116120cf1dd8SToby Isaac CoordinatesRefToReal(dE, cgeom->dim, cgeom->xi, cgeom->v, cgeom->J, &points[q * dim], x);
11629566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, x, Nc, val, ctx));
116320cf1dd8SToby Isaac } else {
11649566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, &cgeom->v[dE * q], Nc, val, ctx));
116520cf1dd8SToby Isaac }
1166ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) *value += val[c] * weights[q * Nc + c];
116720cf1dd8SToby Isaac }
11689566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val));
11693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
117020cf1dd8SToby Isaac }
117120cf1dd8SToby Isaac
117226a11704SBarry Smith /*@C
1173dce8aebaSBarry Smith PetscDualSpaceApplyAllDefault - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetAllData()`
117420cf1dd8SToby Isaac
117520cf1dd8SToby Isaac Input Parameters:
1176dce8aebaSBarry Smith + sp - The `PetscDualSpace` object
1177dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetAllData()`
117820cf1dd8SToby Isaac
117920cf1dd8SToby Isaac Output Parameter:
118020cf1dd8SToby Isaac . spValue - The values of all dual space functionals
118120cf1dd8SToby Isaac
1182dce8aebaSBarry Smith Level: advanced
118320cf1dd8SToby Isaac
1184dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`
118520cf1dd8SToby Isaac @*/
PetscDualSpaceApplyAllDefault(PetscDualSpace sp,const PetscScalar * pointEval,PetscScalar * spValue)1186d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyAllDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue)
1187d71ae5a4SJacob Faibussowitsch {
1188b4457527SToby Isaac Vec pointValues, dofValues;
1189b4457527SToby Isaac Mat allMat;
119020cf1dd8SToby Isaac
119120cf1dd8SToby Isaac PetscFunctionBegin;
119220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
11934f572ea9SToby Isaac PetscAssertPointer(pointEval, 2);
11944f572ea9SToby Isaac PetscAssertPointer(spValue, 3);
11959566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetAllData(sp, NULL, &allMat));
1196f4f49eeaSPierre Jolivet if (!sp->allNodeValues) PetscCall(MatCreateVecs(allMat, &sp->allNodeValues, NULL));
1197b4457527SToby Isaac pointValues = sp->allNodeValues;
1198f4f49eeaSPierre Jolivet if (!sp->allDofValues) PetscCall(MatCreateVecs(allMat, NULL, &sp->allDofValues));
1199b4457527SToby Isaac dofValues = sp->allDofValues;
12009566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval));
12019566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue));
12029566063dSJacob Faibussowitsch PetscCall(MatMult(allMat, pointValues, dofValues));
12039566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues));
12049566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues));
12053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
120620cf1dd8SToby Isaac }
1207b4457527SToby Isaac
120826a11704SBarry Smith /*@C
1209dce8aebaSBarry Smith PetscDualSpaceApplyInteriorDefault - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetInteriorData()`
1210b4457527SToby Isaac
1211b4457527SToby Isaac Input Parameters:
1212dce8aebaSBarry Smith + sp - The `PetscDualSpace` object
1213dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetInteriorData()`
1214b4457527SToby Isaac
1215b4457527SToby Isaac Output Parameter:
1216b4457527SToby Isaac . spValue - The values of interior dual space functionals
1217b4457527SToby Isaac
1218dce8aebaSBarry Smith Level: advanced
1219b4457527SToby Isaac
1220dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`
1221b4457527SToby Isaac @*/
PetscDualSpaceApplyInteriorDefault(PetscDualSpace sp,const PetscScalar * pointEval,PetscScalar * spValue)1222d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyInteriorDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue)
1223d71ae5a4SJacob Faibussowitsch {
1224b4457527SToby Isaac Vec pointValues, dofValues;
1225b4457527SToby Isaac Mat intMat;
1226b4457527SToby Isaac
1227b4457527SToby Isaac PetscFunctionBegin;
1228b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
12294f572ea9SToby Isaac PetscAssertPointer(pointEval, 2);
12304f572ea9SToby Isaac PetscAssertPointer(spValue, 3);
12319566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(sp, NULL, &intMat));
1232f4f49eeaSPierre Jolivet if (!sp->intNodeValues) PetscCall(MatCreateVecs(intMat, &sp->intNodeValues, NULL));
1233b4457527SToby Isaac pointValues = sp->intNodeValues;
1234f4f49eeaSPierre Jolivet if (!sp->intDofValues) PetscCall(MatCreateVecs(intMat, NULL, &sp->intDofValues));
1235b4457527SToby Isaac dofValues = sp->intDofValues;
12369566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval));
12379566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue));
12389566063dSJacob Faibussowitsch PetscCall(MatMult(intMat, pointValues, dofValues));
12399566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues));
12409566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues));
12413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
124220cf1dd8SToby Isaac }
124320cf1dd8SToby Isaac
124426a11704SBarry Smith /*@C
1245b4457527SToby Isaac PetscDualSpaceGetAllData - Get all quadrature nodes from this space, and the matrix that sends quadrature node values to degree-of-freedom values
1246a4ce7ad1SMatthew G. Knepley
1247a4ce7ad1SMatthew G. Knepley Input Parameter:
1248a4ce7ad1SMatthew G. Knepley . sp - The dualspace
1249a4ce7ad1SMatthew G. Knepley
1250d8d19677SJose E. Roman Output Parameters:
125126a11704SBarry Smith + allNodes - A `PetscQuadrature` object containing all evaluation nodes, pass `NULL` if not needed
125226a11704SBarry Smith - allMat - A `Mat` for the node-to-dof transformation, pass `NULL` if not needed
1253a4ce7ad1SMatthew G. Knepley
1254a4ce7ad1SMatthew G. Knepley Level: advanced
1255a4ce7ad1SMatthew G. Knepley
1256dce8aebaSBarry Smith .seealso: `PetscQuadrature`, `PetscDualSpace`, `PetscDualSpaceCreate()`, `Mat`
1257a4ce7ad1SMatthew G. Knepley @*/
PetscDualSpaceGetAllData(PetscDualSpace sp,PeOp PetscQuadrature * allNodes,PeOp Mat * allMat)1258ce78bad3SBarry Smith PetscErrorCode PetscDualSpaceGetAllData(PetscDualSpace sp, PeOp PetscQuadrature *allNodes, PeOp Mat *allMat)
1259d71ae5a4SJacob Faibussowitsch {
126020cf1dd8SToby Isaac PetscFunctionBegin;
126120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
12624f572ea9SToby Isaac if (allNodes) PetscAssertPointer(allNodes, 2);
12634f572ea9SToby Isaac if (allMat) PetscAssertPointer(allMat, 3);
1264b4457527SToby Isaac if ((!sp->allNodes || !sp->allMat) && sp->ops->createalldata) {
1265b4457527SToby Isaac PetscQuadrature qpoints;
1266b4457527SToby Isaac Mat amat;
1267b4457527SToby Isaac
1268dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createalldata, &qpoints, &amat);
1269f4f49eeaSPierre Jolivet PetscCall(PetscQuadratureDestroy(&sp->allNodes));
1270f4f49eeaSPierre Jolivet PetscCall(MatDestroy(&sp->allMat));
1271b4457527SToby Isaac sp->allNodes = qpoints;
1272b4457527SToby Isaac sp->allMat = amat;
127320cf1dd8SToby Isaac }
1274b4457527SToby Isaac if (allNodes) *allNodes = sp->allNodes;
1275b4457527SToby Isaac if (allMat) *allMat = sp->allMat;
12763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
127720cf1dd8SToby Isaac }
127820cf1dd8SToby Isaac
127926a11704SBarry Smith /*@C
1280b4457527SToby Isaac PetscDualSpaceCreateAllDataDefault - Create all evaluation nodes and the node-to-dof matrix by examining functionals
1281a4ce7ad1SMatthew G. Knepley
1282a4ce7ad1SMatthew G. Knepley Input Parameter:
1283a4ce7ad1SMatthew G. Knepley . sp - The dualspace
1284a4ce7ad1SMatthew G. Knepley
1285d8d19677SJose E. Roman Output Parameters:
1286dce8aebaSBarry Smith + allNodes - A `PetscQuadrature` object containing all evaluation nodes
1287dce8aebaSBarry Smith - allMat - A `Mat` for the node-to-dof transformation
1288a4ce7ad1SMatthew G. Knepley
1289a4ce7ad1SMatthew G. Knepley Level: advanced
1290a4ce7ad1SMatthew G. Knepley
1291dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`, `Mat`, `PetscQuadrature`
1292a4ce7ad1SMatthew G. Knepley @*/
PetscDualSpaceCreateAllDataDefault(PetscDualSpace sp,PetscQuadrature * allNodes,Mat * allMat)1293d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreateAllDataDefault(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat)
1294d71ae5a4SJacob Faibussowitsch {
129520cf1dd8SToby Isaac PetscInt spdim;
129620cf1dd8SToby Isaac PetscInt numPoints, offset;
129720cf1dd8SToby Isaac PetscReal *points;
129820cf1dd8SToby Isaac PetscInt f, dim;
1299b4457527SToby Isaac PetscInt Nc, nrows, ncols;
1300b4457527SToby Isaac PetscInt maxNumPoints;
130120cf1dd8SToby Isaac PetscQuadrature q;
1302b4457527SToby Isaac Mat A;
130320cf1dd8SToby Isaac
130420cf1dd8SToby Isaac PetscFunctionBegin;
13059566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc));
13069566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &spdim));
130720cf1dd8SToby Isaac if (!spdim) {
13089566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes));
13099566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, 0, 0, 0, NULL, NULL));
131020cf1dd8SToby Isaac }
1311b4457527SToby Isaac nrows = spdim;
13129566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, 0, &q));
13139566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, NULL, &numPoints, NULL, NULL));
1314b4457527SToby Isaac maxNumPoints = numPoints;
131520cf1dd8SToby Isaac for (f = 1; f < spdim; f++) {
131620cf1dd8SToby Isaac PetscInt Np;
131720cf1dd8SToby Isaac
13189566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q));
13199566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL));
132020cf1dd8SToby Isaac numPoints += Np;
1321b4457527SToby Isaac maxNumPoints = PetscMax(maxNumPoints, Np);
132220cf1dd8SToby Isaac }
1323b4457527SToby Isaac ncols = numPoints * Nc;
13249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points));
13259566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, nrows, ncols, maxNumPoints * Nc, NULL, &A));
132620cf1dd8SToby Isaac for (f = 0, offset = 0; f < spdim; f++) {
1327b4457527SToby Isaac const PetscReal *p, *w;
132820cf1dd8SToby Isaac PetscInt Np, i;
1329b4457527SToby Isaac PetscInt fnc;
133020cf1dd8SToby Isaac
13319566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q));
13329566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, &fnc, &Np, &p, &w));
133308401ef6SPierre Jolivet PetscCheck(fnc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "functional component mismatch");
1334ad540459SPierre Jolivet for (i = 0; i < Np * dim; i++) points[offset * dim + i] = p[i];
133548a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(A, f, offset * Nc, w[i], INSERT_VALUES));
1336b4457527SToby Isaac offset += Np;
1337b4457527SToby Isaac }
13389566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
13399566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
13409566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes));
13419566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, dim, 0, numPoints, points, NULL));
1342b4457527SToby Isaac *allMat = A;
13433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1344b4457527SToby Isaac }
1345b4457527SToby Isaac
134626a11704SBarry Smith /*@C
1347b4457527SToby Isaac PetscDualSpaceGetInteriorData - Get all quadrature points necessary to compute the interior degrees of freedom from
1348a4e35b19SJacob Faibussowitsch this space, as well as the matrix that computes the degrees of freedom from the quadrature
1349a4e35b19SJacob Faibussowitsch values.
1350b4457527SToby Isaac
1351b4457527SToby Isaac Input Parameter:
1352b4457527SToby Isaac . sp - The dualspace
1353b4457527SToby Isaac
1354d8d19677SJose E. Roman Output Parameters:
135526a11704SBarry Smith + intNodes - A `PetscQuadrature` object containing all evaluation points needed to evaluate interior degrees of freedom,
135626a11704SBarry Smith pass `NULL` if not needed
1357b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is
1358dce8aebaSBarry Smith the size of the constrained layout (`PetscSectionGetConstrainStorageSize()`) of the dual space section,
1359dce8aebaSBarry Smith npoints is the number of points in intNodes and nc is `PetscDualSpaceGetNumComponents()`.
136026a11704SBarry Smith Pass `NULL` if not needed
1361b4457527SToby Isaac
1362b4457527SToby Isaac Level: advanced
1363b4457527SToby Isaac
1364a4e35b19SJacob Faibussowitsch Notes:
1365a4e35b19SJacob Faibussowitsch Degrees of freedom are interior degrees of freedom if they belong (by
1366a4e35b19SJacob Faibussowitsch `PetscDualSpaceGetSection()`) to interior points in the references, complementary boundary
1367a4e35b19SJacob Faibussowitsch degrees of freedom are marked as constrained in the section returned by
1368a4e35b19SJacob Faibussowitsch `PetscDualSpaceGetSection()`).
1369a4e35b19SJacob Faibussowitsch
1370dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `Mat`, `PetscDualSpaceCreate()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceGetNumComponents()`, `PetscQuadratureGetData()`
1371b4457527SToby Isaac @*/
PetscDualSpaceGetInteriorData(PetscDualSpace sp,PeOp PetscQuadrature * intNodes,PeOp Mat * intMat)1372ce78bad3SBarry Smith PetscErrorCode PetscDualSpaceGetInteriorData(PetscDualSpace sp, PeOp PetscQuadrature *intNodes, PeOp Mat *intMat)
1373d71ae5a4SJacob Faibussowitsch {
1374b4457527SToby Isaac PetscFunctionBegin;
1375b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
13764f572ea9SToby Isaac if (intNodes) PetscAssertPointer(intNodes, 2);
13774f572ea9SToby Isaac if (intMat) PetscAssertPointer(intMat, 3);
1378b4457527SToby Isaac if ((!sp->intNodes || !sp->intMat) && sp->ops->createintdata) {
1379b4457527SToby Isaac PetscQuadrature qpoints;
1380b4457527SToby Isaac Mat imat;
1381b4457527SToby Isaac
1382dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createintdata, &qpoints, &imat);
1383f4f49eeaSPierre Jolivet PetscCall(PetscQuadratureDestroy(&sp->intNodes));
1384f4f49eeaSPierre Jolivet PetscCall(MatDestroy(&sp->intMat));
1385b4457527SToby Isaac sp->intNodes = qpoints;
1386b4457527SToby Isaac sp->intMat = imat;
1387b4457527SToby Isaac }
1388b4457527SToby Isaac if (intNodes) *intNodes = sp->intNodes;
1389b4457527SToby Isaac if (intMat) *intMat = sp->intMat;
13903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1391b4457527SToby Isaac }
1392b4457527SToby Isaac
139326a11704SBarry Smith /*@C
1394b4457527SToby Isaac PetscDualSpaceCreateInteriorDataDefault - Create quadrature points by examining interior functionals and create the matrix mapping quadrature point values to interior dual space values
1395b4457527SToby Isaac
1396b4457527SToby Isaac Input Parameter:
1397b4457527SToby Isaac . sp - The dualspace
1398b4457527SToby Isaac
1399d8d19677SJose E. Roman Output Parameters:
1400dce8aebaSBarry Smith + intNodes - A `PetscQuadrature` object containing all evaluation points needed to evaluate interior degrees of freedom
1401b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is
1402dce8aebaSBarry Smith the size of the constrained layout (`PetscSectionGetConstrainStorageSize()`) of the dual space section,
1403dce8aebaSBarry Smith npoints is the number of points in allNodes and nc is `PetscDualSpaceGetNumComponents()`.
1404b4457527SToby Isaac
1405b4457527SToby Isaac Level: advanced
1406b4457527SToby Isaac
1407dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `Mat`, `PetscDualSpaceCreate()`, `PetscDualSpaceGetInteriorData()`
1408b4457527SToby Isaac @*/
PetscDualSpaceCreateInteriorDataDefault(PetscDualSpace sp,PetscQuadrature * intNodes,Mat * intMat)1409d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreateInteriorDataDefault(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat)
1410d71ae5a4SJacob Faibussowitsch {
1411b4457527SToby Isaac DM dm;
1412b4457527SToby Isaac PetscInt spdim0;
1413b4457527SToby Isaac PetscInt Nc;
1414b4457527SToby Isaac PetscInt pStart, pEnd, p, f;
1415b4457527SToby Isaac PetscSection section;
1416b4457527SToby Isaac PetscInt numPoints, offset, matoffset;
1417b4457527SToby Isaac PetscReal *points;
1418b4457527SToby Isaac PetscInt dim;
1419b4457527SToby Isaac PetscInt *nnz;
1420b4457527SToby Isaac PetscQuadrature q;
1421b4457527SToby Isaac Mat imat;
1422b4457527SToby Isaac
1423b4457527SToby Isaac PetscFunctionBegin;
1424b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
14259566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion));
14269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &spdim0));
1427b4457527SToby Isaac if (!spdim0) {
1428b4457527SToby Isaac *intNodes = NULL;
1429b4457527SToby Isaac *intMat = NULL;
14303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1431b4457527SToby Isaac }
14329566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc));
14339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
14349566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm));
14359566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
14369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(spdim0, &nnz));
1437b4457527SToby Isaac for (p = pStart, f = 0, numPoints = 0; p < pEnd; p++) {
1438b4457527SToby Isaac PetscInt dof, cdof, off, d;
1439b4457527SToby Isaac
14409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof));
14419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof));
1442b4457527SToby Isaac if (!(dof - cdof)) continue;
14439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off));
1444b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) {
1445b4457527SToby Isaac PetscInt Np;
1446b4457527SToby Isaac
14479566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q));
14489566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL));
1449b4457527SToby Isaac nnz[f] = Np * Nc;
1450b4457527SToby Isaac numPoints += Np;
1451b4457527SToby Isaac }
1452b4457527SToby Isaac }
14539566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, spdim0, numPoints * Nc, 0, nnz, &imat));
14549566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz));
14559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points));
1456b4457527SToby Isaac for (p = pStart, f = 0, offset = 0, matoffset = 0; p < pEnd; p++) {
1457b4457527SToby Isaac PetscInt dof, cdof, off, d;
1458b4457527SToby Isaac
14599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof));
14609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof));
1461b4457527SToby Isaac if (!(dof - cdof)) continue;
14629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off));
1463b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) {
1464b4457527SToby Isaac const PetscReal *p;
1465b4457527SToby Isaac const PetscReal *w;
1466b4457527SToby Isaac PetscInt Np, i;
1467b4457527SToby Isaac
14689566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q));
14699566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, &p, &w));
1470ad540459SPierre Jolivet for (i = 0; i < Np * dim; i++) points[offset + i] = p[i];
147148a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(imat, f, matoffset + i, w[i], INSERT_VALUES));
1472b4457527SToby Isaac offset += Np * dim;
1473b4457527SToby Isaac matoffset += Np * Nc;
1474b4457527SToby Isaac }
1475b4457527SToby Isaac }
14769566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, intNodes));
14779566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*intNodes, dim, 0, numPoints, points, NULL));
14789566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(imat, MAT_FINAL_ASSEMBLY));
14799566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(imat, MAT_FINAL_ASSEMBLY));
1480b4457527SToby Isaac *intMat = imat;
14813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
148220cf1dd8SToby Isaac }
148320cf1dd8SToby Isaac
148426a11704SBarry Smith /*@C
1485dce8aebaSBarry Smith PetscDualSpaceEqual - Determine if two dual spaces are equivalent
14864f9ab2b4SJed Brown
14874f9ab2b4SJed Brown Input Parameters:
1488dce8aebaSBarry Smith + A - A `PetscDualSpace` object
1489dce8aebaSBarry Smith - B - Another `PetscDualSpace` object
14904f9ab2b4SJed Brown
14914f9ab2b4SJed Brown Output Parameter:
1492dce8aebaSBarry Smith . equal - `PETSC_TRUE` if the dual spaces are equivalent
14934f9ab2b4SJed Brown
14944f9ab2b4SJed Brown Level: advanced
14954f9ab2b4SJed Brown
1496dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`
14974f9ab2b4SJed Brown @*/
PetscDualSpaceEqual(PetscDualSpace A,PetscDualSpace B,PetscBool * equal)1498d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceEqual(PetscDualSpace A, PetscDualSpace B, PetscBool *equal)
1499d71ae5a4SJacob Faibussowitsch {
15004f9ab2b4SJed Brown PetscInt sizeA, sizeB, dimA, dimB;
15014f9ab2b4SJed Brown const PetscInt *dofA, *dofB;
15024f9ab2b4SJed Brown PetscQuadrature quadA, quadB;
15034f9ab2b4SJed Brown Mat matA, matB;
15044f9ab2b4SJed Brown
15054f9ab2b4SJed Brown PetscFunctionBegin;
15064f9ab2b4SJed Brown PetscValidHeaderSpecific(A, PETSCDUALSPACE_CLASSID, 1);
15074f9ab2b4SJed Brown PetscValidHeaderSpecific(B, PETSCDUALSPACE_CLASSID, 2);
15084f572ea9SToby Isaac PetscAssertPointer(equal, 3);
15094f9ab2b4SJed Brown *equal = PETSC_FALSE;
15109566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(A, &sizeA));
15119566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(B, &sizeB));
15123ba16761SJacob Faibussowitsch if (sizeB != sizeA) PetscFunctionReturn(PETSC_SUCCESS);
15139566063dSJacob Faibussowitsch PetscCall(DMGetDimension(A->dm, &dimA));
15149566063dSJacob Faibussowitsch PetscCall(DMGetDimension(B->dm, &dimB));
15153ba16761SJacob Faibussowitsch if (dimA != dimB) PetscFunctionReturn(PETSC_SUCCESS);
15164f9ab2b4SJed Brown
15179566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(A, &dofA));
15189566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(B, &dofB));
15194f9ab2b4SJed Brown for (PetscInt d = 0; d < dimA; d++) {
15203ba16761SJacob Faibussowitsch if (dofA[d] != dofB[d]) PetscFunctionReturn(PETSC_SUCCESS);
15214f9ab2b4SJed Brown }
15224f9ab2b4SJed Brown
15239566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(A, &quadA, &matA));
15249566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(B, &quadB, &matB));
15254f9ab2b4SJed Brown if (!quadA && !quadB) {
15264f9ab2b4SJed Brown *equal = PETSC_TRUE;
15274f9ab2b4SJed Brown } else if (quadA && quadB) {
15289566063dSJacob Faibussowitsch PetscCall(PetscQuadratureEqual(quadA, quadB, equal));
15293ba16761SJacob Faibussowitsch if (*equal == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
15303ba16761SJacob Faibussowitsch if (!matA && !matB) PetscFunctionReturn(PETSC_SUCCESS);
15319566063dSJacob Faibussowitsch if (matA && matB) PetscCall(MatEqual(matA, matB, equal));
15324f9ab2b4SJed Brown else *equal = PETSC_FALSE;
15334f9ab2b4SJed Brown }
15343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
15354f9ab2b4SJed Brown }
15364f9ab2b4SJed Brown
153720cf1dd8SToby Isaac /*@C
153820cf1dd8SToby Isaac PetscDualSpaceApplyFVM - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional at the cell centroid.
153920cf1dd8SToby Isaac
154020cf1dd8SToby Isaac Input Parameters:
1541dce8aebaSBarry Smith + sp - The `PetscDualSpace` object
154220cf1dd8SToby Isaac . f - The basis functional index
154320cf1dd8SToby Isaac . time - The time
154420cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we currently just use the centroid
154520cf1dd8SToby Isaac . Nc - The number of components for the function
154620cf1dd8SToby Isaac . func - The input function
154720cf1dd8SToby Isaac - ctx - A context for the function
154820cf1dd8SToby Isaac
154920cf1dd8SToby Isaac Output Parameter:
155020cf1dd8SToby Isaac . value - The output value (scalar)
155120cf1dd8SToby Isaac
155260225df5SJacob Faibussowitsch Calling sequence:
1553dce8aebaSBarry Smith .vb
1554*2a8381b2SBarry Smith PetscErrorCode func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt numComponents, PetscScalar values[], PetscCtx ctx)
1555dce8aebaSBarry Smith .ve
155620f4b53cSBarry Smith
1557dce8aebaSBarry Smith Level: advanced
155820cf1dd8SToby Isaac
1559dce8aebaSBarry Smith Note:
1560dce8aebaSBarry Smith The idea is to evaluate the functional as an integral $ n(f) = \int dx n(x) . f(x)$ where both n and f have Nc components.
156120cf1dd8SToby Isaac
1562dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`
156320cf1dd8SToby Isaac @*/
PetscDualSpaceApplyFVM(PetscDualSpace sp,PetscInt f,PetscReal time,PetscFVCellGeom * cgeom,PetscInt Nc,PetscErrorCode (* func)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),PetscCtx ctx,PetscScalar * value)1564*2a8381b2SBarry Smith PetscErrorCode PetscDualSpaceApplyFVM(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFVCellGeom *cgeom, PetscInt Nc, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), PetscCtx ctx, PetscScalar *value)
1565d71ae5a4SJacob Faibussowitsch {
156620cf1dd8SToby Isaac DM dm;
156720cf1dd8SToby Isaac PetscQuadrature n;
156820cf1dd8SToby Isaac const PetscReal *points, *weights;
156920cf1dd8SToby Isaac PetscScalar *val;
157020cf1dd8SToby Isaac PetscInt dimEmbed, qNc, c, Nq, q;
157120cf1dd8SToby Isaac
157220cf1dd8SToby Isaac PetscFunctionBegin;
157320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
15744f572ea9SToby Isaac PetscAssertPointer(value, 8);
15759566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm));
15769566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
15779566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n));
15789566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, NULL, &qNc, &Nq, &points, &weights));
157963a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc);
15809566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val));
158120cf1dd8SToby Isaac *value = 0.;
158220cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) {
15839566063dSJacob Faibussowitsch PetscCall((*func)(dimEmbed, time, cgeom->centroid, Nc, val, ctx));
1584ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) *value += val[c] * weights[q * Nc + c];
158520cf1dd8SToby Isaac }
15869566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val));
15873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
158820cf1dd8SToby Isaac }
158920cf1dd8SToby Isaac
159026a11704SBarry Smith /*@C
159120cf1dd8SToby Isaac PetscDualSpaceGetHeightSubspace - Get the subset of the dual space basis that is supported on a mesh point of a
159220cf1dd8SToby Isaac given height. This assumes that the reference cell is symmetric over points of this height.
159320cf1dd8SToby Isaac
159420f4b53cSBarry Smith Not Collective
159520cf1dd8SToby Isaac
159620cf1dd8SToby Isaac Input Parameters:
1597dce8aebaSBarry Smith + sp - the `PetscDualSpace` object
159820cf1dd8SToby Isaac - height - the height of the mesh point for which the subspace is desired
159920cf1dd8SToby Isaac
160020cf1dd8SToby Isaac Output Parameter:
160120cf1dd8SToby Isaac . subsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the
160220cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0.
160320cf1dd8SToby Isaac
160420cf1dd8SToby Isaac Level: advanced
160520cf1dd8SToby Isaac
1606dce8aebaSBarry Smith Notes:
1607dce8aebaSBarry Smith If the dual space is not defined on mesh points of the given height (e.g. if the space is discontinuous and
1608dce8aebaSBarry Smith pointwise values are not defined on the element boundaries), or if the implementation of `PetscDualSpace` does not
160926a11704SBarry Smith support extracting subspaces, then `NULL` is returned.
1610dce8aebaSBarry Smith
1611dce8aebaSBarry Smith This does not increment the reference count on the returned dual space, and the user should not destroy it.
1612dce8aebaSBarry Smith
161360225df5SJacob Faibussowitsch .seealso: `PetscDualSpace`, `PetscSpaceGetHeightSubspace()`, `PetscDualSpaceGetPointSubspace()`
161420cf1dd8SToby Isaac @*/
PetscDualSpaceGetHeightSubspace(PetscDualSpace sp,PetscInt height,PetscDualSpace * subsp)1615d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetHeightSubspace(PetscDualSpace sp, PetscInt height, PetscDualSpace *subsp)
1616d71ae5a4SJacob Faibussowitsch {
1617b4457527SToby Isaac PetscInt depth = -1, cStart, cEnd;
1618b4457527SToby Isaac DM dm;
161920cf1dd8SToby Isaac
162020cf1dd8SToby Isaac PetscFunctionBegin;
162120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
16224f572ea9SToby Isaac PetscAssertPointer(subsp, 3);
1623f4f49eeaSPierre Jolivet PetscCheck(sp->uniform, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "A non-uniform dual space does not have a single dual space at each height");
162420cf1dd8SToby Isaac *subsp = NULL;
1625b4457527SToby Isaac dm = sp->dm;
16269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
16271dca8a05SBarry Smith PetscCheck(height >= 0 && height <= depth, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid height");
16289566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1629b4457527SToby Isaac if (height == 0 && cEnd == cStart + 1) {
1630b4457527SToby Isaac *subsp = sp;
16313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1632b4457527SToby Isaac }
1633b4457527SToby Isaac if (!sp->heightSpaces) {
1634b4457527SToby Isaac PetscInt h;
1635f4f49eeaSPierre Jolivet PetscCall(PetscCalloc1(depth + 1, &sp->heightSpaces));
1636b4457527SToby Isaac
1637b4457527SToby Isaac for (h = 0; h <= depth; h++) {
1638b4457527SToby Isaac if (h == 0 && cEnd == cStart + 1) continue;
16399927e4dfSBarry Smith if (sp->ops->createheightsubspace) PetscUseTypeMethod(sp, createheightsubspace, height, &sp->heightSpaces[h]);
1640b4457527SToby Isaac else if (sp->pointSpaces) {
1641b4457527SToby Isaac PetscInt hStart, hEnd;
1642b4457527SToby Isaac
16439566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &hStart, &hEnd));
1644b4457527SToby Isaac if (hEnd > hStart) {
1645665f567fSMatthew G. Knepley const char *name;
1646665f567fSMatthew G. Knepley
1647f4f49eeaSPierre Jolivet PetscCall(PetscObjectReference((PetscObject)sp->pointSpaces[hStart]));
1648665f567fSMatthew G. Knepley if (sp->pointSpaces[hStart]) {
16499566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name));
16509566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sp->pointSpaces[hStart], name));
1651665f567fSMatthew G. Knepley }
1652b4457527SToby Isaac sp->heightSpaces[h] = sp->pointSpaces[hStart];
1653b4457527SToby Isaac }
1654b4457527SToby Isaac }
1655b4457527SToby Isaac }
1656b4457527SToby Isaac }
1657b4457527SToby Isaac *subsp = sp->heightSpaces[height];
16583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
165920cf1dd8SToby Isaac }
166020cf1dd8SToby Isaac
166126a11704SBarry Smith /*@C
166220cf1dd8SToby Isaac PetscDualSpaceGetPointSubspace - Get the subset of the dual space basis that is supported on a particular mesh point.
166320cf1dd8SToby Isaac
166420f4b53cSBarry Smith Not Collective
166520cf1dd8SToby Isaac
166620cf1dd8SToby Isaac Input Parameters:
1667dce8aebaSBarry Smith + sp - the `PetscDualSpace` object
166820cf1dd8SToby Isaac - point - the point (in the dual space's DM) for which the subspace is desired
166920cf1dd8SToby Isaac
167026a11704SBarry Smith Output Parameter:
1671a4e35b19SJacob Faibussowitsch . bdsp - the subspace.
167220cf1dd8SToby Isaac
167320cf1dd8SToby Isaac Level: advanced
167420cf1dd8SToby Isaac
1675dce8aebaSBarry Smith Notes:
1676a4e35b19SJacob Faibussowitsch The functionals in the subspace are with respect to the intrinsic geometry of the point,
1677a4e35b19SJacob Faibussowitsch which will be of lesser dimension if height > 0.
1678a4e35b19SJacob Faibussowitsch
1679dce8aebaSBarry Smith If the dual space is not defined on the mesh point (e.g. if the space is discontinuous and pointwise values are not
1680dce8aebaSBarry Smith defined on the element boundaries), or if the implementation of `PetscDualSpace` does not support extracting
1681a4e35b19SJacob Faibussowitsch subspaces, then `NULL` is returned.
1682dce8aebaSBarry Smith
1683dce8aebaSBarry Smith This does not increment the reference count on the returned dual space, and the user should not destroy it.
1684dce8aebaSBarry Smith
1685dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetHeightSubspace()`
168620cf1dd8SToby Isaac @*/
PetscDualSpaceGetPointSubspace(PetscDualSpace sp,PetscInt point,PetscDualSpace * bdsp)1687d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetPointSubspace(PetscDualSpace sp, PetscInt point, PetscDualSpace *bdsp)
1688d71ae5a4SJacob Faibussowitsch {
1689b4457527SToby Isaac PetscInt pStart = 0, pEnd = 0, cStart, cEnd;
1690b4457527SToby Isaac DM dm;
169120cf1dd8SToby Isaac
169220cf1dd8SToby Isaac PetscFunctionBegin;
169320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
16944f572ea9SToby Isaac PetscAssertPointer(bdsp, 3);
169520cf1dd8SToby Isaac *bdsp = NULL;
1696b4457527SToby Isaac dm = sp->dm;
16979566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
16981dca8a05SBarry Smith PetscCheck(point >= pStart && point <= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid point");
16999566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1700b4457527SToby Isaac if (point == cStart && cEnd == cStart + 1) { /* the dual space is only equivalent to the dual space on a cell if the reference mesh has just one cell */
1701b4457527SToby Isaac *bdsp = sp;
17023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1703b4457527SToby Isaac }
1704b4457527SToby Isaac if (!sp->pointSpaces) {
1705b4457527SToby Isaac PetscInt p;
1706f4f49eeaSPierre Jolivet PetscCall(PetscCalloc1(pEnd - pStart, &sp->pointSpaces));
170720cf1dd8SToby Isaac
1708b4457527SToby Isaac for (p = 0; p < pEnd - pStart; p++) {
1709b4457527SToby Isaac if (p + pStart == cStart && cEnd == cStart + 1) continue;
17109927e4dfSBarry Smith if (sp->ops->createpointsubspace) PetscUseTypeMethod(sp, createpointsubspace, p + pStart, &sp->pointSpaces[p]);
1711b4457527SToby Isaac else if (sp->heightSpaces || sp->ops->createheightsubspace) {
1712b4457527SToby Isaac PetscInt dim, depth, height;
1713b4457527SToby Isaac DMLabel label;
1714b4457527SToby Isaac
17159566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &dim));
17169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label));
17179566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, p + pStart, &depth));
171820cf1dd8SToby Isaac height = dim - depth;
1719f4f49eeaSPierre Jolivet PetscCall(PetscDualSpaceGetHeightSubspace(sp, height, &sp->pointSpaces[p]));
17209566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sp->pointSpaces[p]));
172120cf1dd8SToby Isaac }
1722b4457527SToby Isaac }
1723b4457527SToby Isaac }
1724b4457527SToby Isaac *bdsp = sp->pointSpaces[point - pStart];
17253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
172620cf1dd8SToby Isaac }
172720cf1dd8SToby Isaac
17286f905325SMatthew G. Knepley /*@C
17296f905325SMatthew G. Knepley PetscDualSpaceGetSymmetries - Returns a description of the symmetries of this basis
17306f905325SMatthew G. Knepley
173120f4b53cSBarry Smith Not Collective
17326f905325SMatthew G. Knepley
17336f905325SMatthew G. Knepley Input Parameter:
1734dce8aebaSBarry Smith . sp - the `PetscDualSpace` object
17356f905325SMatthew G. Knepley
17366f905325SMatthew G. Knepley Output Parameters:
1737b4457527SToby Isaac + perms - Permutations of the interior degrees of freedom, parameterized by the point orientation
1738b4457527SToby Isaac - flips - Sign reversal of the interior degrees of freedom, parameterized by the point orientation
17396f905325SMatthew G. Knepley
17406f905325SMatthew G. Knepley Level: developer
17416f905325SMatthew G. Knepley
1742dce8aebaSBarry Smith Note:
1743dce8aebaSBarry Smith The permutation and flip arrays are organized in the following way
1744dce8aebaSBarry Smith .vb
1745dce8aebaSBarry Smith perms[p][ornt][dof # on point] = new local dof #
1746dce8aebaSBarry Smith flips[p][ornt][dof # on point] = reversal or not
1747dce8aebaSBarry Smith .ve
1748dce8aebaSBarry Smith
1749dce8aebaSBarry Smith .seealso: `PetscDualSpace`
17506f905325SMatthew G. Knepley @*/
PetscDualSpaceGetSymmetries(PetscDualSpace sp,const PetscInt **** perms,const PetscScalar **** flips)1751d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetSymmetries(PetscDualSpace sp, const PetscInt ****perms, const PetscScalar ****flips)
1752d71ae5a4SJacob Faibussowitsch {
17536f905325SMatthew G. Knepley PetscFunctionBegin;
17546f905325SMatthew G. Knepley PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
17559371c9d4SSatish Balay if (perms) {
17564f572ea9SToby Isaac PetscAssertPointer(perms, 2);
17579371c9d4SSatish Balay *perms = NULL;
17589371c9d4SSatish Balay }
17599371c9d4SSatish Balay if (flips) {
17604f572ea9SToby Isaac PetscAssertPointer(flips, 3);
17619371c9d4SSatish Balay *flips = NULL;
17629371c9d4SSatish Balay }
17639927e4dfSBarry Smith PetscTryTypeMethod(sp, getsymmetries, perms, flips);
17643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
17656f905325SMatthew G. Knepley }
17664bee2e38SMatthew G. Knepley
176726a11704SBarry Smith /*@C
1768b4457527SToby Isaac PetscDualSpaceGetFormDegree - Get the form degree k for the k-form the describes the pushforwards/pullbacks of this
1769b4457527SToby Isaac dual space's functionals.
1770b4457527SToby Isaac
1771b4457527SToby Isaac Input Parameter:
1772dce8aebaSBarry Smith . dsp - The `PetscDualSpace`
1773b4457527SToby Isaac
1774b4457527SToby Isaac Output Parameter:
1775b4457527SToby Isaac . k - The *signed* degree k of the k. If k >= 0, this means that the degrees of freedom are k-forms, and are stored
1776b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example,
1777b4457527SToby Isaac the 1-form basis in 3-D is (dx, dy, dz), and the 2-form basis in 3-D is (dx wedge dy, dx wedge dz, dy wedge dz).
1778b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the
1779b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms
1780b4457527SToby Isaac but are stored as 1-forms.
1781b4457527SToby Isaac
1782b4457527SToby Isaac Level: developer
1783b4457527SToby Isaac
1784dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType`
1785b4457527SToby Isaac @*/
PetscDualSpaceGetFormDegree(PetscDualSpace dsp,PetscInt * k)1786d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetFormDegree(PetscDualSpace dsp, PetscInt *k)
1787d71ae5a4SJacob Faibussowitsch {
1788b4457527SToby Isaac PetscFunctionBeginHot;
1789b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1);
17904f572ea9SToby Isaac PetscAssertPointer(k, 2);
1791b4457527SToby Isaac *k = dsp->k;
17923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1793b4457527SToby Isaac }
1794b4457527SToby Isaac
179526a11704SBarry Smith /*@C
1796b4457527SToby Isaac PetscDualSpaceSetFormDegree - Set the form degree k for the k-form the describes the pushforwards/pullbacks of this
1797b4457527SToby Isaac dual space's functionals.
1798b4457527SToby Isaac
1799d8d19677SJose E. Roman Input Parameters:
1800dce8aebaSBarry Smith + dsp - The `PetscDualSpace`
1801b4457527SToby Isaac - k - The *signed* degree k of the k. If k >= 0, this means that the degrees of freedom are k-forms, and are stored
1802b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example,
1803b4457527SToby Isaac the 1-form basis in 3-D is (dx, dy, dz), and the 2-form basis in 3-D is (dx wedge dy, dx wedge dz, dy wedge dz).
1804b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the
1805b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms
1806b4457527SToby Isaac but are stored as 1-forms.
1807b4457527SToby Isaac
1808b4457527SToby Isaac Level: developer
1809b4457527SToby Isaac
1810dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType`
1811b4457527SToby Isaac @*/
PetscDualSpaceSetFormDegree(PetscDualSpace dsp,PetscInt k)1812d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetFormDegree(PetscDualSpace dsp, PetscInt k)
1813d71ae5a4SJacob Faibussowitsch {
1814b4457527SToby Isaac PetscInt dim;
1815b4457527SToby Isaac
1816b4457527SToby Isaac PetscFunctionBeginHot;
1817b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1);
181828b400f6SJacob Faibussowitsch PetscCheck(!dsp->setupcalled, PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up");
1819b4457527SToby Isaac dim = dsp->dm->dim;
18202dce792eSToby Isaac PetscCheck((k >= -dim && k <= dim) || k == PETSC_FORM_DEGREE_UNDEFINED, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unsupported %" PetscInt_FMT "-form on %" PetscInt_FMT "-dimensional reference cell", PetscAbsInt(k), dim);
1821b4457527SToby Isaac dsp->k = k;
18223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1823b4457527SToby Isaac }
1824b4457527SToby Isaac
182526a11704SBarry Smith /*@C
18264bee2e38SMatthew G. Knepley PetscDualSpaceGetDeRahm - Get the k-simplex associated with the functionals in this dual space
18274bee2e38SMatthew G. Knepley
18284bee2e38SMatthew G. Knepley Input Parameter:
1829dce8aebaSBarry Smith . dsp - The `PetscDualSpace`
18304bee2e38SMatthew G. Knepley
18314bee2e38SMatthew G. Knepley Output Parameter:
18324bee2e38SMatthew G. Knepley . k - The simplex dimension
18334bee2e38SMatthew G. Knepley
1834a4ce7ad1SMatthew G. Knepley Level: developer
18354bee2e38SMatthew G. Knepley
1836dce8aebaSBarry Smith Note:
1837dce8aebaSBarry Smith Currently supported values are
1838dce8aebaSBarry Smith .vb
1839dce8aebaSBarry Smith 0: These are H_1 methods that only transform coordinates
1840dce8aebaSBarry Smith 1: These are Hcurl methods that transform functions using the covariant Piola transform (COVARIANT_PIOLA_TRANSFORM)
1841dce8aebaSBarry Smith 2: These are the same as 1
1842dce8aebaSBarry Smith 3: These are Hdiv methods that transform functions using the contravariant Piola transform (CONTRAVARIANT_PIOLA_TRANSFORM)
1843dce8aebaSBarry Smith .ve
18444bee2e38SMatthew G. Knepley
1845dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType`
18464bee2e38SMatthew G. Knepley @*/
PetscDualSpaceGetDeRahm(PetscDualSpace dsp,PetscInt * k)1847d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDeRahm(PetscDualSpace dsp, PetscInt *k)
1848d71ae5a4SJacob Faibussowitsch {
1849b4457527SToby Isaac PetscInt dim;
1850b4457527SToby Isaac
18514bee2e38SMatthew G. Knepley PetscFunctionBeginHot;
18524bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1);
18534f572ea9SToby Isaac PetscAssertPointer(k, 2);
1854b4457527SToby Isaac dim = dsp->dm->dim;
1855b4457527SToby Isaac if (!dsp->k) *k = IDENTITY_TRANSFORM;
1856b4457527SToby Isaac else if (dsp->k == 1) *k = COVARIANT_PIOLA_TRANSFORM;
1857b4457527SToby Isaac else if (dsp->k == -(dim - 1)) *k = CONTRAVARIANT_PIOLA_TRANSFORM;
1858b4457527SToby Isaac else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unsupported transformation");
18593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
18604bee2e38SMatthew G. Knepley }
18614bee2e38SMatthew G. Knepley
186226a11704SBarry Smith /*@C
18634bee2e38SMatthew G. Knepley PetscDualSpaceTransform - Transform the function values
18644bee2e38SMatthew G. Knepley
18654bee2e38SMatthew G. Knepley Input Parameters:
1866dce8aebaSBarry Smith + dsp - The `PetscDualSpace`
18674bee2e38SMatthew G. Knepley . trans - The type of transform
18684bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform
18694bee2e38SMatthew G. Knepley . fegeom - The cell geometry
18704bee2e38SMatthew G. Knepley . Nv - The number of function samples
18714bee2e38SMatthew G. Knepley . Nc - The number of function components
18724bee2e38SMatthew G. Knepley - vals - The function values
18734bee2e38SMatthew G. Knepley
18744bee2e38SMatthew G. Knepley Output Parameter:
18754bee2e38SMatthew G. Knepley . vals - The transformed function values
18764bee2e38SMatthew G. Knepley
1877a4ce7ad1SMatthew G. Knepley Level: intermediate
18784bee2e38SMatthew G. Knepley
1879dce8aebaSBarry Smith Note:
1880dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
18812edcad52SToby Isaac
1882dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransformGradient()`, `PetscDualSpaceTransformHessian()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType`
18834bee2e38SMatthew G. Knepley @*/
PetscDualSpaceTransform(PetscDualSpace dsp,PetscDualSpaceTransformType trans,PetscBool isInverse,PetscFEGeom * fegeom,PetscInt Nv,PetscInt Nc,PetscScalar vals[])1884d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransform(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[])
1885d71ae5a4SJacob Faibussowitsch {
1886b4457527SToby Isaac PetscReal Jstar[9] = {0};
1887b4457527SToby Isaac PetscInt dim, v, c, Nk;
18884bee2e38SMatthew G. Knepley
18894bee2e38SMatthew G. Knepley PetscFunctionBeginHot;
18904bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1);
18914f572ea9SToby Isaac PetscAssertPointer(fegeom, 4);
18924f572ea9SToby Isaac PetscAssertPointer(vals, 7);
1893b4457527SToby Isaac /* TODO: not handling dimEmbed != dim right now */
18942ae266adSMatthew G. Knepley dim = dsp->dm->dim;
1895b4457527SToby Isaac /* No change needed for 0-forms */
18963ba16761SJacob Faibussowitsch if (!dsp->k) PetscFunctionReturn(PETSC_SUCCESS);
18979566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(dsp->k), &Nk));
1898b4457527SToby Isaac /* TODO: use fegeom->isAffine */
18999566063dSJacob Faibussowitsch PetscCall(PetscDTAltVPullbackMatrix(dim, dim, isInverse ? fegeom->J : fegeom->invJ, dsp->k, Jstar));
19004bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) {
1901b4457527SToby Isaac switch (Nk) {
1902b4457527SToby Isaac case 1:
1903b4457527SToby Isaac for (c = 0; c < Nc; c++) vals[v * Nc + c] *= Jstar[0];
19044bee2e38SMatthew G. Knepley break;
1905b4457527SToby Isaac case 2:
1906b4457527SToby Isaac for (c = 0; c < Nc; c += 2) DMPlex_Mult2DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]);
19074bee2e38SMatthew G. Knepley break;
1908b4457527SToby Isaac case 3:
1909b4457527SToby Isaac for (c = 0; c < Nc; c += 3) DMPlex_Mult3DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]);
1910b4457527SToby Isaac break;
1911d71ae5a4SJacob Faibussowitsch default:
1912d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported form size %" PetscInt_FMT " for transformation", Nk);
1913b4457527SToby Isaac }
19144bee2e38SMatthew G. Knepley }
19153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
19164bee2e38SMatthew G. Knepley }
1917b4457527SToby Isaac
191826a11704SBarry Smith /*@C
19194bee2e38SMatthew G. Knepley PetscDualSpaceTransformGradient - Transform the function gradient values
19204bee2e38SMatthew G. Knepley
19214bee2e38SMatthew G. Knepley Input Parameters:
1922dce8aebaSBarry Smith + dsp - The `PetscDualSpace`
19234bee2e38SMatthew G. Knepley . trans - The type of transform
19244bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform
19254bee2e38SMatthew G. Knepley . fegeom - The cell geometry
19264bee2e38SMatthew G. Knepley . Nv - The number of function gradient samples
19274bee2e38SMatthew G. Knepley . Nc - The number of function components
19284bee2e38SMatthew G. Knepley - vals - The function gradient values
19294bee2e38SMatthew G. Knepley
19304bee2e38SMatthew G. Knepley Output Parameter:
1931f9244615SMatthew G. Knepley . vals - The transformed function gradient values
19324bee2e38SMatthew G. Knepley
1933a4ce7ad1SMatthew G. Knepley Level: intermediate
19344bee2e38SMatthew G. Knepley
1935dce8aebaSBarry Smith Note:
1936dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
19372edcad52SToby Isaac
1938dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType`
19394bee2e38SMatthew G. Knepley @*/
PetscDualSpaceTransformGradient(PetscDualSpace dsp,PetscDualSpaceTransformType trans,PetscBool isInverse,PetscFEGeom * fegeom,PetscInt Nv,PetscInt Nc,PetscScalar vals[])1940d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransformGradient(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[])
1941d71ae5a4SJacob Faibussowitsch {
194227f02ce8SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed;
194327f02ce8SMatthew G. Knepley PetscInt v, c, d;
19444bee2e38SMatthew G. Knepley
19454bee2e38SMatthew G. Knepley PetscFunctionBeginHot;
19464bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1);
19474f572ea9SToby Isaac PetscAssertPointer(fegeom, 4);
19484f572ea9SToby Isaac PetscAssertPointer(vals, 7);
1949b498ca8aSPierre Jolivet PetscAssert(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE);
19504bee2e38SMatthew G. Knepley /* Transform gradient */
195127f02ce8SMatthew G. Knepley if (dim == dE) {
19524bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) {
19534bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) {
19549371c9d4SSatish Balay switch (dim) {
1955d71ae5a4SJacob Faibussowitsch case 1:
1956d71ae5a4SJacob Faibussowitsch vals[(v * Nc + c) * dim] *= fegeom->invJ[0];
1957d71ae5a4SJacob Faibussowitsch break;
1958d71ae5a4SJacob Faibussowitsch case 2:
1959d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]);
1960d71ae5a4SJacob Faibussowitsch break;
1961d71ae5a4SJacob Faibussowitsch case 3:
1962d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]);
1963d71ae5a4SJacob Faibussowitsch break;
1964d71ae5a4SJacob Faibussowitsch default:
1965d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim);
19664bee2e38SMatthew G. Knepley }
19674bee2e38SMatthew G. Knepley }
19684bee2e38SMatthew G. Knepley }
196927f02ce8SMatthew G. Knepley } else {
197027f02ce8SMatthew G. Knepley for (v = 0; v < Nv; ++v) {
1971ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) DMPlex_MultTransposeReal_Internal(fegeom->invJ, dim, dE, 1, &vals[(v * Nc + c) * dE], &vals[(v * Nc + c) * dE]);
197227f02ce8SMatthew G. Knepley }
197327f02ce8SMatthew G. Knepley }
19744bee2e38SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */
19753ba16761SJacob Faibussowitsch if (Nc == 1 || Nc != dim) PetscFunctionReturn(PETSC_SUCCESS);
19764bee2e38SMatthew G. Knepley switch (trans) {
1977d71ae5a4SJacob Faibussowitsch case IDENTITY_TRANSFORM:
1978d71ae5a4SJacob Faibussowitsch break;
19794bee2e38SMatthew G. Knepley case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */
19804bee2e38SMatthew G. Knepley if (isInverse) {
19814bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) {
19824bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) {
19839371c9d4SSatish Balay switch (dim) {
1984d71ae5a4SJacob Faibussowitsch case 2:
1985d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]);
1986d71ae5a4SJacob Faibussowitsch break;
1987d71ae5a4SJacob Faibussowitsch case 3:
1988d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]);
1989d71ae5a4SJacob Faibussowitsch break;
1990d71ae5a4SJacob Faibussowitsch default:
1991d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim);
19924bee2e38SMatthew G. Knepley }
19934bee2e38SMatthew G. Knepley }
19944bee2e38SMatthew G. Knepley }
19954bee2e38SMatthew G. Knepley } else {
19964bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) {
19974bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) {
19989371c9d4SSatish Balay switch (dim) {
1999d71ae5a4SJacob Faibussowitsch case 2:
2000d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]);
2001d71ae5a4SJacob Faibussowitsch break;
2002d71ae5a4SJacob Faibussowitsch case 3:
2003d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]);
2004d71ae5a4SJacob Faibussowitsch break;
2005d71ae5a4SJacob Faibussowitsch default:
2006d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim);
20074bee2e38SMatthew G. Knepley }
20084bee2e38SMatthew G. Knepley }
20094bee2e38SMatthew G. Knepley }
20104bee2e38SMatthew G. Knepley }
20114bee2e38SMatthew G. Knepley break;
20124bee2e38SMatthew G. Knepley case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */
20134bee2e38SMatthew G. Knepley if (isInverse) {
20144bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) {
20154bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) {
20169371c9d4SSatish Balay switch (dim) {
2017d71ae5a4SJacob Faibussowitsch case 2:
2018d71ae5a4SJacob Faibussowitsch DMPlex_Mult2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]);
2019d71ae5a4SJacob Faibussowitsch break;
2020d71ae5a4SJacob Faibussowitsch case 3:
2021d71ae5a4SJacob Faibussowitsch DMPlex_Mult3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]);
2022d71ae5a4SJacob Faibussowitsch break;
2023d71ae5a4SJacob Faibussowitsch default:
2024d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim);
20254bee2e38SMatthew G. Knepley }
20264bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] *= fegeom->detJ[0];
20274bee2e38SMatthew G. Knepley }
20284bee2e38SMatthew G. Knepley }
20294bee2e38SMatthew G. Knepley } else {
20304bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) {
20314bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) {
20329371c9d4SSatish Balay switch (dim) {
2033d71ae5a4SJacob Faibussowitsch case 2:
2034d71ae5a4SJacob Faibussowitsch DMPlex_Mult2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]);
2035d71ae5a4SJacob Faibussowitsch break;
2036d71ae5a4SJacob Faibussowitsch case 3:
2037d71ae5a4SJacob Faibussowitsch DMPlex_Mult3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]);
2038d71ae5a4SJacob Faibussowitsch break;
2039d71ae5a4SJacob Faibussowitsch default:
2040d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim);
20414bee2e38SMatthew G. Knepley }
20424bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] /= fegeom->detJ[0];
20434bee2e38SMatthew G. Knepley }
20444bee2e38SMatthew G. Knepley }
20454bee2e38SMatthew G. Knepley }
20464bee2e38SMatthew G. Knepley break;
20474bee2e38SMatthew G. Knepley }
20483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
20494bee2e38SMatthew G. Knepley }
20504bee2e38SMatthew G. Knepley
205126a11704SBarry Smith /*@C
2052f9244615SMatthew G. Knepley PetscDualSpaceTransformHessian - Transform the function Hessian values
2053f9244615SMatthew G. Knepley
2054f9244615SMatthew G. Knepley Input Parameters:
2055dce8aebaSBarry Smith + dsp - The `PetscDualSpace`
2056f9244615SMatthew G. Knepley . trans - The type of transform
2057f9244615SMatthew G. Knepley . isInverse - Flag to invert the transform
2058f9244615SMatthew G. Knepley . fegeom - The cell geometry
2059f9244615SMatthew G. Knepley . Nv - The number of function Hessian samples
2060f9244615SMatthew G. Knepley . Nc - The number of function components
2061f9244615SMatthew G. Knepley - vals - The function gradient values
2062f9244615SMatthew G. Knepley
2063f9244615SMatthew G. Knepley Output Parameter:
2064f9244615SMatthew G. Knepley . vals - The transformed function Hessian values
2065f9244615SMatthew G. Knepley
2066f9244615SMatthew G. Knepley Level: intermediate
2067f9244615SMatthew G. Knepley
2068dce8aebaSBarry Smith Note:
2069dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
2070f9244615SMatthew G. Knepley
2071dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType`
2072f9244615SMatthew G. Knepley @*/
PetscDualSpaceTransformHessian(PetscDualSpace dsp,PetscDualSpaceTransformType trans,PetscBool isInverse,PetscFEGeom * fegeom,PetscInt Nv,PetscInt Nc,PetscScalar vals[])2073d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransformHessian(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[])
2074d71ae5a4SJacob Faibussowitsch {
2075f9244615SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed;
2076f9244615SMatthew G. Knepley PetscInt v, c;
2077f9244615SMatthew G. Knepley
2078f9244615SMatthew G. Knepley PetscFunctionBeginHot;
2079f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1);
20804f572ea9SToby Isaac PetscAssertPointer(fegeom, 4);
20814f572ea9SToby Isaac PetscAssertPointer(vals, 7);
2082b498ca8aSPierre Jolivet PetscAssert(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE);
2083f9244615SMatthew G. Knepley /* Transform Hessian: J^{-T}_{ik} J^{-T}_{jl} H(f)_{kl} = J^{-T}_{ik} H(f)_{kl} J^{-1}_{lj} */
2084f9244615SMatthew G. Knepley if (dim == dE) {
2085f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) {
2086f9244615SMatthew G. Knepley for (c = 0; c < Nc; ++c) {
20879371c9d4SSatish Balay switch (dim) {
2088d71ae5a4SJacob Faibussowitsch case 1:
2089d71ae5a4SJacob Faibussowitsch vals[(v * Nc + c) * dim * dim] *= PetscSqr(fegeom->invJ[0]);
2090d71ae5a4SJacob Faibussowitsch break;
2091d71ae5a4SJacob Faibussowitsch case 2:
2092d71ae5a4SJacob Faibussowitsch DMPlex_PTAP2DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]);
2093d71ae5a4SJacob Faibussowitsch break;
2094d71ae5a4SJacob Faibussowitsch case 3:
2095d71ae5a4SJacob Faibussowitsch DMPlex_PTAP3DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]);
2096d71ae5a4SJacob Faibussowitsch break;
2097d71ae5a4SJacob Faibussowitsch default:
2098d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim);
2099f9244615SMatthew G. Knepley }
2100f9244615SMatthew G. Knepley }
2101f9244615SMatthew G. Knepley }
2102f9244615SMatthew G. Knepley } else {
2103f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) {
2104ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) DMPlex_PTAPReal_Internal(fegeom->invJ, dim, dE, &vals[(v * Nc + c) * dE * dE], &vals[(v * Nc + c) * dE * dE]);
2105f9244615SMatthew G. Knepley }
2106f9244615SMatthew G. Knepley }
2107f9244615SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */
21083ba16761SJacob Faibussowitsch if (Nc == 1 || Nc != dim) PetscFunctionReturn(PETSC_SUCCESS);
2109f9244615SMatthew G. Knepley switch (trans) {
2110d71ae5a4SJacob Faibussowitsch case IDENTITY_TRANSFORM:
2111d71ae5a4SJacob Faibussowitsch break;
2112d71ae5a4SJacob Faibussowitsch case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */
2113d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported");
2114d71ae5a4SJacob Faibussowitsch case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */
2115d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported");
2116f9244615SMatthew G. Knepley }
21173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2118f9244615SMatthew G. Knepley }
2119f9244615SMatthew G. Knepley
212026a11704SBarry Smith /*@C
21214bee2e38SMatthew G. Knepley PetscDualSpacePullback - Transform the given functional so that it operates on real space, rather than the reference element. Operationally, this means that we map the function evaluations depending on continuity requirements of our finite element method.
21224bee2e38SMatthew G. Knepley
21234bee2e38SMatthew G. Knepley Input Parameters:
2124dce8aebaSBarry Smith + dsp - The `PetscDualSpace`
21254bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell
21264bee2e38SMatthew G. Knepley . Nq - The number of function samples
21274bee2e38SMatthew G. Knepley . Nc - The number of function components
21284bee2e38SMatthew G. Knepley - pointEval - The function values
21294bee2e38SMatthew G. Knepley
21304bee2e38SMatthew G. Knepley Output Parameter:
21314bee2e38SMatthew G. Knepley . pointEval - The transformed function values
21324bee2e38SMatthew G. Knepley
21334bee2e38SMatthew G. Knepley Level: advanced
21344bee2e38SMatthew G. Knepley
2135dce8aebaSBarry Smith Notes:
2136dce8aebaSBarry Smith Functions transform in a complementary way (pushforward) to functionals, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex.
21374bee2e38SMatthew G. Knepley
2138da81f932SPierre Jolivet This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
21392edcad52SToby Isaac
2140dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()`
21414bee2e38SMatthew G. Knepley @*/
PetscDualSpacePullback(PetscDualSpace dsp,PetscFEGeom * fegeom,PetscInt Nq,PetscInt Nc,PetscScalar pointEval[])2142d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePullback(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[])
2143d71ae5a4SJacob Faibussowitsch {
21444bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans;
2145b4457527SToby Isaac PetscInt k;
21464bee2e38SMatthew G. Knepley
21474bee2e38SMatthew G. Knepley PetscFunctionBeginHot;
21484bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1);
21494f572ea9SToby Isaac PetscAssertPointer(fegeom, 2);
21504f572ea9SToby Isaac PetscAssertPointer(pointEval, 5);
21514bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k.
21524bee2e38SMatthew G. Knepley This determines their transformation properties. */
21539566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k));
21549371c9d4SSatish Balay switch (k) {
2155d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */
2156d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM;
2157d71ae5a4SJacob Faibussowitsch break;
2158d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */
2159d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM;
2160d71ae5a4SJacob Faibussowitsch break;
2161b4457527SToby Isaac case 2:
2162d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */
2163d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM;
2164d71ae5a4SJacob Faibussowitsch break;
2165d71ae5a4SJacob Faibussowitsch default:
2166d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k);
21674bee2e38SMatthew G. Knepley }
21689566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_TRUE, fegeom, Nq, Nc, pointEval));
21693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
21704bee2e38SMatthew G. Knepley }
21714bee2e38SMatthew G. Knepley
217226a11704SBarry Smith /*@C
21734bee2e38SMatthew G. Knepley PetscDualSpacePushforward - Transform the given function so that it operates on real space, rather than the reference element. Operationally, this means that we map the function evaluations depending on continuity requirements of our finite element method.
21744bee2e38SMatthew G. Knepley
21754bee2e38SMatthew G. Knepley Input Parameters:
2176dce8aebaSBarry Smith + dsp - The `PetscDualSpace`
21774bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell
21784bee2e38SMatthew G. Knepley . Nq - The number of function samples
21794bee2e38SMatthew G. Knepley . Nc - The number of function components
21804bee2e38SMatthew G. Knepley - pointEval - The function values
21814bee2e38SMatthew G. Knepley
21824bee2e38SMatthew G. Knepley Output Parameter:
21834bee2e38SMatthew G. Knepley . pointEval - The transformed function values
21844bee2e38SMatthew G. Knepley
21854bee2e38SMatthew G. Knepley Level: advanced
21864bee2e38SMatthew G. Knepley
2187dce8aebaSBarry Smith Notes:
2188dce8aebaSBarry Smith Functionals transform in a complementary way (pullback) to functions, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex.
21894bee2e38SMatthew G. Knepley
2190dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
21912edcad52SToby Isaac
2192dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()`
21934bee2e38SMatthew G. Knepley @*/
PetscDualSpacePushforward(PetscDualSpace dsp,PetscFEGeom * fegeom,PetscInt Nq,PetscInt Nc,PetscScalar pointEval[])2194d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforward(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[])
2195d71ae5a4SJacob Faibussowitsch {
21964bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans;
2197b4457527SToby Isaac PetscInt k;
21984bee2e38SMatthew G. Knepley
21994bee2e38SMatthew G. Knepley PetscFunctionBeginHot;
22004bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1);
22014f572ea9SToby Isaac PetscAssertPointer(fegeom, 2);
22024f572ea9SToby Isaac PetscAssertPointer(pointEval, 5);
22034bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k.
22044bee2e38SMatthew G. Knepley This determines their transformation properties. */
22059566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k));
22069371c9d4SSatish Balay switch (k) {
2207d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */
2208d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM;
2209d71ae5a4SJacob Faibussowitsch break;
2210d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */
2211d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM;
2212d71ae5a4SJacob Faibussowitsch break;
2213b4457527SToby Isaac case 2:
2214d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */
2215d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM;
2216d71ae5a4SJacob Faibussowitsch break;
2217d71ae5a4SJacob Faibussowitsch default:
2218d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k);
22194bee2e38SMatthew G. Knepley }
22209566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval));
22213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
22224bee2e38SMatthew G. Knepley }
22234bee2e38SMatthew G. Knepley
222426a11704SBarry Smith /*@C
22254bee2e38SMatthew G. Knepley PetscDualSpacePushforwardGradient - Transform the given function gradient so that it operates on real space, rather than the reference element. Operationally, this means that we map the function evaluations depending on continuity requirements of our finite element method.
22264bee2e38SMatthew G. Knepley
22274bee2e38SMatthew G. Knepley Input Parameters:
2228dce8aebaSBarry Smith + dsp - The `PetscDualSpace`
22294bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell
22304bee2e38SMatthew G. Knepley . Nq - The number of function gradient samples
22314bee2e38SMatthew G. Knepley . Nc - The number of function components
22324bee2e38SMatthew G. Knepley - pointEval - The function gradient values
22334bee2e38SMatthew G. Knepley
22344bee2e38SMatthew G. Knepley Output Parameter:
22354bee2e38SMatthew G. Knepley . pointEval - The transformed function gradient values
22364bee2e38SMatthew G. Knepley
22374bee2e38SMatthew G. Knepley Level: advanced
22384bee2e38SMatthew G. Knepley
2239dce8aebaSBarry Smith Notes:
2240dce8aebaSBarry Smith Functionals transform in a complementary way (pullback) to functions, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex.
22414bee2e38SMatthew G. Knepley
2242dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
22432edcad52SToby Isaac
2244bfe80ac4SPierre Jolivet .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()`
2245dc0529c6SBarry Smith @*/
PetscDualSpacePushforwardGradient(PetscDualSpace dsp,PetscFEGeom * fegeom,PetscInt Nq,PetscInt Nc,PetscScalar pointEval[])2246d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforwardGradient(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[])
2247d71ae5a4SJacob Faibussowitsch {
22484bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans;
2249b4457527SToby Isaac PetscInt k;
22504bee2e38SMatthew G. Knepley
22514bee2e38SMatthew G. Knepley PetscFunctionBeginHot;
22524bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1);
22534f572ea9SToby Isaac PetscAssertPointer(fegeom, 2);
22544f572ea9SToby Isaac PetscAssertPointer(pointEval, 5);
22554bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k.
22564bee2e38SMatthew G. Knepley This determines their transformation properties. */
22579566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k));
22589371c9d4SSatish Balay switch (k) {
2259d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */
2260d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM;
2261d71ae5a4SJacob Faibussowitsch break;
2262d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */
2263d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM;
2264d71ae5a4SJacob Faibussowitsch break;
2265b4457527SToby Isaac case 2:
2266d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */
2267d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM;
2268d71ae5a4SJacob Faibussowitsch break;
2269d71ae5a4SJacob Faibussowitsch default:
2270d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k);
22714bee2e38SMatthew G. Knepley }
22729566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformGradient(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval));
22733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
22744bee2e38SMatthew G. Knepley }
2275f9244615SMatthew G. Knepley
227626a11704SBarry Smith /*@C
2277f9244615SMatthew G. Knepley PetscDualSpacePushforwardHessian - Transform the given function Hessian so that it operates on real space, rather than the reference element. Operationally, this means that we map the function evaluations depending on continuity requirements of our finite element method.
2278f9244615SMatthew G. Knepley
2279f9244615SMatthew G. Knepley Input Parameters:
2280dce8aebaSBarry Smith + dsp - The `PetscDualSpace`
2281f9244615SMatthew G. Knepley . fegeom - The geometry for this cell
2282f9244615SMatthew G. Knepley . Nq - The number of function Hessian samples
2283f9244615SMatthew G. Knepley . Nc - The number of function components
2284f9244615SMatthew G. Knepley - pointEval - The function gradient values
2285f9244615SMatthew G. Knepley
2286f9244615SMatthew G. Knepley Output Parameter:
2287f9244615SMatthew G. Knepley . pointEval - The transformed function Hessian values
2288f9244615SMatthew G. Knepley
2289f9244615SMatthew G. Knepley Level: advanced
2290f9244615SMatthew G. Knepley
2291dce8aebaSBarry Smith Notes:
2292dce8aebaSBarry Smith Functionals transform in a complementary way (pullback) to functions, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex.
2293f9244615SMatthew G. Knepley
2294dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
2295f9244615SMatthew G. Knepley
2296bfe80ac4SPierre Jolivet .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()`
2297f9244615SMatthew G. Knepley @*/
PetscDualSpacePushforwardHessian(PetscDualSpace dsp,PetscFEGeom * fegeom,PetscInt Nq,PetscInt Nc,PetscScalar pointEval[])2298d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforwardHessian(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[])
2299d71ae5a4SJacob Faibussowitsch {
2300f9244615SMatthew G. Knepley PetscDualSpaceTransformType trans;
2301f9244615SMatthew G. Knepley PetscInt k;
2302f9244615SMatthew G. Knepley
2303f9244615SMatthew G. Knepley PetscFunctionBeginHot;
2304f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1);
23054f572ea9SToby Isaac PetscAssertPointer(fegeom, 2);
23064f572ea9SToby Isaac PetscAssertPointer(pointEval, 5);
2307f9244615SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k.
2308f9244615SMatthew G. Knepley This determines their transformation properties. */
23099566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k));
23109371c9d4SSatish Balay switch (k) {
2311d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */
2312d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM;
2313d71ae5a4SJacob Faibussowitsch break;
2314d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */
2315d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM;
2316d71ae5a4SJacob Faibussowitsch break;
2317f9244615SMatthew G. Knepley case 2:
2318d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */
2319d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM;
2320d71ae5a4SJacob Faibussowitsch break;
2321d71ae5a4SJacob Faibussowitsch default:
2322d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k);
2323f9244615SMatthew G. Knepley }
23249566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformHessian(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval));
23253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2326f9244615SMatthew G. Knepley }
2327