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: 226f905325SMatthew G. Knepley . tup - A tuple of len integers whos sum is at most 'max' 236f905325SMatthew G. Knepley 246f905325SMatthew G. Knepley Level: developer 256f905325SMatthew G. Knepley 26db781477SPatrick Sanan .seealso: `PetscDualSpaceTensorPointLexicographic_Internal()` 276f905325SMatthew G. Knepley */ 289371c9d4SSatish Balay PetscErrorCode PetscDualSpaceLatticePointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) { 296f905325SMatthew G. Knepley PetscFunctionBegin; 306f905325SMatthew G. Knepley while (len--) { 316f905325SMatthew G. Knepley max -= tup[len]; 326f905325SMatthew G. Knepley if (!max) { 336f905325SMatthew G. Knepley tup[len] = 0; 346f905325SMatthew G. Knepley break; 356f905325SMatthew G. Knepley } 366f905325SMatthew G. Knepley } 376f905325SMatthew G. Knepley tup[++len]++; 386f905325SMatthew G. Knepley PetscFunctionReturn(0); 396f905325SMatthew G. Knepley } 406f905325SMatthew G. Knepley 416f905325SMatthew G. Knepley /* 426f905325SMatthew G. Knepley PetscDualSpaceTensorPointLexicographic_Internal - Returns all tuples of size 'len' with nonnegative integers that are all less than or equal to 'max'. 436f905325SMatthew G. Knepley Ordering is lexicographic with lowest index as least significant in ordering. 446f905325SMatthew 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}. 456f905325SMatthew G. Knepley 466f905325SMatthew G. Knepley Input Parameters: 476f905325SMatthew G. Knepley + len - The length of the tuple 486f905325SMatthew G. Knepley . max - The maximum value 496f905325SMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 506f905325SMatthew G. Knepley 516f905325SMatthew G. Knepley Output Parameter: 526f905325SMatthew G. Knepley . tup - A tuple of len integers whos sum is at most 'max' 536f905325SMatthew G. Knepley 546f905325SMatthew G. Knepley Level: developer 556f905325SMatthew G. Knepley 56db781477SPatrick Sanan .seealso: `PetscDualSpaceLatticePointLexicographic_Internal()` 576f905325SMatthew G. Knepley */ 589371c9d4SSatish Balay PetscErrorCode PetscDualSpaceTensorPointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) { 596f905325SMatthew G. Knepley PetscInt i; 606f905325SMatthew G. Knepley 616f905325SMatthew G. Knepley PetscFunctionBegin; 626f905325SMatthew G. Knepley for (i = 0; i < len; i++) { 636f905325SMatthew G. Knepley if (tup[i] < max) { 646f905325SMatthew G. Knepley break; 656f905325SMatthew G. Knepley } else { 666f905325SMatthew G. Knepley tup[i] = 0; 676f905325SMatthew G. Knepley } 686f905325SMatthew G. Knepley } 696f905325SMatthew G. Knepley tup[i]++; 706f905325SMatthew G. Knepley PetscFunctionReturn(0); 716f905325SMatthew G. Knepley } 726f905325SMatthew G. Knepley 7320cf1dd8SToby Isaac /*@C 7420cf1dd8SToby Isaac PetscDualSpaceRegister - Adds a new PetscDualSpace implementation 7520cf1dd8SToby Isaac 7620cf1dd8SToby Isaac Not Collective 7720cf1dd8SToby Isaac 7820cf1dd8SToby Isaac Input Parameters: 7920cf1dd8SToby Isaac + name - The name of a new user-defined creation routine 8020cf1dd8SToby Isaac - create_func - The creation routine itself 8120cf1dd8SToby Isaac 8220cf1dd8SToby Isaac Notes: 8320cf1dd8SToby Isaac PetscDualSpaceRegister() may be called multiple times to add several user-defined PetscDualSpaces 8420cf1dd8SToby Isaac 8520cf1dd8SToby Isaac Sample usage: 8620cf1dd8SToby Isaac .vb 8720cf1dd8SToby Isaac PetscDualSpaceRegister("my_space", MyPetscDualSpaceCreate); 8820cf1dd8SToby Isaac .ve 8920cf1dd8SToby Isaac 9020cf1dd8SToby Isaac Then, your PetscDualSpace type can be chosen with the procedural interface via 9120cf1dd8SToby Isaac .vb 9220cf1dd8SToby Isaac PetscDualSpaceCreate(MPI_Comm, PetscDualSpace *); 9320cf1dd8SToby Isaac PetscDualSpaceSetType(PetscDualSpace, "my_dual_space"); 9420cf1dd8SToby Isaac .ve 9520cf1dd8SToby Isaac or at runtime via the option 9620cf1dd8SToby Isaac .vb 9720cf1dd8SToby Isaac -petscdualspace_type my_dual_space 9820cf1dd8SToby Isaac .ve 9920cf1dd8SToby Isaac 10020cf1dd8SToby Isaac Level: advanced 10120cf1dd8SToby Isaac 102db781477SPatrick Sanan .seealso: `PetscDualSpaceRegisterAll()`, `PetscDualSpaceRegisterDestroy()` 10320cf1dd8SToby Isaac 10420cf1dd8SToby Isaac @*/ 1059371c9d4SSatish Balay PetscErrorCode PetscDualSpaceRegister(const char sname[], PetscErrorCode (*function)(PetscDualSpace)) { 10620cf1dd8SToby Isaac PetscFunctionBegin; 1079566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&PetscDualSpaceList, sname, function)); 10820cf1dd8SToby Isaac PetscFunctionReturn(0); 10920cf1dd8SToby Isaac } 11020cf1dd8SToby Isaac 11120cf1dd8SToby Isaac /*@C 11220cf1dd8SToby Isaac PetscDualSpaceSetType - Builds a particular PetscDualSpace 11320cf1dd8SToby Isaac 114d083f849SBarry Smith Collective on sp 11520cf1dd8SToby Isaac 11620cf1dd8SToby Isaac Input Parameters: 11720cf1dd8SToby Isaac + sp - The PetscDualSpace object 11820cf1dd8SToby Isaac - name - The kind of space 11920cf1dd8SToby Isaac 12020cf1dd8SToby Isaac Options Database Key: 12120cf1dd8SToby Isaac . -petscdualspace_type <type> - Sets the PetscDualSpace type; use -help for a list of available types 12220cf1dd8SToby Isaac 12320cf1dd8SToby Isaac Level: intermediate 12420cf1dd8SToby Isaac 125db781477SPatrick Sanan .seealso: `PetscDualSpaceGetType()`, `PetscDualSpaceCreate()` 12620cf1dd8SToby Isaac @*/ 1279371c9d4SSatish Balay PetscErrorCode PetscDualSpaceSetType(PetscDualSpace sp, PetscDualSpaceType name) { 12820cf1dd8SToby Isaac PetscErrorCode (*r)(PetscDualSpace); 12920cf1dd8SToby Isaac PetscBool match; 13020cf1dd8SToby Isaac 13120cf1dd8SToby Isaac PetscFunctionBegin; 13220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)sp, name, &match)); 13420cf1dd8SToby Isaac if (match) PetscFunctionReturn(0); 13520cf1dd8SToby Isaac 1369566063dSJacob Faibussowitsch if (!PetscDualSpaceRegisterAllCalled) PetscCall(PetscDualSpaceRegisterAll()); 1379566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(PetscDualSpaceList, name, &r)); 13828b400f6SJacob Faibussowitsch PetscCheck(r, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDualSpace type: %s", name); 13920cf1dd8SToby Isaac 140dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, destroy); 14120cf1dd8SToby Isaac sp->ops->destroy = NULL; 142dbbe0bcdSBarry Smith 1439566063dSJacob Faibussowitsch PetscCall((*r)(sp)); 1449566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)sp, name)); 14520cf1dd8SToby Isaac PetscFunctionReturn(0); 14620cf1dd8SToby Isaac } 14720cf1dd8SToby Isaac 14820cf1dd8SToby Isaac /*@C 14920cf1dd8SToby Isaac PetscDualSpaceGetType - Gets the PetscDualSpace type name (as a string) from the object. 15020cf1dd8SToby Isaac 15120cf1dd8SToby Isaac Not Collective 15220cf1dd8SToby Isaac 15320cf1dd8SToby Isaac Input Parameter: 15420cf1dd8SToby Isaac . sp - The PetscDualSpace 15520cf1dd8SToby Isaac 15620cf1dd8SToby Isaac Output Parameter: 15720cf1dd8SToby Isaac . name - The PetscDualSpace type name 15820cf1dd8SToby Isaac 15920cf1dd8SToby Isaac Level: intermediate 16020cf1dd8SToby Isaac 161db781477SPatrick Sanan .seealso: `PetscDualSpaceSetType()`, `PetscDualSpaceCreate()` 16220cf1dd8SToby Isaac @*/ 1639371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetType(PetscDualSpace sp, PetscDualSpaceType *name) { 16420cf1dd8SToby Isaac PetscFunctionBegin; 16520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 16620cf1dd8SToby Isaac PetscValidPointer(name, 2); 167*48a46eb9SPierre Jolivet if (!PetscDualSpaceRegisterAllCalled) PetscCall(PetscDualSpaceRegisterAll()); 16820cf1dd8SToby Isaac *name = ((PetscObject)sp)->type_name; 16920cf1dd8SToby Isaac PetscFunctionReturn(0); 17020cf1dd8SToby Isaac } 17120cf1dd8SToby Isaac 1729371c9d4SSatish Balay static PetscErrorCode PetscDualSpaceView_ASCII(PetscDualSpace sp, PetscViewer v) { 173221d6281SMatthew G. Knepley PetscViewerFormat format; 174221d6281SMatthew G. Knepley PetscInt pdim, f; 175221d6281SMatthew G. Knepley 176221d6281SMatthew G. Knepley PetscFunctionBegin; 1779566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &pdim)); 1789566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)sp, v)); 1799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 180b4457527SToby Isaac if (sp->k) { 18163a3b9bcSJacob 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)); 182b4457527SToby Isaac } else { 18363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual space with %" PetscInt_FMT " components, size %" PetscInt_FMT "\n", sp->Nc, pdim)); 184b4457527SToby Isaac } 185dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, view, v); 1869566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(v, &format)); 187221d6281SMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 189221d6281SMatthew G. Knepley for (f = 0; f < pdim; ++f) { 19063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual basis vector %" PetscInt_FMT "\n", f)); 1919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 1929566063dSJacob Faibussowitsch PetscCall(PetscQuadratureView(sp->functional[f], v)); 1939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 194221d6281SMatthew G. Knepley } 1959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 196221d6281SMatthew G. Knepley } 1979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 198221d6281SMatthew G. Knepley PetscFunctionReturn(0); 199221d6281SMatthew G. Knepley } 200221d6281SMatthew G. Knepley 201fe2efc57SMark /*@C 202fe2efc57SMark PetscDualSpaceViewFromOptions - View from Options 203fe2efc57SMark 204fe2efc57SMark Collective on PetscDualSpace 205fe2efc57SMark 206fe2efc57SMark Input Parameters: 207fe2efc57SMark + A - the PetscDualSpace object 208736c3998SJose E. Roman . obj - Optional object, proivides prefix 209736c3998SJose E. Roman - name - command line option 210fe2efc57SMark 211fe2efc57SMark Level: intermediate 212db781477SPatrick Sanan .seealso: `PetscDualSpace`, `PetscDualSpaceView()`, `PetscObjectViewFromOptions()`, `PetscDualSpaceCreate()` 213fe2efc57SMark @*/ 2149371c9d4SSatish Balay PetscErrorCode PetscDualSpaceViewFromOptions(PetscDualSpace A, PetscObject obj, const char name[]) { 215fe2efc57SMark PetscFunctionBegin; 216fe2efc57SMark PetscValidHeaderSpecific(A, PETSCDUALSPACE_CLASSID, 1); 2179566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 218fe2efc57SMark PetscFunctionReturn(0); 219fe2efc57SMark } 220fe2efc57SMark 22120cf1dd8SToby Isaac /*@ 22220cf1dd8SToby Isaac PetscDualSpaceView - Views a PetscDualSpace 22320cf1dd8SToby Isaac 224d083f849SBarry Smith Collective on sp 22520cf1dd8SToby Isaac 226d8d19677SJose E. Roman Input Parameters: 22720cf1dd8SToby Isaac + sp - the PetscDualSpace object to view 22820cf1dd8SToby Isaac - v - the viewer 22920cf1dd8SToby Isaac 230a4ce7ad1SMatthew G. Knepley Level: beginner 23120cf1dd8SToby Isaac 232db781477SPatrick Sanan .seealso `PetscDualSpaceDestroy()`, `PetscDualSpace` 23320cf1dd8SToby Isaac @*/ 2349371c9d4SSatish Balay PetscErrorCode PetscDualSpaceView(PetscDualSpace sp, PetscViewer v) { 235d9bac1caSLisandro Dalcin PetscBool iascii; 23620cf1dd8SToby Isaac 23720cf1dd8SToby Isaac PetscFunctionBegin; 23820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 239d9bac1caSLisandro Dalcin if (v) PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2); 2409566063dSJacob Faibussowitsch if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sp), &v)); 2419566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii)); 2429566063dSJacob Faibussowitsch if (iascii) PetscCall(PetscDualSpaceView_ASCII(sp, v)); 24320cf1dd8SToby Isaac PetscFunctionReturn(0); 24420cf1dd8SToby Isaac } 24520cf1dd8SToby Isaac 24620cf1dd8SToby Isaac /*@ 24720cf1dd8SToby Isaac PetscDualSpaceSetFromOptions - sets parameters in a PetscDualSpace from the options database 24820cf1dd8SToby Isaac 249d083f849SBarry Smith Collective on sp 25020cf1dd8SToby Isaac 25120cf1dd8SToby Isaac Input Parameter: 25220cf1dd8SToby Isaac . sp - the PetscDualSpace object to set options for 25320cf1dd8SToby Isaac 25420cf1dd8SToby Isaac Options Database: 2558f2aacc6SMatthew G. Knepley + -petscdualspace_order <order> - the approximation order of the space 256fe36a153SMatthew G. Knepley . -petscdualspace_form_degree <deg> - the form degree, say 0 for point evaluations, or 2 for area integrals 2578f2aacc6SMatthew G. Knepley . -petscdualspace_components <c> - the number of components, say d for a vector field 2588f2aacc6SMatthew G. Knepley - -petscdualspace_refcell <celltype> - Reference cell type name 25920cf1dd8SToby Isaac 260a4ce7ad1SMatthew G. Knepley Level: intermediate 26120cf1dd8SToby Isaac 262db781477SPatrick Sanan .seealso `PetscDualSpaceView()`, `PetscDualSpace`, `PetscObjectSetFromOptions()` 26320cf1dd8SToby Isaac @*/ 2649371c9d4SSatish Balay PetscErrorCode PetscDualSpaceSetFromOptions(PetscDualSpace sp) { 2652df84da0SMatthew G. Knepley DMPolytopeType refCell = DM_POLYTOPE_TRIANGLE; 26620cf1dd8SToby Isaac const char *defaultType; 26720cf1dd8SToby Isaac char name[256]; 268f783ec47SMatthew G. Knepley PetscBool flg; 26920cf1dd8SToby Isaac 27020cf1dd8SToby Isaac PetscFunctionBegin; 27120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 27220cf1dd8SToby Isaac if (!((PetscObject)sp)->type_name) { 27320cf1dd8SToby Isaac defaultType = PETSCDUALSPACELAGRANGE; 27420cf1dd8SToby Isaac } else { 27520cf1dd8SToby Isaac defaultType = ((PetscObject)sp)->type_name; 27620cf1dd8SToby Isaac } 2779566063dSJacob Faibussowitsch if (!PetscSpaceRegisterAllCalled) PetscCall(PetscSpaceRegisterAll()); 27820cf1dd8SToby Isaac 279d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)sp); 2809566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-petscdualspace_type", "Dual space", "PetscDualSpaceSetType", PetscDualSpaceList, defaultType, name, 256, &flg)); 28120cf1dd8SToby Isaac if (flg) { 2829566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, name)); 28320cf1dd8SToby Isaac } else if (!((PetscObject)sp)->type_name) { 2849566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, defaultType)); 28520cf1dd8SToby Isaac } 2869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_order", "The approximation order", "PetscDualSpaceSetOrder", sp->order, &sp->order, NULL, 0)); 2879566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-petscdualspace_form_degree", "The form degree of the dofs", "PetscDualSpaceSetFormDegree", sp->k, &sp->k, NULL)); 2889566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_components", "The number of components", "PetscDualSpaceSetNumComponents", sp->Nc, &sp->Nc, NULL, 1)); 289dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, setfromoptions, PetscOptionsObject); 2909566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-petscdualspace_refcell", "Reference cell shape", "PetscDualSpaceSetReferenceCell", DMPolytopeTypes, (PetscEnum)refCell, (PetscEnum *)&refCell, &flg)); 291063ee4adSMatthew G. Knepley if (flg) { 292063ee4adSMatthew G. Knepley DM K; 293063ee4adSMatthew G. Knepley 2949566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, refCell, &K)); 2959566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(sp, K)); 2969566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 297063ee4adSMatthew G. Knepley } 298063ee4adSMatthew G. Knepley 29920cf1dd8SToby Isaac /* process any options handlers added with PetscObjectAddOptionsHandler() */ 300dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)sp, PetscOptionsObject)); 301d0609cedSBarry Smith PetscOptionsEnd(); 302063ee4adSMatthew G. Knepley sp->setfromoptionscalled = PETSC_TRUE; 30320cf1dd8SToby Isaac PetscFunctionReturn(0); 30420cf1dd8SToby Isaac } 30520cf1dd8SToby Isaac 30620cf1dd8SToby Isaac /*@ 30720cf1dd8SToby Isaac PetscDualSpaceSetUp - Construct a basis for the PetscDualSpace 30820cf1dd8SToby Isaac 309d083f849SBarry Smith Collective on sp 31020cf1dd8SToby Isaac 31120cf1dd8SToby Isaac Input Parameter: 31220cf1dd8SToby Isaac . sp - the PetscDualSpace object to setup 31320cf1dd8SToby Isaac 314a4ce7ad1SMatthew G. Knepley Level: intermediate 31520cf1dd8SToby Isaac 316db781477SPatrick Sanan .seealso `PetscDualSpaceView()`, `PetscDualSpaceDestroy()`, `PetscDualSpace` 31720cf1dd8SToby Isaac @*/ 3189371c9d4SSatish Balay PetscErrorCode PetscDualSpaceSetUp(PetscDualSpace sp) { 31920cf1dd8SToby Isaac PetscFunctionBegin; 32020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 32120cf1dd8SToby Isaac if (sp->setupcalled) PetscFunctionReturn(0); 3229566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 32320cf1dd8SToby Isaac sp->setupcalled = PETSC_TRUE; 324dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, setup); 3259566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 3269566063dSJacob Faibussowitsch if (sp->setfromoptionscalled) PetscCall(PetscDualSpaceViewFromOptions(sp, NULL, "-petscdualspace_view")); 32720cf1dd8SToby Isaac PetscFunctionReturn(0); 32820cf1dd8SToby Isaac } 32920cf1dd8SToby Isaac 3309371c9d4SSatish Balay static PetscErrorCode PetscDualSpaceClearDMData_Internal(PetscDualSpace sp, DM dm) { 331b4457527SToby Isaac PetscInt pStart = -1, pEnd = -1, depth = -1; 332b4457527SToby Isaac 333b4457527SToby Isaac PetscFunctionBegin; 334b4457527SToby Isaac if (!dm) PetscFunctionReturn(0); 3359566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 337b4457527SToby Isaac 338b4457527SToby Isaac if (sp->pointSpaces) { 339b4457527SToby Isaac PetscInt i; 340b4457527SToby Isaac 341*48a46eb9SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) PetscCall(PetscDualSpaceDestroy(&(sp->pointSpaces[i]))); 342b4457527SToby Isaac } 3439566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->pointSpaces)); 344b4457527SToby Isaac 345b4457527SToby Isaac if (sp->heightSpaces) { 346b4457527SToby Isaac PetscInt i; 347b4457527SToby Isaac 348*48a46eb9SPierre Jolivet for (i = 0; i <= depth; i++) PetscCall(PetscDualSpaceDestroy(&(sp->heightSpaces[i]))); 349b4457527SToby Isaac } 3509566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->heightSpaces)); 351b4457527SToby Isaac 3529566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(sp->pointSection))); 3539566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->intNodes))); 3549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->intDofValues))); 3559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->intNodeValues))); 3569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->intMat))); 3579566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->allNodes))); 3589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->allDofValues))); 3599566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->allNodeValues))); 3609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->allMat))); 3619566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->numDof)); 362b4457527SToby Isaac PetscFunctionReturn(0); 363b4457527SToby Isaac } 364b4457527SToby Isaac 36520cf1dd8SToby Isaac /*@ 36620cf1dd8SToby Isaac PetscDualSpaceDestroy - Destroys a PetscDualSpace object 36720cf1dd8SToby Isaac 368d083f849SBarry Smith Collective on sp 36920cf1dd8SToby Isaac 37020cf1dd8SToby Isaac Input Parameter: 37120cf1dd8SToby Isaac . sp - the PetscDualSpace object to destroy 37220cf1dd8SToby Isaac 373a4ce7ad1SMatthew G. Knepley Level: beginner 37420cf1dd8SToby Isaac 375db781477SPatrick Sanan .seealso `PetscDualSpaceView()`, `PetscDualSpace()`, `PetscDualSpaceCreate()` 37620cf1dd8SToby Isaac @*/ 3779371c9d4SSatish Balay PetscErrorCode PetscDualSpaceDestroy(PetscDualSpace *sp) { 37820cf1dd8SToby Isaac PetscInt dim, f; 379b4457527SToby Isaac DM dm; 38020cf1dd8SToby Isaac 38120cf1dd8SToby Isaac PetscFunctionBegin; 38220cf1dd8SToby Isaac if (!*sp) PetscFunctionReturn(0); 38320cf1dd8SToby Isaac PetscValidHeaderSpecific((*sp), PETSCDUALSPACE_CLASSID, 1); 38420cf1dd8SToby Isaac 3859371c9d4SSatish Balay if (--((PetscObject)(*sp))->refct > 0) { 3869371c9d4SSatish Balay *sp = NULL; 3879371c9d4SSatish Balay PetscFunctionReturn(0); 3889371c9d4SSatish Balay } 38920cf1dd8SToby Isaac ((PetscObject)(*sp))->refct = 0; 39020cf1dd8SToby Isaac 3919566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(*sp, &dim)); 392b4457527SToby Isaac dm = (*sp)->dm; 393b4457527SToby Isaac 394dbbe0bcdSBarry Smith PetscTryTypeMethod((*sp), destroy); 3959566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceClearDMData_Internal(*sp, dm)); 396b4457527SToby Isaac 397*48a46eb9SPierre Jolivet for (f = 0; f < dim; ++f) PetscCall(PetscQuadratureDestroy(&(*sp)->functional[f])); 3989566063dSJacob Faibussowitsch PetscCall(PetscFree((*sp)->functional)); 3999566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*sp)->dm)); 4009566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(sp)); 40120cf1dd8SToby Isaac PetscFunctionReturn(0); 40220cf1dd8SToby Isaac } 40320cf1dd8SToby Isaac 40420cf1dd8SToby Isaac /*@ 40520cf1dd8SToby Isaac PetscDualSpaceCreate - Creates an empty PetscDualSpace object. The type can then be set with PetscDualSpaceSetType(). 40620cf1dd8SToby Isaac 407d083f849SBarry Smith Collective 40820cf1dd8SToby Isaac 40920cf1dd8SToby Isaac Input Parameter: 41020cf1dd8SToby Isaac . comm - The communicator for the PetscDualSpace object 41120cf1dd8SToby Isaac 41220cf1dd8SToby Isaac Output Parameter: 41320cf1dd8SToby Isaac . sp - The PetscDualSpace object 41420cf1dd8SToby Isaac 41520cf1dd8SToby Isaac Level: beginner 41620cf1dd8SToby Isaac 417db781477SPatrick Sanan .seealso: `PetscDualSpaceSetType()`, `PETSCDUALSPACELAGRANGE` 41820cf1dd8SToby Isaac @*/ 4199371c9d4SSatish Balay PetscErrorCode PetscDualSpaceCreate(MPI_Comm comm, PetscDualSpace *sp) { 42020cf1dd8SToby Isaac PetscDualSpace s; 42120cf1dd8SToby Isaac 42220cf1dd8SToby Isaac PetscFunctionBegin; 42320cf1dd8SToby Isaac PetscValidPointer(sp, 2); 4249566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(FECitation, &FEcite)); 42520cf1dd8SToby Isaac *sp = NULL; 4269566063dSJacob Faibussowitsch PetscCall(PetscFEInitializePackage()); 42720cf1dd8SToby Isaac 4289566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(s, PETSCDUALSPACE_CLASSID, "PetscDualSpace", "Dual Space", "PetscDualSpace", comm, PetscDualSpaceDestroy, PetscDualSpaceView)); 42920cf1dd8SToby Isaac 43020cf1dd8SToby Isaac s->order = 0; 43120cf1dd8SToby Isaac s->Nc = 1; 4324bee2e38SMatthew G. Knepley s->k = 0; 433b4457527SToby Isaac s->spdim = -1; 434b4457527SToby Isaac s->spintdim = -1; 435b4457527SToby Isaac s->uniform = PETSC_TRUE; 43620cf1dd8SToby Isaac s->setupcalled = PETSC_FALSE; 43720cf1dd8SToby Isaac 43820cf1dd8SToby Isaac *sp = s; 43920cf1dd8SToby Isaac PetscFunctionReturn(0); 44020cf1dd8SToby Isaac } 44120cf1dd8SToby Isaac 44220cf1dd8SToby Isaac /*@ 44320cf1dd8SToby Isaac PetscDualSpaceDuplicate - Creates a duplicate PetscDualSpace object, however it is not setup. 44420cf1dd8SToby Isaac 445d083f849SBarry Smith Collective on sp 44620cf1dd8SToby Isaac 44720cf1dd8SToby Isaac Input Parameter: 44820cf1dd8SToby Isaac . sp - The original PetscDualSpace 44920cf1dd8SToby Isaac 45020cf1dd8SToby Isaac Output Parameter: 45120cf1dd8SToby Isaac . spNew - The duplicate PetscDualSpace 45220cf1dd8SToby Isaac 45320cf1dd8SToby Isaac Level: beginner 45420cf1dd8SToby Isaac 455db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `PetscDualSpaceSetType()` 45620cf1dd8SToby Isaac @*/ 4579371c9d4SSatish Balay PetscErrorCode PetscDualSpaceDuplicate(PetscDualSpace sp, PetscDualSpace *spNew) { 458b4457527SToby Isaac DM dm; 459b4457527SToby Isaac PetscDualSpaceType type; 460b4457527SToby Isaac const char *name; 46120cf1dd8SToby Isaac 46220cf1dd8SToby Isaac PetscFunctionBegin; 46320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 46420cf1dd8SToby Isaac PetscValidPointer(spNew, 2); 4659566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(PetscObjectComm((PetscObject)sp), spNew)); 4669566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name)); 4679566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*spNew, name)); 4689566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetType(sp, &type)); 4699566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(*spNew, type)); 4709566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 4719566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(*spNew, dm)); 472b4457527SToby Isaac 473b4457527SToby Isaac (*spNew)->order = sp->order; 474b4457527SToby Isaac (*spNew)->k = sp->k; 475b4457527SToby Isaac (*spNew)->Nc = sp->Nc; 476b4457527SToby Isaac (*spNew)->uniform = sp->uniform; 477dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, duplicate, *spNew); 47820cf1dd8SToby Isaac PetscFunctionReturn(0); 47920cf1dd8SToby Isaac } 48020cf1dd8SToby Isaac 48120cf1dd8SToby Isaac /*@ 48220cf1dd8SToby Isaac PetscDualSpaceGetDM - Get the DM representing the reference cell 48320cf1dd8SToby Isaac 48420cf1dd8SToby Isaac Not collective 48520cf1dd8SToby Isaac 48620cf1dd8SToby Isaac Input Parameter: 48720cf1dd8SToby Isaac . sp - The PetscDualSpace 48820cf1dd8SToby Isaac 48920cf1dd8SToby Isaac Output Parameter: 49020cf1dd8SToby Isaac . dm - The reference cell 49120cf1dd8SToby Isaac 49220cf1dd8SToby Isaac Level: intermediate 49320cf1dd8SToby Isaac 494db781477SPatrick Sanan .seealso: `PetscDualSpaceSetDM()`, `PetscDualSpaceCreate()` 49520cf1dd8SToby Isaac @*/ 4969371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetDM(PetscDualSpace sp, DM *dm) { 49720cf1dd8SToby Isaac PetscFunctionBegin; 49820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 49920cf1dd8SToby Isaac PetscValidPointer(dm, 2); 50020cf1dd8SToby Isaac *dm = sp->dm; 50120cf1dd8SToby Isaac PetscFunctionReturn(0); 50220cf1dd8SToby Isaac } 50320cf1dd8SToby Isaac 50420cf1dd8SToby Isaac /*@ 50520cf1dd8SToby Isaac PetscDualSpaceSetDM - Get the DM representing the reference cell 50620cf1dd8SToby Isaac 50720cf1dd8SToby Isaac Not collective 50820cf1dd8SToby Isaac 50920cf1dd8SToby Isaac Input Parameters: 51020cf1dd8SToby Isaac + sp - The PetscDualSpace 51120cf1dd8SToby Isaac - dm - The reference cell 51220cf1dd8SToby Isaac 51320cf1dd8SToby Isaac Level: intermediate 51420cf1dd8SToby Isaac 515db781477SPatrick Sanan .seealso: `PetscDualSpaceGetDM()`, `PetscDualSpaceCreate()` 51620cf1dd8SToby Isaac @*/ 5179371c9d4SSatish Balay PetscErrorCode PetscDualSpaceSetDM(PetscDualSpace sp, DM dm) { 51820cf1dd8SToby Isaac PetscFunctionBegin; 51920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 52020cf1dd8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 52128b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change DM after dualspace is set up"); 5229566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 523*48a46eb9SPierre Jolivet if (sp->dm && sp->dm != dm) PetscCall(PetscDualSpaceClearDMData_Internal(sp, sp->dm)); 5249566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sp->dm)); 52520cf1dd8SToby Isaac sp->dm = dm; 52620cf1dd8SToby Isaac PetscFunctionReturn(0); 52720cf1dd8SToby Isaac } 52820cf1dd8SToby Isaac 52920cf1dd8SToby Isaac /*@ 53020cf1dd8SToby Isaac PetscDualSpaceGetOrder - Get the order of the dual space 53120cf1dd8SToby Isaac 53220cf1dd8SToby Isaac Not collective 53320cf1dd8SToby Isaac 53420cf1dd8SToby Isaac Input Parameter: 53520cf1dd8SToby Isaac . sp - The PetscDualSpace 53620cf1dd8SToby Isaac 53720cf1dd8SToby Isaac Output Parameter: 53820cf1dd8SToby Isaac . order - The order 53920cf1dd8SToby Isaac 54020cf1dd8SToby Isaac Level: intermediate 54120cf1dd8SToby Isaac 542db781477SPatrick Sanan .seealso: `PetscDualSpaceSetOrder()`, `PetscDualSpaceCreate()` 54320cf1dd8SToby Isaac @*/ 5449371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetOrder(PetscDualSpace sp, PetscInt *order) { 54520cf1dd8SToby Isaac PetscFunctionBegin; 54620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 547dadcf809SJacob Faibussowitsch PetscValidIntPointer(order, 2); 54820cf1dd8SToby Isaac *order = sp->order; 54920cf1dd8SToby Isaac PetscFunctionReturn(0); 55020cf1dd8SToby Isaac } 55120cf1dd8SToby Isaac 55220cf1dd8SToby Isaac /*@ 55320cf1dd8SToby Isaac PetscDualSpaceSetOrder - Set the order of the dual space 55420cf1dd8SToby Isaac 55520cf1dd8SToby Isaac Not collective 55620cf1dd8SToby Isaac 55720cf1dd8SToby Isaac Input Parameters: 55820cf1dd8SToby Isaac + sp - The PetscDualSpace 55920cf1dd8SToby Isaac - order - The order 56020cf1dd8SToby Isaac 56120cf1dd8SToby Isaac Level: intermediate 56220cf1dd8SToby Isaac 563db781477SPatrick Sanan .seealso: `PetscDualSpaceGetOrder()`, `PetscDualSpaceCreate()` 56420cf1dd8SToby Isaac @*/ 5659371c9d4SSatish Balay PetscErrorCode PetscDualSpaceSetOrder(PetscDualSpace sp, PetscInt order) { 56620cf1dd8SToby Isaac PetscFunctionBegin; 56720cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 56828b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change order after dualspace is set up"); 56920cf1dd8SToby Isaac sp->order = order; 57020cf1dd8SToby Isaac PetscFunctionReturn(0); 57120cf1dd8SToby Isaac } 57220cf1dd8SToby Isaac 57320cf1dd8SToby Isaac /*@ 57420cf1dd8SToby Isaac PetscDualSpaceGetNumComponents - Return the number of components for this space 57520cf1dd8SToby Isaac 57620cf1dd8SToby Isaac Input Parameter: 57720cf1dd8SToby Isaac . sp - The PetscDualSpace 57820cf1dd8SToby Isaac 57920cf1dd8SToby Isaac Output Parameter: 58020cf1dd8SToby Isaac . Nc - The number of components 58120cf1dd8SToby Isaac 58220cf1dd8SToby Isaac Note: A vector space, for example, will have d components, where d is the spatial dimension 58320cf1dd8SToby Isaac 58420cf1dd8SToby Isaac Level: intermediate 58520cf1dd8SToby Isaac 586db781477SPatrick Sanan .seealso: `PetscDualSpaceSetNumComponents()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 58720cf1dd8SToby Isaac @*/ 5889371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetNumComponents(PetscDualSpace sp, PetscInt *Nc) { 58920cf1dd8SToby Isaac PetscFunctionBegin; 59020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 591dadcf809SJacob Faibussowitsch PetscValidIntPointer(Nc, 2); 59220cf1dd8SToby Isaac *Nc = sp->Nc; 59320cf1dd8SToby Isaac PetscFunctionReturn(0); 59420cf1dd8SToby Isaac } 59520cf1dd8SToby Isaac 59620cf1dd8SToby Isaac /*@ 59720cf1dd8SToby Isaac PetscDualSpaceSetNumComponents - Set the number of components for this space 59820cf1dd8SToby Isaac 59920cf1dd8SToby Isaac Input Parameters: 60020cf1dd8SToby Isaac + sp - The PetscDualSpace 60120cf1dd8SToby Isaac - order - The number of components 60220cf1dd8SToby Isaac 60320cf1dd8SToby Isaac Level: intermediate 60420cf1dd8SToby Isaac 605db781477SPatrick Sanan .seealso: `PetscDualSpaceGetNumComponents()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 60620cf1dd8SToby Isaac @*/ 6079371c9d4SSatish Balay PetscErrorCode PetscDualSpaceSetNumComponents(PetscDualSpace sp, PetscInt Nc) { 60820cf1dd8SToby Isaac PetscFunctionBegin; 60920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 61028b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 61120cf1dd8SToby Isaac sp->Nc = Nc; 61220cf1dd8SToby Isaac PetscFunctionReturn(0); 61320cf1dd8SToby Isaac } 61420cf1dd8SToby Isaac 61520cf1dd8SToby Isaac /*@ 61620cf1dd8SToby Isaac PetscDualSpaceGetFunctional - Get the i-th basis functional in the dual space 61720cf1dd8SToby Isaac 61820cf1dd8SToby Isaac Not collective 61920cf1dd8SToby Isaac 62020cf1dd8SToby Isaac Input Parameters: 62120cf1dd8SToby Isaac + sp - The PetscDualSpace 62220cf1dd8SToby Isaac - i - The basis number 62320cf1dd8SToby Isaac 62420cf1dd8SToby Isaac Output Parameter: 62520cf1dd8SToby Isaac . functional - The basis functional 62620cf1dd8SToby Isaac 62720cf1dd8SToby Isaac Level: intermediate 62820cf1dd8SToby Isaac 629db781477SPatrick Sanan .seealso: `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()` 63020cf1dd8SToby Isaac @*/ 6319371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetFunctional(PetscDualSpace sp, PetscInt i, PetscQuadrature *functional) { 63220cf1dd8SToby Isaac PetscInt dim; 63320cf1dd8SToby Isaac 63420cf1dd8SToby Isaac PetscFunctionBegin; 63520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 63620cf1dd8SToby Isaac PetscValidPointer(functional, 3); 6379566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &dim)); 63863a3b9bcSJacob 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); 63920cf1dd8SToby Isaac *functional = sp->functional[i]; 64020cf1dd8SToby Isaac PetscFunctionReturn(0); 64120cf1dd8SToby Isaac } 64220cf1dd8SToby Isaac 64320cf1dd8SToby Isaac /*@ 64420cf1dd8SToby Isaac PetscDualSpaceGetDimension - Get the dimension of the dual space, i.e. the number of basis functionals 64520cf1dd8SToby Isaac 64620cf1dd8SToby Isaac Not collective 64720cf1dd8SToby Isaac 64820cf1dd8SToby Isaac Input Parameter: 64920cf1dd8SToby Isaac . sp - The PetscDualSpace 65020cf1dd8SToby Isaac 65120cf1dd8SToby Isaac Output Parameter: 65220cf1dd8SToby Isaac . dim - The dimension 65320cf1dd8SToby Isaac 65420cf1dd8SToby Isaac Level: intermediate 65520cf1dd8SToby Isaac 656db781477SPatrick Sanan .seealso: `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 65720cf1dd8SToby Isaac @*/ 6589371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetDimension(PetscDualSpace sp, PetscInt *dim) { 65920cf1dd8SToby Isaac PetscFunctionBegin; 66020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 661dadcf809SJacob Faibussowitsch PetscValidIntPointer(dim, 2); 662b4457527SToby Isaac if (sp->spdim < 0) { 663b4457527SToby Isaac PetscSection section; 664b4457527SToby Isaac 6659566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 666b4457527SToby Isaac if (section) { 6679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &(sp->spdim))); 668b4457527SToby Isaac } else sp->spdim = 0; 669b4457527SToby Isaac } 670b4457527SToby Isaac *dim = sp->spdim; 67120cf1dd8SToby Isaac PetscFunctionReturn(0); 67220cf1dd8SToby Isaac } 67320cf1dd8SToby Isaac 674b4457527SToby Isaac /*@ 675b4457527SToby 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 676b4457527SToby Isaac 677b4457527SToby Isaac Not collective 678b4457527SToby Isaac 679b4457527SToby Isaac Input Parameter: 680b4457527SToby Isaac . sp - The PetscDualSpace 681b4457527SToby Isaac 682b4457527SToby Isaac Output Parameter: 683b4457527SToby Isaac . dim - The dimension 684b4457527SToby Isaac 685b4457527SToby Isaac Level: intermediate 686b4457527SToby Isaac 687db781477SPatrick Sanan .seealso: `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 688b4457527SToby Isaac @*/ 6899371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetInteriorDimension(PetscDualSpace sp, PetscInt *intdim) { 690b4457527SToby Isaac PetscFunctionBegin; 691b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 692dadcf809SJacob Faibussowitsch PetscValidIntPointer(intdim, 2); 693b4457527SToby Isaac if (sp->spintdim < 0) { 694b4457527SToby Isaac PetscSection section; 695b4457527SToby Isaac 6969566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 697b4457527SToby Isaac if (section) { 6989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &(sp->spintdim))); 699b4457527SToby Isaac } else sp->spintdim = 0; 700b4457527SToby Isaac } 701b4457527SToby Isaac *intdim = sp->spintdim; 702b4457527SToby Isaac PetscFunctionReturn(0); 703b4457527SToby Isaac } 704b4457527SToby Isaac 705b4457527SToby Isaac /*@ 706b4457527SToby Isaac PetscDualSpaceGetUniform - Whether this dual space is uniform 707b4457527SToby Isaac 708b4457527SToby Isaac Not collective 709b4457527SToby Isaac 710b4457527SToby Isaac Input Parameters: 711b4457527SToby Isaac . sp - A dual space 712b4457527SToby Isaac 713b4457527SToby Isaac Output Parameters: 714b4457527SToby Isaac . uniform - PETSC_TRUE if (a) the dual space is the same for each point in a stratum of the reference DMPlex, and 715b4457527SToby Isaac (b) every symmetry of each point in the reference DMPlex is also a symmetry of the point's dual space. 716b4457527SToby Isaac 717b4457527SToby Isaac Level: advanced 718b4457527SToby Isaac 719b4457527SToby Isaac Note: all of the usual spaces on simplex or tensor-product elements will be uniform, only reference cells 720b4457527SToby Isaac with non-uniform strata (like trianguar-prisms) or anisotropic hp dual spaces will not be uniform. 721b4457527SToby Isaac 722db781477SPatrick Sanan .seealso: `PetscDualSpaceGetPointSubspace()`, `PetscDualSpaceGetSymmetries()` 723b4457527SToby Isaac @*/ 7249371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetUniform(PetscDualSpace sp, PetscBool *uniform) { 725b4457527SToby Isaac PetscFunctionBegin; 726b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 727dadcf809SJacob Faibussowitsch PetscValidBoolPointer(uniform, 2); 728b4457527SToby Isaac *uniform = sp->uniform; 729b4457527SToby Isaac PetscFunctionReturn(0); 730b4457527SToby Isaac } 731b4457527SToby Isaac 73220cf1dd8SToby Isaac /*@C 73320cf1dd8SToby Isaac PetscDualSpaceGetNumDof - Get the number of degrees of freedom for each spatial (topological) dimension 73420cf1dd8SToby Isaac 73520cf1dd8SToby Isaac Not collective 73620cf1dd8SToby Isaac 73720cf1dd8SToby Isaac Input Parameter: 73820cf1dd8SToby Isaac . sp - The PetscDualSpace 73920cf1dd8SToby Isaac 74020cf1dd8SToby Isaac Output Parameter: 74120cf1dd8SToby Isaac . numDof - An array of length dim+1 which holds the number of dofs for each dimension 74220cf1dd8SToby Isaac 74320cf1dd8SToby Isaac Level: intermediate 74420cf1dd8SToby Isaac 745db781477SPatrick Sanan .seealso: `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 74620cf1dd8SToby Isaac @*/ 7479371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetNumDof(PetscDualSpace sp, const PetscInt **numDof) { 74820cf1dd8SToby Isaac PetscFunctionBegin; 74920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 75020cf1dd8SToby Isaac PetscValidPointer(numDof, 2); 75128b400f6SJacob 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"); 752b4457527SToby Isaac if (!sp->numDof) { 753b4457527SToby Isaac DM dm; 754b4457527SToby Isaac PetscInt depth, d; 755b4457527SToby Isaac PetscSection section; 756b4457527SToby Isaac 7579566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 7589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 7599566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth + 1, &(sp->numDof))); 7609566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 761b4457527SToby Isaac for (d = 0; d <= depth; d++) { 762b4457527SToby Isaac PetscInt dStart, dEnd; 763b4457527SToby Isaac 7649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 765b4457527SToby Isaac if (dEnd <= dStart) continue; 7669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, dStart, &(sp->numDof[d]))); 767b4457527SToby Isaac } 768b4457527SToby Isaac } 769b4457527SToby Isaac *numDof = sp->numDof; 77008401ef6SPierre Jolivet PetscCheck(*numDof, PetscObjectComm((PetscObject)sp), PETSC_ERR_LIB, "Empty numDof[] returned from dual space implementation"); 77120cf1dd8SToby Isaac PetscFunctionReturn(0); 77220cf1dd8SToby Isaac } 77320cf1dd8SToby Isaac 774b4457527SToby Isaac /* create the section of the right size and set a permutation for topological ordering */ 7759371c9d4SSatish Balay PetscErrorCode PetscDualSpaceSectionCreate_Internal(PetscDualSpace sp, PetscSection *topSection) { 776b4457527SToby Isaac DM dm; 777b4457527SToby Isaac PetscInt pStart, pEnd, cStart, cEnd, c, depth, count, i; 778b4457527SToby Isaac PetscInt *seen, *perm; 779b4457527SToby Isaac PetscSection section; 780b4457527SToby Isaac 781b4457527SToby Isaac PetscFunctionBegin; 782b4457527SToby Isaac dm = sp->dm; 7839566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion)); 7849566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 7859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 7869566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &seen)); 7879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &perm)); 7889566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 7899566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 790b4457527SToby Isaac for (c = cStart, count = 0; c < cEnd; c++) { 791b4457527SToby Isaac PetscInt closureSize = -1, e; 792b4457527SToby Isaac PetscInt *closure = NULL; 793b4457527SToby Isaac 794b4457527SToby Isaac perm[count++] = c; 795b4457527SToby Isaac seen[c - pStart] = 1; 7969566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 797b4457527SToby Isaac for (e = 0; e < closureSize; e++) { 798b4457527SToby Isaac PetscInt point = closure[2 * e]; 799b4457527SToby Isaac 800b4457527SToby Isaac if (seen[point - pStart]) continue; 801b4457527SToby Isaac perm[count++] = point; 802b4457527SToby Isaac seen[point - pStart] = 1; 803b4457527SToby Isaac } 8049566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 805b4457527SToby Isaac } 8061dca8a05SBarry Smith PetscCheck(count == pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad topological ordering"); 8079371c9d4SSatish Balay for (i = 0; i < pEnd - pStart; i++) 8089371c9d4SSatish Balay if (perm[i] != i) break; 809b4457527SToby Isaac if (i < pEnd - pStart) { 810b4457527SToby Isaac IS permIS; 811b4457527SToby Isaac 8129566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pEnd - pStart, perm, PETSC_OWN_POINTER, &permIS)); 8139566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(permIS)); 8149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(section, permIS)); 8159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS)); 816b4457527SToby Isaac } else { 8179566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 818b4457527SToby Isaac } 8199566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 820b4457527SToby Isaac *topSection = section; 821b4457527SToby Isaac PetscFunctionReturn(0); 822b4457527SToby Isaac } 823b4457527SToby Isaac 824b4457527SToby Isaac /* mark boundary points and set up */ 8259371c9d4SSatish Balay PetscErrorCode PetscDualSpaceSectionSetUp_Internal(PetscDualSpace sp, PetscSection section) { 826b4457527SToby Isaac DM dm; 827b4457527SToby Isaac DMLabel boundary; 828b4457527SToby Isaac PetscInt pStart, pEnd, p; 829b4457527SToby Isaac 830b4457527SToby Isaac PetscFunctionBegin; 831b4457527SToby Isaac dm = sp->dm; 8329566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "boundary", &boundary)); 8339566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 8349566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, 1, boundary)); 8359566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, boundary)); 8369566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 837b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 838b4457527SToby Isaac PetscInt bval; 839b4457527SToby Isaac 8409566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(boundary, p, &bval)); 841b4457527SToby Isaac if (bval == 1) { 842b4457527SToby Isaac PetscInt dof; 843b4457527SToby Isaac 8449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 8459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetConstraintDof(section, p, dof)); 846b4457527SToby Isaac } 847b4457527SToby Isaac } 8489566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&boundary)); 8499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 850b4457527SToby Isaac PetscFunctionReturn(0); 851b4457527SToby Isaac } 852b4457527SToby Isaac 853a4ce7ad1SMatthew G. Knepley /*@ 854b4457527SToby Isaac PetscDualSpaceGetSection - Create a PetscSection over the reference cell with the layout from this space 855a4ce7ad1SMatthew G. Knepley 856a4ce7ad1SMatthew G. Knepley Collective on sp 857a4ce7ad1SMatthew G. Knepley 858a4ce7ad1SMatthew G. Knepley Input Parameters: 859f0fc11ceSJed Brown . sp - The PetscDualSpace 860a4ce7ad1SMatthew G. Knepley 861a4ce7ad1SMatthew G. Knepley Output Parameter: 862a4ce7ad1SMatthew G. Knepley . section - The section 863a4ce7ad1SMatthew G. Knepley 864a4ce7ad1SMatthew G. Knepley Level: advanced 865a4ce7ad1SMatthew G. Knepley 866db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `DMPLEX` 867a4ce7ad1SMatthew G. Knepley @*/ 8689371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetSection(PetscDualSpace sp, PetscSection *section) { 869b4457527SToby Isaac PetscInt pStart, pEnd, p; 870b4457527SToby Isaac 871b4457527SToby Isaac PetscFunctionBegin; 87278f1d139SRomain Beucher if (!sp->dm) { 87378f1d139SRomain Beucher *section = NULL; 87478f1d139SRomain Beucher PetscFunctionReturn(0); 87578f1d139SRomain Beucher } 876b4457527SToby Isaac if (!sp->pointSection) { 877b4457527SToby Isaac /* mark the boundary */ 8789566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionCreate_Internal(sp, &(sp->pointSection))); 8799566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(sp->dm, &pStart, &pEnd)); 880b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 881b4457527SToby Isaac PetscDualSpace psp; 882b4457527SToby Isaac 8839566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, p, &psp)); 884b4457527SToby Isaac if (psp) { 885b4457527SToby Isaac PetscInt dof; 886b4457527SToby Isaac 8879566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorDimension(psp, &dof)); 8889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sp->pointSection, p, dof)); 889b4457527SToby Isaac } 890b4457527SToby Isaac } 8919566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionSetUp_Internal(sp, sp->pointSection)); 892b4457527SToby Isaac } 893b4457527SToby Isaac *section = sp->pointSection; 894b4457527SToby Isaac PetscFunctionReturn(0); 895b4457527SToby Isaac } 896b4457527SToby Isaac 897b4457527SToby Isaac /* this assumes that all of the point dual spaces store their interior dofs first, which is true when the point DMs 898b4457527SToby Isaac * have one cell */ 8999371c9d4SSatish Balay PetscErrorCode PetscDualSpacePushForwardSubspaces_Internal(PetscDualSpace sp, PetscInt sStart, PetscInt sEnd) { 900b4457527SToby Isaac PetscReal *sv0, *v0, *J; 901b4457527SToby Isaac PetscSection section; 902b4457527SToby Isaac PetscInt dim, s, k; 90320cf1dd8SToby Isaac DM dm; 90420cf1dd8SToby Isaac 90520cf1dd8SToby Isaac PetscFunctionBegin; 9069566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 9079566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9089566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 9099566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim, &sv0, dim * dim, &J)); 9109566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFormDegree(sp, &k)); 911b4457527SToby Isaac for (s = sStart; s < sEnd; s++) { 912b4457527SToby Isaac PetscReal detJ, hdetJ; 913b4457527SToby Isaac PetscDualSpace ssp; 914b4457527SToby Isaac PetscInt dof, off, f, sdim; 915b4457527SToby Isaac PetscInt i, j; 916b4457527SToby Isaac DM sdm; 91720cf1dd8SToby Isaac 9189566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, s, &ssp)); 919b4457527SToby Isaac if (!ssp) continue; 9209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, s, &dof)); 9219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, s, &off)); 922b4457527SToby Isaac /* get the first vertex of the reference cell */ 9239566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(ssp, &sdm)); 9249566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sdm, &sdim)); 9259566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(sdm, 0, sv0, NULL, NULL, &hdetJ)); 9269566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, s, v0, J, NULL, &detJ)); 927b4457527SToby Isaac /* compactify Jacobian */ 9289371c9d4SSatish Balay for (i = 0; i < dim; i++) 9299371c9d4SSatish Balay for (j = 0; j < sdim; j++) J[i * sdim + j] = J[i * dim + j]; 930b4457527SToby Isaac for (f = 0; f < dof; f++) { 931b4457527SToby Isaac PetscQuadrature fn; 93220cf1dd8SToby Isaac 9339566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(ssp, f, &fn)); 9349566063dSJacob Faibussowitsch PetscCall(PetscQuadraturePushForward(fn, dim, sv0, v0, J, k, &(sp->functional[off + f]))); 93520cf1dd8SToby Isaac } 93620cf1dd8SToby Isaac } 9379566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, sv0, J)); 93820cf1dd8SToby Isaac PetscFunctionReturn(0); 93920cf1dd8SToby Isaac } 94020cf1dd8SToby Isaac 94120cf1dd8SToby Isaac /*@C 94220cf1dd8SToby Isaac PetscDualSpaceApply - Apply a functional from the dual space basis to an input function 94320cf1dd8SToby Isaac 94420cf1dd8SToby Isaac Input Parameters: 94520cf1dd8SToby Isaac + sp - The PetscDualSpace object 94620cf1dd8SToby Isaac . f - The basis functional index 94720cf1dd8SToby Isaac . time - The time 94820cf1dd8SToby 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) 94920cf1dd8SToby Isaac . numComp - The number of components for the function 95020cf1dd8SToby Isaac . func - The input function 95120cf1dd8SToby Isaac - ctx - A context for the function 95220cf1dd8SToby Isaac 95320cf1dd8SToby Isaac Output Parameter: 95420cf1dd8SToby Isaac . value - numComp output values 95520cf1dd8SToby Isaac 95620cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 95720cf1dd8SToby Isaac 95820cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 95920cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 96020cf1dd8SToby Isaac 961a4ce7ad1SMatthew G. Knepley Level: beginner 96220cf1dd8SToby Isaac 963db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 96420cf1dd8SToby Isaac @*/ 9659371c9d4SSatish Balay PetscErrorCode PetscDualSpaceApply(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFEGeom *cgeom, PetscInt numComp, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void *ctx, PetscScalar *value) { 96620cf1dd8SToby Isaac PetscFunctionBegin; 96720cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 96820cf1dd8SToby Isaac PetscValidPointer(cgeom, 4); 969dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 970dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, apply, f, time, cgeom, numComp, func, ctx, value); 97120cf1dd8SToby Isaac PetscFunctionReturn(0); 97220cf1dd8SToby Isaac } 97320cf1dd8SToby Isaac 97420cf1dd8SToby Isaac /*@C 975b4457527SToby Isaac PetscDualSpaceApplyAll - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetAllData() 97620cf1dd8SToby Isaac 97720cf1dd8SToby Isaac Input Parameters: 97820cf1dd8SToby Isaac + sp - The PetscDualSpace object 979b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetAllData() 98020cf1dd8SToby Isaac 98120cf1dd8SToby Isaac Output Parameter: 98220cf1dd8SToby Isaac . spValue - The values of all dual space functionals 98320cf1dd8SToby Isaac 984a4ce7ad1SMatthew G. Knepley Level: beginner 98520cf1dd8SToby Isaac 986db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 98720cf1dd8SToby Isaac @*/ 9889371c9d4SSatish Balay PetscErrorCode PetscDualSpaceApplyAll(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) { 98920cf1dd8SToby Isaac PetscFunctionBegin; 99020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 991dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyall, pointEval, spValue); 99220cf1dd8SToby Isaac PetscFunctionReturn(0); 99320cf1dd8SToby Isaac } 99420cf1dd8SToby Isaac 99520cf1dd8SToby Isaac /*@C 996b4457527SToby Isaac PetscDualSpaceApplyInterior - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetInteriorData() 997b4457527SToby Isaac 998b4457527SToby Isaac Input Parameters: 999b4457527SToby Isaac + sp - The PetscDualSpace object 1000b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetInteriorData() 1001b4457527SToby Isaac 1002b4457527SToby Isaac Output Parameter: 1003b4457527SToby Isaac . spValue - The values of interior dual space functionals 1004b4457527SToby Isaac 1005b4457527SToby Isaac Level: beginner 1006b4457527SToby Isaac 1007db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1008b4457527SToby Isaac @*/ 10099371c9d4SSatish Balay PetscErrorCode PetscDualSpaceApplyInterior(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) { 1010b4457527SToby Isaac PetscFunctionBegin; 1011b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1012dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyint, pointEval, spValue); 1013b4457527SToby Isaac PetscFunctionReturn(0); 1014b4457527SToby Isaac } 1015b4457527SToby Isaac 1016b4457527SToby Isaac /*@C 101720cf1dd8SToby Isaac PetscDualSpaceApplyDefault - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional. 101820cf1dd8SToby Isaac 101920cf1dd8SToby Isaac Input Parameters: 102020cf1dd8SToby Isaac + sp - The PetscDualSpace object 102120cf1dd8SToby Isaac . f - The basis functional index 102220cf1dd8SToby Isaac . time - The time 102320cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian) 102420cf1dd8SToby Isaac . Nc - The number of components for the function 102520cf1dd8SToby Isaac . func - The input function 102620cf1dd8SToby Isaac - ctx - A context for the function 102720cf1dd8SToby Isaac 102820cf1dd8SToby Isaac Output Parameter: 102920cf1dd8SToby Isaac . value - The output value 103020cf1dd8SToby Isaac 103120cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 103220cf1dd8SToby Isaac 103320cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 103420cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 103520cf1dd8SToby Isaac 103620cf1dd8SToby Isaac and the idea is to evaluate the functional as an integral 103720cf1dd8SToby Isaac 103820cf1dd8SToby Isaac $ n(f) = int dx n(x) . f(x) 103920cf1dd8SToby Isaac 104020cf1dd8SToby Isaac where both n and f have Nc components. 104120cf1dd8SToby Isaac 1042a4ce7ad1SMatthew G. Knepley Level: beginner 104320cf1dd8SToby Isaac 1044db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 104520cf1dd8SToby Isaac @*/ 10469371c9d4SSatish Balay PetscErrorCode PetscDualSpaceApplyDefault(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFEGeom *cgeom, PetscInt Nc, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void *ctx, PetscScalar *value) { 104720cf1dd8SToby Isaac DM dm; 104820cf1dd8SToby Isaac PetscQuadrature n; 104920cf1dd8SToby Isaac const PetscReal *points, *weights; 105020cf1dd8SToby Isaac PetscReal x[3]; 105120cf1dd8SToby Isaac PetscScalar *val; 105220cf1dd8SToby Isaac PetscInt dim, dE, qNc, c, Nq, q; 105320cf1dd8SToby Isaac PetscBool isAffine; 105420cf1dd8SToby Isaac 105520cf1dd8SToby Isaac PetscFunctionBegin; 105620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1057dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 10589566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 10599566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 10609566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, &dim, &qNc, &Nq, &points, &weights)); 106163a3b9bcSJacob 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); 106263a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 10639566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 106420cf1dd8SToby Isaac *value = 0.0; 106520cf1dd8SToby Isaac isAffine = cgeom->isAffine; 106620cf1dd8SToby Isaac dE = cgeom->dimEmbed; 106720cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 106820cf1dd8SToby Isaac if (isAffine) { 106920cf1dd8SToby Isaac CoordinatesRefToReal(dE, cgeom->dim, cgeom->xi, cgeom->v, cgeom->J, &points[q * dim], x); 10709566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, x, Nc, val, ctx)); 107120cf1dd8SToby Isaac } else { 10729566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, &cgeom->v[dE * q], Nc, val, ctx)); 107320cf1dd8SToby Isaac } 10749371c9d4SSatish Balay for (c = 0; c < Nc; ++c) { *value += val[c] * weights[q * Nc + c]; } 107520cf1dd8SToby Isaac } 10769566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 107720cf1dd8SToby Isaac PetscFunctionReturn(0); 107820cf1dd8SToby Isaac } 107920cf1dd8SToby Isaac 108020cf1dd8SToby Isaac /*@C 1081b4457527SToby Isaac PetscDualSpaceApplyAllDefault - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetAllData() 108220cf1dd8SToby Isaac 108320cf1dd8SToby Isaac Input Parameters: 108420cf1dd8SToby Isaac + sp - The PetscDualSpace object 1085b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetAllData() 108620cf1dd8SToby Isaac 108720cf1dd8SToby Isaac Output Parameter: 108820cf1dd8SToby Isaac . spValue - The values of all dual space functionals 108920cf1dd8SToby Isaac 1090a4ce7ad1SMatthew G. Knepley Level: beginner 109120cf1dd8SToby Isaac 1092db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 109320cf1dd8SToby Isaac @*/ 10949371c9d4SSatish Balay PetscErrorCode PetscDualSpaceApplyAllDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) { 1095b4457527SToby Isaac Vec pointValues, dofValues; 1096b4457527SToby Isaac Mat allMat; 109720cf1dd8SToby Isaac 109820cf1dd8SToby Isaac PetscFunctionBegin; 109920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 110020cf1dd8SToby Isaac PetscValidScalarPointer(pointEval, 2); 1101064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11029566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetAllData(sp, NULL, &allMat)); 1103*48a46eb9SPierre Jolivet if (!(sp->allNodeValues)) PetscCall(MatCreateVecs(allMat, &(sp->allNodeValues), NULL)); 1104b4457527SToby Isaac pointValues = sp->allNodeValues; 1105*48a46eb9SPierre Jolivet if (!(sp->allDofValues)) PetscCall(MatCreateVecs(allMat, NULL, &(sp->allDofValues))); 1106b4457527SToby Isaac dofValues = sp->allDofValues; 11079566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11089566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11099566063dSJacob Faibussowitsch PetscCall(MatMult(allMat, pointValues, dofValues)); 11109566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11119566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 1112b4457527SToby Isaac PetscFunctionReturn(0); 111320cf1dd8SToby Isaac } 1114b4457527SToby Isaac 1115b4457527SToby Isaac /*@C 1116b4457527SToby Isaac PetscDualSpaceApplyInteriorDefault - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetInteriorData() 1117b4457527SToby Isaac 1118b4457527SToby Isaac Input Parameters: 1119b4457527SToby Isaac + sp - The PetscDualSpace object 1120b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetInteriorData() 1121b4457527SToby Isaac 1122b4457527SToby Isaac Output Parameter: 1123b4457527SToby Isaac . spValue - The values of interior dual space functionals 1124b4457527SToby Isaac 1125b4457527SToby Isaac Level: beginner 1126b4457527SToby Isaac 1127db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1128b4457527SToby Isaac @*/ 11299371c9d4SSatish Balay PetscErrorCode PetscDualSpaceApplyInteriorDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) { 1130b4457527SToby Isaac Vec pointValues, dofValues; 1131b4457527SToby Isaac Mat intMat; 1132b4457527SToby Isaac 1133b4457527SToby Isaac PetscFunctionBegin; 1134b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1135b4457527SToby Isaac PetscValidScalarPointer(pointEval, 2); 1136064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11379566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(sp, NULL, &intMat)); 1138*48a46eb9SPierre Jolivet if (!(sp->intNodeValues)) PetscCall(MatCreateVecs(intMat, &(sp->intNodeValues), NULL)); 1139b4457527SToby Isaac pointValues = sp->intNodeValues; 1140*48a46eb9SPierre Jolivet if (!(sp->intDofValues)) PetscCall(MatCreateVecs(intMat, NULL, &(sp->intDofValues))); 1141b4457527SToby Isaac dofValues = sp->intDofValues; 11429566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11439566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11449566063dSJacob Faibussowitsch PetscCall(MatMult(intMat, pointValues, dofValues)); 11459566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11469566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 114720cf1dd8SToby Isaac PetscFunctionReturn(0); 114820cf1dd8SToby Isaac } 114920cf1dd8SToby Isaac 1150a4ce7ad1SMatthew G. Knepley /*@ 1151b4457527SToby Isaac PetscDualSpaceGetAllData - Get all quadrature nodes from this space, and the matrix that sends quadrature node values to degree-of-freedom values 1152a4ce7ad1SMatthew G. Knepley 1153a4ce7ad1SMatthew G. Knepley Input Parameter: 1154a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1155a4ce7ad1SMatthew G. Knepley 1156d8d19677SJose E. Roman Output Parameters: 1157b4457527SToby Isaac + allNodes - A PetscQuadrature object containing all evaluation nodes 1158b4457527SToby Isaac - allMat - A Mat for the node-to-dof transformation 1159a4ce7ad1SMatthew G. Knepley 1160a4ce7ad1SMatthew G. Knepley Level: advanced 1161a4ce7ad1SMatthew G. Knepley 1162db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1163a4ce7ad1SMatthew G. Knepley @*/ 11649371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetAllData(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) { 116520cf1dd8SToby Isaac PetscFunctionBegin; 116620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1167b4457527SToby Isaac if (allNodes) PetscValidPointer(allNodes, 2); 1168b4457527SToby Isaac if (allMat) PetscValidPointer(allMat, 3); 1169b4457527SToby Isaac if ((!sp->allNodes || !sp->allMat) && sp->ops->createalldata) { 1170b4457527SToby Isaac PetscQuadrature qpoints; 1171b4457527SToby Isaac Mat amat; 1172b4457527SToby Isaac 1173dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createalldata, &qpoints, &amat); 11749566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->allNodes))); 11759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->allMat))); 1176b4457527SToby Isaac sp->allNodes = qpoints; 1177b4457527SToby Isaac sp->allMat = amat; 117820cf1dd8SToby Isaac } 1179b4457527SToby Isaac if (allNodes) *allNodes = sp->allNodes; 1180b4457527SToby Isaac if (allMat) *allMat = sp->allMat; 118120cf1dd8SToby Isaac PetscFunctionReturn(0); 118220cf1dd8SToby Isaac } 118320cf1dd8SToby Isaac 1184a4ce7ad1SMatthew G. Knepley /*@ 1185b4457527SToby Isaac PetscDualSpaceCreateAllDataDefault - Create all evaluation nodes and the node-to-dof matrix by examining functionals 1186a4ce7ad1SMatthew G. Knepley 1187a4ce7ad1SMatthew G. Knepley Input Parameter: 1188a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1189a4ce7ad1SMatthew G. Knepley 1190d8d19677SJose E. Roman Output Parameters: 1191b4457527SToby Isaac + allNodes - A PetscQuadrature object containing all evaluation nodes 1192b4457527SToby Isaac - allMat - A Mat for the node-to-dof transformation 1193a4ce7ad1SMatthew G. Knepley 1194a4ce7ad1SMatthew G. Knepley Level: advanced 1195a4ce7ad1SMatthew G. Knepley 1196db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1197a4ce7ad1SMatthew G. Knepley @*/ 11989371c9d4SSatish Balay PetscErrorCode PetscDualSpaceCreateAllDataDefault(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) { 119920cf1dd8SToby Isaac PetscInt spdim; 120020cf1dd8SToby Isaac PetscInt numPoints, offset; 120120cf1dd8SToby Isaac PetscReal *points; 120220cf1dd8SToby Isaac PetscInt f, dim; 1203b4457527SToby Isaac PetscInt Nc, nrows, ncols; 1204b4457527SToby Isaac PetscInt maxNumPoints; 120520cf1dd8SToby Isaac PetscQuadrature q; 1206b4457527SToby Isaac Mat A; 120720cf1dd8SToby Isaac 120820cf1dd8SToby Isaac PetscFunctionBegin; 12099566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 12109566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &spdim)); 121120cf1dd8SToby Isaac if (!spdim) { 12129566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes)); 12139566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, 0, 0, 0, NULL, NULL)); 121420cf1dd8SToby Isaac } 1215b4457527SToby Isaac nrows = spdim; 12169566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, 0, &q)); 12179566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, NULL, &numPoints, NULL, NULL)); 1218b4457527SToby Isaac maxNumPoints = numPoints; 121920cf1dd8SToby Isaac for (f = 1; f < spdim; f++) { 122020cf1dd8SToby Isaac PetscInt Np; 122120cf1dd8SToby Isaac 12229566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q)); 12239566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL)); 122420cf1dd8SToby Isaac numPoints += Np; 1225b4457527SToby Isaac maxNumPoints = PetscMax(maxNumPoints, Np); 122620cf1dd8SToby Isaac } 1227b4457527SToby Isaac ncols = numPoints * Nc; 12289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points)); 12299566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, nrows, ncols, maxNumPoints * Nc, NULL, &A)); 123020cf1dd8SToby Isaac for (f = 0, offset = 0; f < spdim; f++) { 1231b4457527SToby Isaac const PetscReal *p, *w; 123220cf1dd8SToby Isaac PetscInt Np, i; 1233b4457527SToby Isaac PetscInt fnc; 123420cf1dd8SToby Isaac 12359566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q)); 12369566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, &fnc, &Np, &p, &w)); 123708401ef6SPierre Jolivet PetscCheck(fnc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "functional component mismatch"); 12389371c9d4SSatish Balay for (i = 0; i < Np * dim; i++) { points[offset * dim + i] = p[i]; } 1239*48a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(A, f, offset * Nc, w[i], INSERT_VALUES)); 1240b4457527SToby Isaac offset += Np; 1241b4457527SToby Isaac } 12429566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 12439566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 12449566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes)); 12459566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, dim, 0, numPoints, points, NULL)); 1246b4457527SToby Isaac *allMat = A; 1247b4457527SToby Isaac PetscFunctionReturn(0); 1248b4457527SToby Isaac } 1249b4457527SToby Isaac 1250b4457527SToby Isaac /*@ 1251b4457527SToby Isaac PetscDualSpaceGetInteriorData - Get all quadrature points necessary to compute the interior degrees of freedom from 1252b4457527SToby Isaac this space, as well as the matrix that computes the degrees of freedom from the quadrature values. Degrees of 1253b4457527SToby Isaac freedom are interior degrees of freedom if they belong (by PetscDualSpaceGetSection()) to interior points in the 1254b4457527SToby Isaac reference DMPlex: complementary boundary degrees of freedom are marked as constrained in the section returned by 1255b4457527SToby Isaac PetscDualSpaceGetSection()). 1256b4457527SToby Isaac 1257b4457527SToby Isaac Input Parameter: 1258b4457527SToby Isaac . sp - The dualspace 1259b4457527SToby Isaac 1260d8d19677SJose E. Roman Output Parameters: 1261b4457527SToby Isaac + intNodes - A PetscQuadrature object containing all evaluation points needed to evaluate interior degrees of freedom 1262b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1263b4457527SToby Isaac the size of the constrained layout (PetscSectionGetConstrainStorageSize()) of the dual space section, 1264b4457527SToby Isaac npoints is the number of points in intNodes and nc is PetscDualSpaceGetNumComponents(). 1265b4457527SToby Isaac 1266b4457527SToby Isaac Level: advanced 1267b4457527SToby Isaac 1268db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceGetNumComponents()`, `PetscQuadratureGetData()` 1269b4457527SToby Isaac @*/ 12709371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetInteriorData(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) { 1271b4457527SToby Isaac PetscFunctionBegin; 1272b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1273b4457527SToby Isaac if (intNodes) PetscValidPointer(intNodes, 2); 1274b4457527SToby Isaac if (intMat) PetscValidPointer(intMat, 3); 1275b4457527SToby Isaac if ((!sp->intNodes || !sp->intMat) && sp->ops->createintdata) { 1276b4457527SToby Isaac PetscQuadrature qpoints; 1277b4457527SToby Isaac Mat imat; 1278b4457527SToby Isaac 1279dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createintdata, &qpoints, &imat); 12809566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->intNodes))); 12819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->intMat))); 1282b4457527SToby Isaac sp->intNodes = qpoints; 1283b4457527SToby Isaac sp->intMat = imat; 1284b4457527SToby Isaac } 1285b4457527SToby Isaac if (intNodes) *intNodes = sp->intNodes; 1286b4457527SToby Isaac if (intMat) *intMat = sp->intMat; 1287b4457527SToby Isaac PetscFunctionReturn(0); 1288b4457527SToby Isaac } 1289b4457527SToby Isaac 1290b4457527SToby Isaac /*@ 1291b4457527SToby Isaac PetscDualSpaceCreateInteriorDataDefault - Create quadrature points by examining interior functionals and create the matrix mapping quadrature point values to interior dual space values 1292b4457527SToby Isaac 1293b4457527SToby Isaac Input Parameter: 1294b4457527SToby Isaac . sp - The dualspace 1295b4457527SToby Isaac 1296d8d19677SJose E. Roman Output Parameters: 1297b4457527SToby Isaac + intNodes - A PetscQuadrature object containing all evaluation points needed to evaluate interior degrees of freedom 1298b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1299b4457527SToby Isaac the size of the constrained layout (PetscSectionGetConstrainStorageSize()) of the dual space section, 1300b4457527SToby Isaac npoints is the number of points in allNodes and nc is PetscDualSpaceGetNumComponents(). 1301b4457527SToby Isaac 1302b4457527SToby Isaac Level: advanced 1303b4457527SToby Isaac 1304db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `PetscDualSpaceGetInteriorData()` 1305b4457527SToby Isaac @*/ 13069371c9d4SSatish Balay PetscErrorCode PetscDualSpaceCreateInteriorDataDefault(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) { 1307b4457527SToby Isaac DM dm; 1308b4457527SToby Isaac PetscInt spdim0; 1309b4457527SToby Isaac PetscInt Nc; 1310b4457527SToby Isaac PetscInt pStart, pEnd, p, f; 1311b4457527SToby Isaac PetscSection section; 1312b4457527SToby Isaac PetscInt numPoints, offset, matoffset; 1313b4457527SToby Isaac PetscReal *points; 1314b4457527SToby Isaac PetscInt dim; 1315b4457527SToby Isaac PetscInt *nnz; 1316b4457527SToby Isaac PetscQuadrature q; 1317b4457527SToby Isaac Mat imat; 1318b4457527SToby Isaac 1319b4457527SToby Isaac PetscFunctionBegin; 1320b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 13219566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 13229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &spdim0)); 1323b4457527SToby Isaac if (!spdim0) { 1324b4457527SToby Isaac *intNodes = NULL; 1325b4457527SToby Isaac *intMat = NULL; 1326b4457527SToby Isaac PetscFunctionReturn(0); 1327b4457527SToby Isaac } 13289566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 13299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 13309566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 13319566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 13329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(spdim0, &nnz)); 1333b4457527SToby Isaac for (p = pStart, f = 0, numPoints = 0; p < pEnd; p++) { 1334b4457527SToby Isaac PetscInt dof, cdof, off, d; 1335b4457527SToby Isaac 13369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 13379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1338b4457527SToby Isaac if (!(dof - cdof)) continue; 13399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1340b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1341b4457527SToby Isaac PetscInt Np; 1342b4457527SToby Isaac 13439566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q)); 13449566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL)); 1345b4457527SToby Isaac nnz[f] = Np * Nc; 1346b4457527SToby Isaac numPoints += Np; 1347b4457527SToby Isaac } 1348b4457527SToby Isaac } 13499566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, spdim0, numPoints * Nc, 0, nnz, &imat)); 13509566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 13519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points)); 1352b4457527SToby Isaac for (p = pStart, f = 0, offset = 0, matoffset = 0; p < pEnd; p++) { 1353b4457527SToby Isaac PetscInt dof, cdof, off, d; 1354b4457527SToby Isaac 13559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 13569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1357b4457527SToby Isaac if (!(dof - cdof)) continue; 13589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1359b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1360b4457527SToby Isaac const PetscReal *p; 1361b4457527SToby Isaac const PetscReal *w; 1362b4457527SToby Isaac PetscInt Np, i; 1363b4457527SToby Isaac 13649566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q)); 13659566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, &p, &w)); 13669371c9d4SSatish Balay for (i = 0; i < Np * dim; i++) { points[offset + i] = p[i]; } 1367*48a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(imat, f, matoffset + i, w[i], INSERT_VALUES)); 1368b4457527SToby Isaac offset += Np * dim; 1369b4457527SToby Isaac matoffset += Np * Nc; 1370b4457527SToby Isaac } 1371b4457527SToby Isaac } 13729566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, intNodes)); 13739566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*intNodes, dim, 0, numPoints, points, NULL)); 13749566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(imat, MAT_FINAL_ASSEMBLY)); 13759566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(imat, MAT_FINAL_ASSEMBLY)); 1376b4457527SToby Isaac *intMat = imat; 137720cf1dd8SToby Isaac PetscFunctionReturn(0); 137820cf1dd8SToby Isaac } 137920cf1dd8SToby Isaac 13804f9ab2b4SJed Brown /*@ 13814f9ab2b4SJed Brown PetscDualSpaceEqual - Determine if a dual space is equivalent 13824f9ab2b4SJed Brown 13834f9ab2b4SJed Brown Input Parameters: 13844f9ab2b4SJed Brown + A - A PetscDualSpace object 13854f9ab2b4SJed Brown - B - Another PetscDualSpace object 13864f9ab2b4SJed Brown 13874f9ab2b4SJed Brown Output Parameter: 13884f9ab2b4SJed Brown . equal - PETSC_TRUE if the dual spaces are equivalent 13894f9ab2b4SJed Brown 13904f9ab2b4SJed Brown Level: advanced 13914f9ab2b4SJed Brown 1392db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 13934f9ab2b4SJed Brown @*/ 13949371c9d4SSatish Balay PetscErrorCode PetscDualSpaceEqual(PetscDualSpace A, PetscDualSpace B, PetscBool *equal) { 13954f9ab2b4SJed Brown PetscInt sizeA, sizeB, dimA, dimB; 13964f9ab2b4SJed Brown const PetscInt *dofA, *dofB; 13974f9ab2b4SJed Brown PetscQuadrature quadA, quadB; 13984f9ab2b4SJed Brown Mat matA, matB; 13994f9ab2b4SJed Brown 14004f9ab2b4SJed Brown PetscFunctionBegin; 14014f9ab2b4SJed Brown PetscValidHeaderSpecific(A, PETSCDUALSPACE_CLASSID, 1); 14024f9ab2b4SJed Brown PetscValidHeaderSpecific(B, PETSCDUALSPACE_CLASSID, 2); 14034f9ab2b4SJed Brown PetscValidBoolPointer(equal, 3); 14044f9ab2b4SJed Brown *equal = PETSC_FALSE; 14059566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(A, &sizeA)); 14069566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(B, &sizeB)); 14079371c9d4SSatish Balay if (sizeB != sizeA) { PetscFunctionReturn(0); } 14089566063dSJacob Faibussowitsch PetscCall(DMGetDimension(A->dm, &dimA)); 14099566063dSJacob Faibussowitsch PetscCall(DMGetDimension(B->dm, &dimB)); 14109371c9d4SSatish Balay if (dimA != dimB) { PetscFunctionReturn(0); } 14114f9ab2b4SJed Brown 14129566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(A, &dofA)); 14139566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(B, &dofB)); 14144f9ab2b4SJed Brown for (PetscInt d = 0; d < dimA; d++) { 14159371c9d4SSatish Balay if (dofA[d] != dofB[d]) { PetscFunctionReturn(0); } 14164f9ab2b4SJed Brown } 14174f9ab2b4SJed Brown 14189566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(A, &quadA, &matA)); 14199566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(B, &quadB, &matB)); 14204f9ab2b4SJed Brown if (!quadA && !quadB) { 14214f9ab2b4SJed Brown *equal = PETSC_TRUE; 14224f9ab2b4SJed Brown } else if (quadA && quadB) { 14239566063dSJacob Faibussowitsch PetscCall(PetscQuadratureEqual(quadA, quadB, equal)); 14244f9ab2b4SJed Brown if (*equal == PETSC_FALSE) PetscFunctionReturn(0); 14254f9ab2b4SJed Brown if (!matA && !matB) PetscFunctionReturn(0); 14269566063dSJacob Faibussowitsch if (matA && matB) PetscCall(MatEqual(matA, matB, equal)); 14274f9ab2b4SJed Brown else *equal = PETSC_FALSE; 14284f9ab2b4SJed Brown } 14294f9ab2b4SJed Brown PetscFunctionReturn(0); 14304f9ab2b4SJed Brown } 14314f9ab2b4SJed Brown 143220cf1dd8SToby Isaac /*@C 143320cf1dd8SToby Isaac PetscDualSpaceApplyFVM - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional at the cell centroid. 143420cf1dd8SToby Isaac 143520cf1dd8SToby Isaac Input Parameters: 143620cf1dd8SToby Isaac + sp - The PetscDualSpace object 143720cf1dd8SToby Isaac . f - The basis functional index 143820cf1dd8SToby Isaac . time - The time 143920cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we currently just use the centroid 144020cf1dd8SToby Isaac . Nc - The number of components for the function 144120cf1dd8SToby Isaac . func - The input function 144220cf1dd8SToby Isaac - ctx - A context for the function 144320cf1dd8SToby Isaac 144420cf1dd8SToby Isaac Output Parameter: 144520cf1dd8SToby Isaac . value - The output value (scalar) 144620cf1dd8SToby Isaac 144720cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 144820cf1dd8SToby Isaac 144920cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 145020cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 145120cf1dd8SToby Isaac 145220cf1dd8SToby Isaac and the idea is to evaluate the functional as an integral 145320cf1dd8SToby Isaac 145420cf1dd8SToby Isaac $ n(f) = int dx n(x) . f(x) 145520cf1dd8SToby Isaac 145620cf1dd8SToby Isaac where both n and f have Nc components. 145720cf1dd8SToby Isaac 1458a4ce7ad1SMatthew G. Knepley Level: beginner 145920cf1dd8SToby Isaac 1460db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 146120cf1dd8SToby Isaac @*/ 14629371c9d4SSatish Balay PetscErrorCode PetscDualSpaceApplyFVM(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFVCellGeom *cgeom, PetscInt Nc, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void *ctx, PetscScalar *value) { 146320cf1dd8SToby Isaac DM dm; 146420cf1dd8SToby Isaac PetscQuadrature n; 146520cf1dd8SToby Isaac const PetscReal *points, *weights; 146620cf1dd8SToby Isaac PetscScalar *val; 146720cf1dd8SToby Isaac PetscInt dimEmbed, qNc, c, Nq, q; 146820cf1dd8SToby Isaac 146920cf1dd8SToby Isaac PetscFunctionBegin; 147020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1471dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 14729566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 14739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 14749566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 14759566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, NULL, &qNc, &Nq, &points, &weights)); 147663a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 14779566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 147820cf1dd8SToby Isaac *value = 0.; 147920cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 14809566063dSJacob Faibussowitsch PetscCall((*func)(dimEmbed, time, cgeom->centroid, Nc, val, ctx)); 14819371c9d4SSatish Balay for (c = 0; c < Nc; ++c) { *value += val[c] * weights[q * Nc + c]; } 148220cf1dd8SToby Isaac } 14839566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 148420cf1dd8SToby Isaac PetscFunctionReturn(0); 148520cf1dd8SToby Isaac } 148620cf1dd8SToby Isaac 148720cf1dd8SToby Isaac /*@ 148820cf1dd8SToby Isaac PetscDualSpaceGetHeightSubspace - Get the subset of the dual space basis that is supported on a mesh point of a 148920cf1dd8SToby Isaac given height. This assumes that the reference cell is symmetric over points of this height. 149020cf1dd8SToby Isaac 149120cf1dd8SToby Isaac If the dual space is not defined on mesh points of the given height (e.g. if the space is discontinuous and 149220cf1dd8SToby Isaac pointwise values are not defined on the element boundaries), or if the implementation of PetscDualSpace does not 149320cf1dd8SToby Isaac support extracting subspaces, then NULL is returned. 149420cf1dd8SToby Isaac 149520cf1dd8SToby Isaac This does not increment the reference count on the returned dual space, and the user should not destroy it. 149620cf1dd8SToby Isaac 149720cf1dd8SToby Isaac Not collective 149820cf1dd8SToby Isaac 149920cf1dd8SToby Isaac Input Parameters: 150020cf1dd8SToby Isaac + sp - the PetscDualSpace object 150120cf1dd8SToby Isaac - height - the height of the mesh point for which the subspace is desired 150220cf1dd8SToby Isaac 150320cf1dd8SToby Isaac Output Parameter: 150420cf1dd8SToby Isaac . subsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 150520cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 150620cf1dd8SToby Isaac 150720cf1dd8SToby Isaac Level: advanced 150820cf1dd8SToby Isaac 1509db781477SPatrick Sanan .seealso: `PetscSpaceGetHeightSubspace()`, `PetscDualSpace` 151020cf1dd8SToby Isaac @*/ 15119371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetHeightSubspace(PetscDualSpace sp, PetscInt height, PetscDualSpace *subsp) { 1512b4457527SToby Isaac PetscInt depth = -1, cStart, cEnd; 1513b4457527SToby Isaac DM dm; 151420cf1dd8SToby Isaac 151520cf1dd8SToby Isaac PetscFunctionBegin; 151620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1517064a246eSJacob Faibussowitsch PetscValidPointer(subsp, 3); 151808401ef6SPierre 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"); 151920cf1dd8SToby Isaac *subsp = NULL; 1520b4457527SToby Isaac dm = sp->dm; 15219566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 15221dca8a05SBarry Smith PetscCheck(height >= 0 && height <= depth, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid height"); 15239566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1524b4457527SToby Isaac if (height == 0 && cEnd == cStart + 1) { 1525b4457527SToby Isaac *subsp = sp; 1526b4457527SToby Isaac PetscFunctionReturn(0); 1527b4457527SToby Isaac } 1528b4457527SToby Isaac if (!sp->heightSpaces) { 1529b4457527SToby Isaac PetscInt h; 15309566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth + 1, &(sp->heightSpaces))); 1531b4457527SToby Isaac 1532b4457527SToby Isaac for (h = 0; h <= depth; h++) { 1533b4457527SToby Isaac if (h == 0 && cEnd == cStart + 1) continue; 15349566063dSJacob Faibussowitsch if (sp->ops->createheightsubspace) PetscCall((*sp->ops->createheightsubspace)(sp, height, &(sp->heightSpaces[h]))); 1535b4457527SToby Isaac else if (sp->pointSpaces) { 1536b4457527SToby Isaac PetscInt hStart, hEnd; 1537b4457527SToby Isaac 15389566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &hStart, &hEnd)); 1539b4457527SToby Isaac if (hEnd > hStart) { 1540665f567fSMatthew G. Knepley const char *name; 1541665f567fSMatthew G. Knepley 15429566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(sp->pointSpaces[hStart]))); 1543665f567fSMatthew G. Knepley if (sp->pointSpaces[hStart]) { 15449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name)); 15459566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sp->pointSpaces[hStart], name)); 1546665f567fSMatthew G. Knepley } 1547b4457527SToby Isaac sp->heightSpaces[h] = sp->pointSpaces[hStart]; 1548b4457527SToby Isaac } 1549b4457527SToby Isaac } 1550b4457527SToby Isaac } 1551b4457527SToby Isaac } 1552b4457527SToby Isaac *subsp = sp->heightSpaces[height]; 155320cf1dd8SToby Isaac PetscFunctionReturn(0); 155420cf1dd8SToby Isaac } 155520cf1dd8SToby Isaac 155620cf1dd8SToby Isaac /*@ 155720cf1dd8SToby Isaac PetscDualSpaceGetPointSubspace - Get the subset of the dual space basis that is supported on a particular mesh point. 155820cf1dd8SToby Isaac 155920cf1dd8SToby Isaac If the dual space is not defined on the mesh point (e.g. if the space is discontinuous and pointwise values are not 156020cf1dd8SToby Isaac defined on the element boundaries), or if the implementation of PetscDualSpace does not support extracting 156120cf1dd8SToby Isaac subspaces, then NULL is returned. 156220cf1dd8SToby Isaac 156320cf1dd8SToby Isaac This does not increment the reference count on the returned dual space, and the user should not destroy it. 156420cf1dd8SToby Isaac 156520cf1dd8SToby Isaac Not collective 156620cf1dd8SToby Isaac 156720cf1dd8SToby Isaac Input Parameters: 156820cf1dd8SToby Isaac + sp - the PetscDualSpace object 156920cf1dd8SToby Isaac - point - the point (in the dual space's DM) for which the subspace is desired 157020cf1dd8SToby Isaac 157120cf1dd8SToby Isaac Output Parameters: 157220cf1dd8SToby Isaac bdsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 157320cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 157420cf1dd8SToby Isaac 157520cf1dd8SToby Isaac Level: advanced 157620cf1dd8SToby Isaac 1577db781477SPatrick Sanan .seealso: `PetscDualSpace` 157820cf1dd8SToby Isaac @*/ 15799371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetPointSubspace(PetscDualSpace sp, PetscInt point, PetscDualSpace *bdsp) { 1580b4457527SToby Isaac PetscInt pStart = 0, pEnd = 0, cStart, cEnd; 1581b4457527SToby Isaac DM dm; 158220cf1dd8SToby Isaac 158320cf1dd8SToby Isaac PetscFunctionBegin; 158420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1585064a246eSJacob Faibussowitsch PetscValidPointer(bdsp, 3); 158620cf1dd8SToby Isaac *bdsp = NULL; 1587b4457527SToby Isaac dm = sp->dm; 15889566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 15891dca8a05SBarry Smith PetscCheck(point >= pStart && point <= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid point"); 15909566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1591b4457527SToby 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 */ 1592b4457527SToby Isaac *bdsp = sp; 1593b4457527SToby Isaac PetscFunctionReturn(0); 1594b4457527SToby Isaac } 1595b4457527SToby Isaac if (!sp->pointSpaces) { 1596b4457527SToby Isaac PetscInt p; 15979566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &(sp->pointSpaces))); 159820cf1dd8SToby Isaac 1599b4457527SToby Isaac for (p = 0; p < pEnd - pStart; p++) { 1600b4457527SToby Isaac if (p + pStart == cStart && cEnd == cStart + 1) continue; 16019566063dSJacob Faibussowitsch if (sp->ops->createpointsubspace) PetscCall((*sp->ops->createpointsubspace)(sp, p + pStart, &(sp->pointSpaces[p]))); 1602b4457527SToby Isaac else if (sp->heightSpaces || sp->ops->createheightsubspace) { 1603b4457527SToby Isaac PetscInt dim, depth, height; 1604b4457527SToby Isaac DMLabel label; 1605b4457527SToby Isaac 16069566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &dim)); 16079566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 16089566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, p + pStart, &depth)); 160920cf1dd8SToby Isaac height = dim - depth; 16109566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(sp, height, &(sp->pointSpaces[p]))); 16119566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sp->pointSpaces[p])); 161220cf1dd8SToby Isaac } 1613b4457527SToby Isaac } 1614b4457527SToby Isaac } 1615b4457527SToby Isaac *bdsp = sp->pointSpaces[point - pStart]; 161620cf1dd8SToby Isaac PetscFunctionReturn(0); 161720cf1dd8SToby Isaac } 161820cf1dd8SToby Isaac 16196f905325SMatthew G. Knepley /*@C 16206f905325SMatthew G. Knepley PetscDualSpaceGetSymmetries - Returns a description of the symmetries of this basis 16216f905325SMatthew G. Knepley 16226f905325SMatthew G. Knepley Not collective 16236f905325SMatthew G. Knepley 16246f905325SMatthew G. Knepley Input Parameter: 16256f905325SMatthew G. Knepley . sp - the PetscDualSpace object 16266f905325SMatthew G. Knepley 16276f905325SMatthew G. Knepley Output Parameters: 1628b4457527SToby Isaac + perms - Permutations of the interior degrees of freedom, parameterized by the point orientation 1629b4457527SToby Isaac - flips - Sign reversal of the interior degrees of freedom, parameterized by the point orientation 16306f905325SMatthew G. Knepley 16316f905325SMatthew G. Knepley Note: The permutation and flip arrays are organized in the following way 16326f905325SMatthew G. Knepley $ perms[p][ornt][dof # on point] = new local dof # 16336f905325SMatthew G. Knepley $ flips[p][ornt][dof # on point] = reversal or not 16346f905325SMatthew G. Knepley 16356f905325SMatthew G. Knepley Level: developer 16366f905325SMatthew G. Knepley 16376f905325SMatthew G. Knepley @*/ 16389371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetSymmetries(PetscDualSpace sp, const PetscInt ****perms, const PetscScalar ****flips) { 16396f905325SMatthew G. Knepley PetscFunctionBegin; 16406f905325SMatthew G. Knepley PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 16419371c9d4SSatish Balay if (perms) { 16429371c9d4SSatish Balay PetscValidPointer(perms, 2); 16439371c9d4SSatish Balay *perms = NULL; 16449371c9d4SSatish Balay } 16459371c9d4SSatish Balay if (flips) { 16469371c9d4SSatish Balay PetscValidPointer(flips, 3); 16479371c9d4SSatish Balay *flips = NULL; 16489371c9d4SSatish Balay } 16499566063dSJacob Faibussowitsch if (sp->ops->getsymmetries) PetscCall((sp->ops->getsymmetries)(sp, perms, flips)); 16506f905325SMatthew G. Knepley PetscFunctionReturn(0); 16516f905325SMatthew G. Knepley } 16524bee2e38SMatthew G. Knepley 16534bee2e38SMatthew G. Knepley /*@ 1654b4457527SToby Isaac PetscDualSpaceGetFormDegree - Get the form degree k for the k-form the describes the pushforwards/pullbacks of this 1655b4457527SToby Isaac dual space's functionals. 1656b4457527SToby Isaac 1657b4457527SToby Isaac Input Parameter: 1658b4457527SToby Isaac . dsp - The PetscDualSpace 1659b4457527SToby Isaac 1660b4457527SToby Isaac Output Parameter: 1661b4457527SToby 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 1662b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1663b4457527SToby 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). 1664b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1665b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1666b4457527SToby Isaac but are stored as 1-forms. 1667b4457527SToby Isaac 1668b4457527SToby Isaac Level: developer 1669b4457527SToby Isaac 1670db781477SPatrick Sanan .seealso: `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 1671b4457527SToby Isaac @*/ 16729371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetFormDegree(PetscDualSpace dsp, PetscInt *k) { 1673b4457527SToby Isaac PetscFunctionBeginHot; 1674b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1675dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1676b4457527SToby Isaac *k = dsp->k; 1677b4457527SToby Isaac PetscFunctionReturn(0); 1678b4457527SToby Isaac } 1679b4457527SToby Isaac 1680b4457527SToby Isaac /*@ 1681b4457527SToby Isaac PetscDualSpaceSetFormDegree - Set the form degree k for the k-form the describes the pushforwards/pullbacks of this 1682b4457527SToby Isaac dual space's functionals. 1683b4457527SToby Isaac 1684d8d19677SJose E. Roman Input Parameters: 1685b4457527SToby Isaac + dsp - The PetscDualSpace 1686b4457527SToby 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 1687b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1688b4457527SToby 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). 1689b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1690b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1691b4457527SToby Isaac but are stored as 1-forms. 1692b4457527SToby Isaac 1693b4457527SToby Isaac Level: developer 1694b4457527SToby Isaac 1695db781477SPatrick Sanan .seealso: `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 1696b4457527SToby Isaac @*/ 16979371c9d4SSatish Balay PetscErrorCode PetscDualSpaceSetFormDegree(PetscDualSpace dsp, PetscInt k) { 1698b4457527SToby Isaac PetscInt dim; 1699b4457527SToby Isaac 1700b4457527SToby Isaac PetscFunctionBeginHot; 1701b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 170228b400f6SJacob Faibussowitsch PetscCheck(!dsp->setupcalled, PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 1703b4457527SToby Isaac dim = dsp->dm->dim; 17041dca8a05SBarry Smith PetscCheck(k >= -dim && k <= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unsupported %" PetscInt_FMT "-form on %" PetscInt_FMT "-dimensional reference cell", PetscAbsInt(k), dim); 1705b4457527SToby Isaac dsp->k = k; 1706b4457527SToby Isaac PetscFunctionReturn(0); 1707b4457527SToby Isaac } 1708b4457527SToby Isaac 1709b4457527SToby Isaac /*@ 17104bee2e38SMatthew G. Knepley PetscDualSpaceGetDeRahm - Get the k-simplex associated with the functionals in this dual space 17114bee2e38SMatthew G. Knepley 17124bee2e38SMatthew G. Knepley Input Parameter: 17134bee2e38SMatthew G. Knepley . dsp - The PetscDualSpace 17144bee2e38SMatthew G. Knepley 17154bee2e38SMatthew G. Knepley Output Parameter: 17164bee2e38SMatthew G. Knepley . k - The simplex dimension 17174bee2e38SMatthew G. Knepley 1718a4ce7ad1SMatthew G. Knepley Level: developer 17194bee2e38SMatthew G. Knepley 17204bee2e38SMatthew G. Knepley Note: Currently supported values are 17214bee2e38SMatthew G. Knepley $ 0: These are H_1 methods that only transform coordinates 17224bee2e38SMatthew G. Knepley $ 1: These are Hcurl methods that transform functions using the covariant Piola transform (COVARIANT_PIOLA_TRANSFORM) 17234bee2e38SMatthew G. Knepley $ 2: These are the same as 1 17244bee2e38SMatthew G. Knepley $ 3: These are Hdiv methods that transform functions using the contravariant Piola transform (CONTRAVARIANT_PIOLA_TRANSFORM) 17254bee2e38SMatthew G. Knepley 1726db781477SPatrick Sanan .seealso: `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 17274bee2e38SMatthew G. Knepley @*/ 17289371c9d4SSatish Balay PetscErrorCode PetscDualSpaceGetDeRahm(PetscDualSpace dsp, PetscInt *k) { 1729b4457527SToby Isaac PetscInt dim; 1730b4457527SToby Isaac 17314bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 17324bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1733dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1734b4457527SToby Isaac dim = dsp->dm->dim; 1735b4457527SToby Isaac if (!dsp->k) *k = IDENTITY_TRANSFORM; 1736b4457527SToby Isaac else if (dsp->k == 1) *k = COVARIANT_PIOLA_TRANSFORM; 1737b4457527SToby Isaac else if (dsp->k == -(dim - 1)) *k = CONTRAVARIANT_PIOLA_TRANSFORM; 1738b4457527SToby Isaac else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unsupported transformation"); 17394bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 17404bee2e38SMatthew G. Knepley } 17414bee2e38SMatthew G. Knepley 17424bee2e38SMatthew G. Knepley /*@C 17434bee2e38SMatthew G. Knepley PetscDualSpaceTransform - Transform the function values 17444bee2e38SMatthew G. Knepley 17454bee2e38SMatthew G. Knepley Input Parameters: 17464bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 17474bee2e38SMatthew G. Knepley . trans - The type of transform 17484bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 17494bee2e38SMatthew G. Knepley . fegeom - The cell geometry 17504bee2e38SMatthew G. Knepley . Nv - The number of function samples 17514bee2e38SMatthew G. Knepley . Nc - The number of function components 17524bee2e38SMatthew G. Knepley - vals - The function values 17534bee2e38SMatthew G. Knepley 17544bee2e38SMatthew G. Knepley Output Parameter: 17554bee2e38SMatthew G. Knepley . vals - The transformed function values 17564bee2e38SMatthew G. Knepley 1757a4ce7ad1SMatthew G. Knepley Level: intermediate 17584bee2e38SMatthew G. Knepley 1759f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 17602edcad52SToby Isaac 1761db781477SPatrick Sanan .seealso: `PetscDualSpaceTransformGradient()`, `PetscDualSpaceTransformHessian()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 17624bee2e38SMatthew G. Knepley @*/ 17639371c9d4SSatish Balay PetscErrorCode PetscDualSpaceTransform(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) { 1764b4457527SToby Isaac PetscReal Jstar[9] = {0}; 1765b4457527SToby Isaac PetscInt dim, v, c, Nk; 17664bee2e38SMatthew G. Knepley 17674bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 17684bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 17694bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1770dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 1771b4457527SToby Isaac /* TODO: not handling dimEmbed != dim right now */ 17722ae266adSMatthew G. Knepley dim = dsp->dm->dim; 1773b4457527SToby Isaac /* No change needed for 0-forms */ 1774b4457527SToby Isaac if (!dsp->k) PetscFunctionReturn(0); 17759566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(dsp->k), &Nk)); 1776b4457527SToby Isaac /* TODO: use fegeom->isAffine */ 17779566063dSJacob Faibussowitsch PetscCall(PetscDTAltVPullbackMatrix(dim, dim, isInverse ? fegeom->J : fegeom->invJ, dsp->k, Jstar)); 17784bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1779b4457527SToby Isaac switch (Nk) { 1780b4457527SToby Isaac case 1: 1781b4457527SToby Isaac for (c = 0; c < Nc; c++) vals[v * Nc + c] *= Jstar[0]; 17824bee2e38SMatthew G. Knepley break; 1783b4457527SToby Isaac case 2: 1784b4457527SToby Isaac for (c = 0; c < Nc; c += 2) DMPlex_Mult2DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]); 17854bee2e38SMatthew G. Knepley break; 1786b4457527SToby Isaac case 3: 1787b4457527SToby Isaac for (c = 0; c < Nc; c += 3) DMPlex_Mult3DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]); 1788b4457527SToby Isaac break; 178963a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported form size %" PetscInt_FMT " for transformation", Nk); 1790b4457527SToby Isaac } 17914bee2e38SMatthew G. Knepley } 17924bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 17934bee2e38SMatthew G. Knepley } 1794b4457527SToby Isaac 17954bee2e38SMatthew G. Knepley /*@C 17964bee2e38SMatthew G. Knepley PetscDualSpaceTransformGradient - Transform the function gradient values 17974bee2e38SMatthew G. Knepley 17984bee2e38SMatthew G. Knepley Input Parameters: 17994bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 18004bee2e38SMatthew G. Knepley . trans - The type of transform 18014bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18024bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18034bee2e38SMatthew G. Knepley . Nv - The number of function gradient samples 18044bee2e38SMatthew G. Knepley . Nc - The number of function components 18054bee2e38SMatthew G. Knepley - vals - The function gradient values 18064bee2e38SMatthew G. Knepley 18074bee2e38SMatthew G. Knepley Output Parameter: 1808f9244615SMatthew G. Knepley . vals - The transformed function gradient values 18094bee2e38SMatthew G. Knepley 1810a4ce7ad1SMatthew G. Knepley Level: intermediate 18114bee2e38SMatthew G. Knepley 1812f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18132edcad52SToby Isaac 1814db781477SPatrick Sanan .seealso: `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 18154bee2e38SMatthew G. Knepley @*/ 18169371c9d4SSatish Balay PetscErrorCode PetscDualSpaceTransformGradient(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) { 181727f02ce8SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 181827f02ce8SMatthew G. Knepley PetscInt v, c, d; 18194bee2e38SMatthew G. Knepley 18204bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18214bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18224bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1823dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 182427f02ce8SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 182563a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 182627f02ce8SMatthew G. Knepley #endif 18274bee2e38SMatthew G. Knepley /* Transform gradient */ 182827f02ce8SMatthew G. Knepley if (dim == dE) { 18294bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 18304bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 18319371c9d4SSatish Balay switch (dim) { 1832100a78e1SStefano Zampini case 1: vals[(v * Nc + c) * dim] *= fegeom->invJ[0]; break; 18336142fa51SMatthew G. Knepley case 2: DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]); break; 18346142fa51SMatthew G. Knepley case 3: DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]); break; 183563a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 18364bee2e38SMatthew G. Knepley } 18374bee2e38SMatthew G. Knepley } 18384bee2e38SMatthew G. Knepley } 183927f02ce8SMatthew G. Knepley } else { 184027f02ce8SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 18419371c9d4SSatish Balay for (c = 0; c < Nc; ++c) { DMPlex_MultTransposeReal_Internal(fegeom->invJ, dim, dE, 1, &vals[(v * Nc + c) * dE], &vals[(v * Nc + c) * dE]); } 184227f02ce8SMatthew G. Knepley } 184327f02ce8SMatthew G. Knepley } 18444bee2e38SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 18454bee2e38SMatthew G. Knepley if (Nc == 1 || Nc != dim) PetscFunctionReturn(0); 18464bee2e38SMatthew G. Knepley switch (trans) { 18474bee2e38SMatthew G. Knepley case IDENTITY_TRANSFORM: break; 18484bee2e38SMatthew G. Knepley case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 18494bee2e38SMatthew G. Knepley if (isInverse) { 18504bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 18514bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 18529371c9d4SSatish Balay switch (dim) { 18536142fa51SMatthew G. Knepley case 2: DMPlex_MultTranspose2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); break; 18546142fa51SMatthew G. Knepley case 3: DMPlex_MultTranspose3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); break; 185563a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 18564bee2e38SMatthew G. Knepley } 18574bee2e38SMatthew G. Knepley } 18584bee2e38SMatthew G. Knepley } 18594bee2e38SMatthew G. Knepley } else { 18604bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 18614bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 18629371c9d4SSatish Balay switch (dim) { 18636142fa51SMatthew G. Knepley case 2: DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); break; 18646142fa51SMatthew G. Knepley case 3: DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); break; 186563a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 18664bee2e38SMatthew G. Knepley } 18674bee2e38SMatthew G. Knepley } 18684bee2e38SMatthew G. Knepley } 18694bee2e38SMatthew G. Knepley } 18704bee2e38SMatthew G. Knepley break; 18714bee2e38SMatthew G. Knepley case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 18724bee2e38SMatthew G. Knepley if (isInverse) { 18734bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 18744bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 18759371c9d4SSatish Balay switch (dim) { 18766142fa51SMatthew G. Knepley case 2: DMPlex_Mult2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); break; 18776142fa51SMatthew G. Knepley case 3: DMPlex_Mult3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); break; 187863a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 18794bee2e38SMatthew G. Knepley } 18804bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] *= fegeom->detJ[0]; 18814bee2e38SMatthew G. Knepley } 18824bee2e38SMatthew G. Knepley } 18834bee2e38SMatthew G. Knepley } else { 18844bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 18854bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 18869371c9d4SSatish Balay switch (dim) { 18876142fa51SMatthew G. Knepley case 2: DMPlex_Mult2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); break; 18886142fa51SMatthew G. Knepley case 3: DMPlex_Mult3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); break; 188963a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 18904bee2e38SMatthew G. Knepley } 18914bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] /= fegeom->detJ[0]; 18924bee2e38SMatthew G. Knepley } 18934bee2e38SMatthew G. Knepley } 18944bee2e38SMatthew G. Knepley } 18954bee2e38SMatthew G. Knepley break; 18964bee2e38SMatthew G. Knepley } 18974bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 18984bee2e38SMatthew G. Knepley } 18994bee2e38SMatthew G. Knepley 19004bee2e38SMatthew G. Knepley /*@C 1901f9244615SMatthew G. Knepley PetscDualSpaceTransformHessian - Transform the function Hessian values 1902f9244615SMatthew G. Knepley 1903f9244615SMatthew G. Knepley Input Parameters: 1904f9244615SMatthew G. Knepley + dsp - The PetscDualSpace 1905f9244615SMatthew G. Knepley . trans - The type of transform 1906f9244615SMatthew G. Knepley . isInverse - Flag to invert the transform 1907f9244615SMatthew G. Knepley . fegeom - The cell geometry 1908f9244615SMatthew G. Knepley . Nv - The number of function Hessian samples 1909f9244615SMatthew G. Knepley . Nc - The number of function components 1910f9244615SMatthew G. Knepley - vals - The function gradient values 1911f9244615SMatthew G. Knepley 1912f9244615SMatthew G. Knepley Output Parameter: 1913f9244615SMatthew G. Knepley . vals - The transformed function Hessian values 1914f9244615SMatthew G. Knepley 1915f9244615SMatthew G. Knepley Level: intermediate 1916f9244615SMatthew G. Knepley 1917f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 1918f9244615SMatthew G. Knepley 1919db781477SPatrick Sanan .seealso: `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 1920f9244615SMatthew G. Knepley @*/ 19219371c9d4SSatish Balay PetscErrorCode PetscDualSpaceTransformHessian(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) { 1922f9244615SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 1923f9244615SMatthew G. Knepley PetscInt v, c; 1924f9244615SMatthew G. Knepley 1925f9244615SMatthew G. Knepley PetscFunctionBeginHot; 1926f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1927f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1928dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 1929f9244615SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 193063a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 1931f9244615SMatthew G. Knepley #endif 1932f9244615SMatthew G. Knepley /* Transform Hessian: J^{-T}_{ik} J^{-T}_{jl} H(f)_{kl} = J^{-T}_{ik} H(f)_{kl} J^{-1}_{lj} */ 1933f9244615SMatthew G. Knepley if (dim == dE) { 1934f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1935f9244615SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 19369371c9d4SSatish Balay switch (dim) { 1937f9244615SMatthew G. Knepley case 1: vals[(v * Nc + c) * dim * dim] *= PetscSqr(fegeom->invJ[0]); break; 1938f9244615SMatthew G. Knepley case 2: DMPlex_PTAP2DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]); break; 1939f9244615SMatthew G. Knepley case 3: DMPlex_PTAP3DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]); break; 194063a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 1941f9244615SMatthew G. Knepley } 1942f9244615SMatthew G. Knepley } 1943f9244615SMatthew G. Knepley } 1944f9244615SMatthew G. Knepley } else { 1945f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19469371c9d4SSatish Balay 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]); } 1947f9244615SMatthew G. Knepley } 1948f9244615SMatthew G. Knepley } 1949f9244615SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 1950f9244615SMatthew G. Knepley if (Nc == 1 || Nc != dim) PetscFunctionReturn(0); 1951f9244615SMatthew G. Knepley switch (trans) { 1952f9244615SMatthew G. Knepley case IDENTITY_TRANSFORM: break; 19539371c9d4SSatish Balay case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 19549371c9d4SSatish Balay case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 1955f9244615SMatthew G. Knepley } 1956f9244615SMatthew G. Knepley PetscFunctionReturn(0); 1957f9244615SMatthew G. Knepley } 1958f9244615SMatthew G. Knepley 1959f9244615SMatthew G. Knepley /*@C 19604bee2e38SMatthew 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. 19614bee2e38SMatthew G. Knepley 19624bee2e38SMatthew G. Knepley Input Parameters: 19634bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 19644bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 19654bee2e38SMatthew G. Knepley . Nq - The number of function samples 19664bee2e38SMatthew G. Knepley . Nc - The number of function components 19674bee2e38SMatthew G. Knepley - pointEval - The function values 19684bee2e38SMatthew G. Knepley 19694bee2e38SMatthew G. Knepley Output Parameter: 19704bee2e38SMatthew G. Knepley . pointEval - The transformed function values 19714bee2e38SMatthew G. Knepley 19724bee2e38SMatthew G. Knepley Level: advanced 19734bee2e38SMatthew G. Knepley 19744bee2e38SMatthew G. Knepley Note: 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. 19754bee2e38SMatthew G. Knepley 19762edcad52SToby Isaac Note: This only handles tranformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 19772edcad52SToby Isaac 1978db781477SPatrick Sanan .seealso: `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 19794bee2e38SMatthew G. Knepley @*/ 19809371c9d4SSatish Balay PetscErrorCode PetscDualSpacePullback(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) { 19814bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 1982b4457527SToby Isaac PetscInt k; 19834bee2e38SMatthew G. Knepley 19844bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 19854bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 19864bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 1987dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 19884bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 19894bee2e38SMatthew G. Knepley This determines their transformation properties. */ 19909566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 19919371c9d4SSatish Balay switch (k) { 19929371c9d4SSatish Balay case 0: /* H^1 point evaluations */ trans = IDENTITY_TRANSFORM; break; 19939371c9d4SSatish Balay case 1: /* Hcurl preserves tangential edge traces */ trans = COVARIANT_PIOLA_TRANSFORM; break; 1994b4457527SToby Isaac case 2: 19959371c9d4SSatish Balay case 3: /* Hdiv preserve normal traces */ trans = CONTRAVARIANT_PIOLA_TRANSFORM; break; 199663a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 19974bee2e38SMatthew G. Knepley } 19989566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_TRUE, fegeom, Nq, Nc, pointEval)); 19994bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 20004bee2e38SMatthew G. Knepley } 20014bee2e38SMatthew G. Knepley 20024bee2e38SMatthew G. Knepley /*@C 20034bee2e38SMatthew 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. 20044bee2e38SMatthew G. Knepley 20054bee2e38SMatthew G. Knepley Input Parameters: 20064bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 20074bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 20084bee2e38SMatthew G. Knepley . Nq - The number of function samples 20094bee2e38SMatthew G. Knepley . Nc - The number of function components 20104bee2e38SMatthew G. Knepley - pointEval - The function values 20114bee2e38SMatthew G. Knepley 20124bee2e38SMatthew G. Knepley Output Parameter: 20134bee2e38SMatthew G. Knepley . pointEval - The transformed function values 20144bee2e38SMatthew G. Knepley 20154bee2e38SMatthew G. Knepley Level: advanced 20164bee2e38SMatthew G. Knepley 20174bee2e38SMatthew G. Knepley Note: 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. 20184bee2e38SMatthew G. Knepley 2019f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 20202edcad52SToby Isaac 2021db781477SPatrick Sanan .seealso: `PetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 20224bee2e38SMatthew G. Knepley @*/ 20239371c9d4SSatish Balay PetscErrorCode PetscDualSpacePushforward(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) { 20244bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2025b4457527SToby Isaac PetscInt k; 20264bee2e38SMatthew G. Knepley 20274bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 20284bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 20294bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2030dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 20314bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 20324bee2e38SMatthew G. Knepley This determines their transformation properties. */ 20339566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 20349371c9d4SSatish Balay switch (k) { 20359371c9d4SSatish Balay case 0: /* H^1 point evaluations */ trans = IDENTITY_TRANSFORM; break; 20369371c9d4SSatish Balay case 1: /* Hcurl preserves tangential edge traces */ trans = COVARIANT_PIOLA_TRANSFORM; break; 2037b4457527SToby Isaac case 2: 20389371c9d4SSatish Balay case 3: /* Hdiv preserve normal traces */ trans = CONTRAVARIANT_PIOLA_TRANSFORM; break; 203963a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 20404bee2e38SMatthew G. Knepley } 20419566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 20424bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 20434bee2e38SMatthew G. Knepley } 20444bee2e38SMatthew G. Knepley 20454bee2e38SMatthew G. Knepley /*@C 20464bee2e38SMatthew 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. 20474bee2e38SMatthew G. Knepley 20484bee2e38SMatthew G. Knepley Input Parameters: 20494bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 20504bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 20514bee2e38SMatthew G. Knepley . Nq - The number of function gradient samples 20524bee2e38SMatthew G. Knepley . Nc - The number of function components 20534bee2e38SMatthew G. Knepley - pointEval - The function gradient values 20544bee2e38SMatthew G. Knepley 20554bee2e38SMatthew G. Knepley Output Parameter: 20564bee2e38SMatthew G. Knepley . pointEval - The transformed function gradient values 20574bee2e38SMatthew G. Knepley 20584bee2e38SMatthew G. Knepley Level: advanced 20594bee2e38SMatthew G. Knepley 20604bee2e38SMatthew G. Knepley Note: 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. 20614bee2e38SMatthew G. Knepley 2062f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 20632edcad52SToby Isaac 2064db781477SPatrick Sanan .seealso: `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2065dc0529c6SBarry Smith @*/ 20669371c9d4SSatish Balay PetscErrorCode PetscDualSpacePushforwardGradient(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) { 20674bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2068b4457527SToby Isaac PetscInt k; 20694bee2e38SMatthew G. Knepley 20704bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 20714bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 20724bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2073dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 20744bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 20754bee2e38SMatthew G. Knepley This determines their transformation properties. */ 20769566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 20779371c9d4SSatish Balay switch (k) { 20789371c9d4SSatish Balay case 0: /* H^1 point evaluations */ trans = IDENTITY_TRANSFORM; break; 20799371c9d4SSatish Balay case 1: /* Hcurl preserves tangential edge traces */ trans = COVARIANT_PIOLA_TRANSFORM; break; 2080b4457527SToby Isaac case 2: 20819371c9d4SSatish Balay case 3: /* Hdiv preserve normal traces */ trans = CONTRAVARIANT_PIOLA_TRANSFORM; break; 208263a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 20834bee2e38SMatthew G. Knepley } 20849566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformGradient(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 20854bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 20864bee2e38SMatthew G. Knepley } 2087f9244615SMatthew G. Knepley 2088f9244615SMatthew G. Knepley /*@C 2089f9244615SMatthew 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. 2090f9244615SMatthew G. Knepley 2091f9244615SMatthew G. Knepley Input Parameters: 2092f9244615SMatthew G. Knepley + dsp - The PetscDualSpace 2093f9244615SMatthew G. Knepley . fegeom - The geometry for this cell 2094f9244615SMatthew G. Knepley . Nq - The number of function Hessian samples 2095f9244615SMatthew G. Knepley . Nc - The number of function components 2096f9244615SMatthew G. Knepley - pointEval - The function gradient values 2097f9244615SMatthew G. Knepley 2098f9244615SMatthew G. Knepley Output Parameter: 2099f9244615SMatthew G. Knepley . pointEval - The transformed function Hessian values 2100f9244615SMatthew G. Knepley 2101f9244615SMatthew G. Knepley Level: advanced 2102f9244615SMatthew G. Knepley 2103f9244615SMatthew G. Knepley Note: 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. 2104f9244615SMatthew G. Knepley 2105f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2106f9244615SMatthew G. Knepley 2107db781477SPatrick Sanan .seealso: `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2108f9244615SMatthew G. Knepley @*/ 21099371c9d4SSatish Balay PetscErrorCode PetscDualSpacePushforwardHessian(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) { 2110f9244615SMatthew G. Knepley PetscDualSpaceTransformType trans; 2111f9244615SMatthew G. Knepley PetscInt k; 2112f9244615SMatthew G. Knepley 2113f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2114f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2115f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2116dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 2117f9244615SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 2118f9244615SMatthew G. Knepley This determines their transformation properties. */ 21199566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 21209371c9d4SSatish Balay switch (k) { 21219371c9d4SSatish Balay case 0: /* H^1 point evaluations */ trans = IDENTITY_TRANSFORM; break; 21229371c9d4SSatish Balay case 1: /* Hcurl preserves tangential edge traces */ trans = COVARIANT_PIOLA_TRANSFORM; break; 2123f9244615SMatthew G. Knepley case 2: 21249371c9d4SSatish Balay case 3: /* Hdiv preserve normal traces */ trans = CONTRAVARIANT_PIOLA_TRANSFORM; break; 212563a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 2126f9244615SMatthew G. Knepley } 21279566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformHessian(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 2128f9244615SMatthew G. Knepley PetscFunctionReturn(0); 2129f9244615SMatthew G. Knepley } 2130