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 */ 286f905325SMatthew G. Knepley PetscErrorCode PetscDualSpaceLatticePointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) 296f905325SMatthew G. Knepley { 306f905325SMatthew G. Knepley PetscFunctionBegin; 316f905325SMatthew G. Knepley while (len--) { 326f905325SMatthew G. Knepley max -= tup[len]; 336f905325SMatthew G. Knepley if (!max) { 346f905325SMatthew G. Knepley tup[len] = 0; 356f905325SMatthew G. Knepley break; 366f905325SMatthew G. Knepley } 376f905325SMatthew G. Knepley } 386f905325SMatthew G. Knepley tup[++len]++; 396f905325SMatthew G. Knepley PetscFunctionReturn(0); 406f905325SMatthew G. Knepley } 416f905325SMatthew G. Knepley 426f905325SMatthew G. Knepley /* 436f905325SMatthew G. Knepley PetscDualSpaceTensorPointLexicographic_Internal - Returns all tuples of size 'len' with nonnegative integers that are all less than or equal to 'max'. 446f905325SMatthew G. Knepley Ordering is lexicographic with lowest index as least significant in ordering. 456f905325SMatthew G. Knepley e.g. for len == 2 and max == 2, this will return, in order, {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0,2}, {1,2}, {2,2}. 466f905325SMatthew G. Knepley 476f905325SMatthew G. Knepley Input Parameters: 486f905325SMatthew G. Knepley + len - The length of the tuple 496f905325SMatthew G. Knepley . max - The maximum value 506f905325SMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 516f905325SMatthew G. Knepley 526f905325SMatthew G. Knepley Output Parameter: 536f905325SMatthew G. Knepley . tup - A tuple of len integers whos sum is at most 'max' 546f905325SMatthew G. Knepley 556f905325SMatthew G. Knepley Level: developer 566f905325SMatthew G. Knepley 57db781477SPatrick Sanan .seealso: `PetscDualSpaceLatticePointLexicographic_Internal()` 586f905325SMatthew G. Knepley */ 596f905325SMatthew G. Knepley PetscErrorCode PetscDualSpaceTensorPointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) 606f905325SMatthew G. Knepley { 616f905325SMatthew G. Knepley PetscInt i; 626f905325SMatthew G. Knepley 636f905325SMatthew G. Knepley PetscFunctionBegin; 646f905325SMatthew G. Knepley for (i = 0; i < len; i++) { 656f905325SMatthew G. Knepley if (tup[i] < max) { 666f905325SMatthew G. Knepley break; 676f905325SMatthew G. Knepley } else { 686f905325SMatthew G. Knepley tup[i] = 0; 696f905325SMatthew G. Knepley } 706f905325SMatthew G. Knepley } 716f905325SMatthew G. Knepley tup[i]++; 726f905325SMatthew G. Knepley PetscFunctionReturn(0); 736f905325SMatthew G. Knepley } 746f905325SMatthew G. Knepley 7520cf1dd8SToby Isaac /*@C 7620cf1dd8SToby Isaac PetscDualSpaceRegister - Adds a new PetscDualSpace implementation 7720cf1dd8SToby Isaac 7820cf1dd8SToby Isaac Not Collective 7920cf1dd8SToby Isaac 8020cf1dd8SToby Isaac Input Parameters: 8120cf1dd8SToby Isaac + name - The name of a new user-defined creation routine 8220cf1dd8SToby Isaac - create_func - The creation routine itself 8320cf1dd8SToby Isaac 8420cf1dd8SToby Isaac Notes: 8520cf1dd8SToby Isaac PetscDualSpaceRegister() may be called multiple times to add several user-defined PetscDualSpaces 8620cf1dd8SToby Isaac 8720cf1dd8SToby Isaac Sample usage: 8820cf1dd8SToby Isaac .vb 8920cf1dd8SToby Isaac PetscDualSpaceRegister("my_space", MyPetscDualSpaceCreate); 9020cf1dd8SToby Isaac .ve 9120cf1dd8SToby Isaac 9220cf1dd8SToby Isaac Then, your PetscDualSpace type can be chosen with the procedural interface via 9320cf1dd8SToby Isaac .vb 9420cf1dd8SToby Isaac PetscDualSpaceCreate(MPI_Comm, PetscDualSpace *); 9520cf1dd8SToby Isaac PetscDualSpaceSetType(PetscDualSpace, "my_dual_space"); 9620cf1dd8SToby Isaac .ve 9720cf1dd8SToby Isaac or at runtime via the option 9820cf1dd8SToby Isaac .vb 9920cf1dd8SToby Isaac -petscdualspace_type my_dual_space 10020cf1dd8SToby Isaac .ve 10120cf1dd8SToby Isaac 10220cf1dd8SToby Isaac Level: advanced 10320cf1dd8SToby Isaac 104db781477SPatrick Sanan .seealso: `PetscDualSpaceRegisterAll()`, `PetscDualSpaceRegisterDestroy()` 10520cf1dd8SToby Isaac 10620cf1dd8SToby Isaac @*/ 10720cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceRegister(const char sname[], PetscErrorCode (*function)(PetscDualSpace)) 10820cf1dd8SToby Isaac { 10920cf1dd8SToby Isaac PetscFunctionBegin; 1109566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&PetscDualSpaceList, sname, function)); 11120cf1dd8SToby Isaac PetscFunctionReturn(0); 11220cf1dd8SToby Isaac } 11320cf1dd8SToby Isaac 11420cf1dd8SToby Isaac /*@C 11520cf1dd8SToby Isaac PetscDualSpaceSetType - Builds a particular PetscDualSpace 11620cf1dd8SToby Isaac 117d083f849SBarry Smith Collective on sp 11820cf1dd8SToby Isaac 11920cf1dd8SToby Isaac Input Parameters: 12020cf1dd8SToby Isaac + sp - The PetscDualSpace object 12120cf1dd8SToby Isaac - name - The kind of space 12220cf1dd8SToby Isaac 12320cf1dd8SToby Isaac Options Database Key: 12420cf1dd8SToby Isaac . -petscdualspace_type <type> - Sets the PetscDualSpace type; use -help for a list of available types 12520cf1dd8SToby Isaac 12620cf1dd8SToby Isaac Level: intermediate 12720cf1dd8SToby Isaac 128db781477SPatrick Sanan .seealso: `PetscDualSpaceGetType()`, `PetscDualSpaceCreate()` 12920cf1dd8SToby Isaac @*/ 13020cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetType(PetscDualSpace sp, PetscDualSpaceType name) 13120cf1dd8SToby Isaac { 13220cf1dd8SToby Isaac PetscErrorCode (*r)(PetscDualSpace); 13320cf1dd8SToby Isaac PetscBool match; 13420cf1dd8SToby Isaac 13520cf1dd8SToby Isaac PetscFunctionBegin; 13620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) sp, name, &match)); 13820cf1dd8SToby Isaac if (match) PetscFunctionReturn(0); 13920cf1dd8SToby Isaac 1409566063dSJacob Faibussowitsch if (!PetscDualSpaceRegisterAllCalled) PetscCall(PetscDualSpaceRegisterAll()); 1419566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(PetscDualSpaceList, name, &r)); 14228b400f6SJacob Faibussowitsch PetscCheck(r,PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDualSpace type: %s", name); 14320cf1dd8SToby Isaac 144*dbbe0bcdSBarry Smith PetscTryTypeMethod(sp,destroy); 14520cf1dd8SToby Isaac sp->ops->destroy = NULL; 146*dbbe0bcdSBarry Smith 1479566063dSJacob Faibussowitsch PetscCall((*r)(sp)); 1489566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject) sp, name)); 14920cf1dd8SToby Isaac PetscFunctionReturn(0); 15020cf1dd8SToby Isaac } 15120cf1dd8SToby Isaac 15220cf1dd8SToby Isaac /*@C 15320cf1dd8SToby Isaac PetscDualSpaceGetType - Gets the PetscDualSpace type name (as a string) from the object. 15420cf1dd8SToby Isaac 15520cf1dd8SToby Isaac Not Collective 15620cf1dd8SToby Isaac 15720cf1dd8SToby Isaac Input Parameter: 15820cf1dd8SToby Isaac . sp - The PetscDualSpace 15920cf1dd8SToby Isaac 16020cf1dd8SToby Isaac Output Parameter: 16120cf1dd8SToby Isaac . name - The PetscDualSpace type name 16220cf1dd8SToby Isaac 16320cf1dd8SToby Isaac Level: intermediate 16420cf1dd8SToby Isaac 165db781477SPatrick Sanan .seealso: `PetscDualSpaceSetType()`, `PetscDualSpaceCreate()` 16620cf1dd8SToby Isaac @*/ 16720cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetType(PetscDualSpace sp, PetscDualSpaceType *name) 16820cf1dd8SToby Isaac { 16920cf1dd8SToby Isaac PetscFunctionBegin; 17020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 17120cf1dd8SToby Isaac PetscValidPointer(name, 2); 17220cf1dd8SToby Isaac if (!PetscDualSpaceRegisterAllCalled) { 1739566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceRegisterAll()); 17420cf1dd8SToby Isaac } 17520cf1dd8SToby Isaac *name = ((PetscObject) sp)->type_name; 17620cf1dd8SToby Isaac PetscFunctionReturn(0); 17720cf1dd8SToby Isaac } 17820cf1dd8SToby Isaac 179221d6281SMatthew G. Knepley static PetscErrorCode PetscDualSpaceView_ASCII(PetscDualSpace sp, PetscViewer v) 180221d6281SMatthew G. Knepley { 181221d6281SMatthew G. Knepley PetscViewerFormat format; 182221d6281SMatthew G. Knepley PetscInt pdim, f; 183221d6281SMatthew G. Knepley 184221d6281SMatthew G. Knepley PetscFunctionBegin; 1859566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &pdim)); 1869566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject) sp, v)); 1879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 188b4457527SToby Isaac if (sp->k) { 18963a3b9bcSJacob 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)); 190b4457527SToby Isaac } else { 19163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual space with %" PetscInt_FMT " components, size %" PetscInt_FMT "\n", sp->Nc, pdim)); 192b4457527SToby Isaac } 193*dbbe0bcdSBarry Smith PetscTryTypeMethod(sp,view, v); 1949566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(v, &format)); 195221d6281SMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 197221d6281SMatthew G. Knepley for (f = 0; f < pdim; ++f) { 19863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual basis vector %" PetscInt_FMT "\n", f)); 1999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 2009566063dSJacob Faibussowitsch PetscCall(PetscQuadratureView(sp->functional[f], v)); 2019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 202221d6281SMatthew G. Knepley } 2039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 204221d6281SMatthew G. Knepley } 2059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 206221d6281SMatthew G. Knepley PetscFunctionReturn(0); 207221d6281SMatthew G. Knepley } 208221d6281SMatthew G. Knepley 209fe2efc57SMark /*@C 210fe2efc57SMark PetscDualSpaceViewFromOptions - View from Options 211fe2efc57SMark 212fe2efc57SMark Collective on PetscDualSpace 213fe2efc57SMark 214fe2efc57SMark Input Parameters: 215fe2efc57SMark + A - the PetscDualSpace object 216736c3998SJose E. Roman . obj - Optional object, proivides prefix 217736c3998SJose E. Roman - name - command line option 218fe2efc57SMark 219fe2efc57SMark Level: intermediate 220db781477SPatrick Sanan .seealso: `PetscDualSpace`, `PetscDualSpaceView()`, `PetscObjectViewFromOptions()`, `PetscDualSpaceCreate()` 221fe2efc57SMark @*/ 222fe2efc57SMark PetscErrorCode PetscDualSpaceViewFromOptions(PetscDualSpace A,PetscObject obj,const char name[]) 223fe2efc57SMark { 224fe2efc57SMark PetscFunctionBegin; 225fe2efc57SMark PetscValidHeaderSpecific(A,PETSCDUALSPACE_CLASSID,1); 2269566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name)); 227fe2efc57SMark PetscFunctionReturn(0); 228fe2efc57SMark } 229fe2efc57SMark 23020cf1dd8SToby Isaac /*@ 23120cf1dd8SToby Isaac PetscDualSpaceView - Views a PetscDualSpace 23220cf1dd8SToby Isaac 233d083f849SBarry Smith Collective on sp 23420cf1dd8SToby Isaac 235d8d19677SJose E. Roman Input Parameters: 23620cf1dd8SToby Isaac + sp - the PetscDualSpace object to view 23720cf1dd8SToby Isaac - v - the viewer 23820cf1dd8SToby Isaac 239a4ce7ad1SMatthew G. Knepley Level: beginner 24020cf1dd8SToby Isaac 241db781477SPatrick Sanan .seealso `PetscDualSpaceDestroy()`, `PetscDualSpace` 24220cf1dd8SToby Isaac @*/ 24320cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceView(PetscDualSpace sp, PetscViewer v) 24420cf1dd8SToby Isaac { 245d9bac1caSLisandro Dalcin PetscBool iascii; 24620cf1dd8SToby Isaac 24720cf1dd8SToby Isaac PetscFunctionBegin; 24820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 249d9bac1caSLisandro Dalcin if (v) PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2); 2509566063dSJacob Faibussowitsch if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) sp), &v)); 2519566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii)); 2529566063dSJacob Faibussowitsch if (iascii) PetscCall(PetscDualSpaceView_ASCII(sp, v)); 25320cf1dd8SToby Isaac PetscFunctionReturn(0); 25420cf1dd8SToby Isaac } 25520cf1dd8SToby Isaac 25620cf1dd8SToby Isaac /*@ 25720cf1dd8SToby Isaac PetscDualSpaceSetFromOptions - sets parameters in a PetscDualSpace from the options database 25820cf1dd8SToby Isaac 259d083f849SBarry Smith Collective on sp 26020cf1dd8SToby Isaac 26120cf1dd8SToby Isaac Input Parameter: 26220cf1dd8SToby Isaac . sp - the PetscDualSpace object to set options for 26320cf1dd8SToby Isaac 26420cf1dd8SToby Isaac Options Database: 2658f2aacc6SMatthew G. Knepley + -petscdualspace_order <order> - the approximation order of the space 266fe36a153SMatthew G. Knepley . -petscdualspace_form_degree <deg> - the form degree, say 0 for point evaluations, or 2 for area integrals 2678f2aacc6SMatthew G. Knepley . -petscdualspace_components <c> - the number of components, say d for a vector field 2688f2aacc6SMatthew G. Knepley - -petscdualspace_refcell <celltype> - Reference cell type name 26920cf1dd8SToby Isaac 270a4ce7ad1SMatthew G. Knepley Level: intermediate 27120cf1dd8SToby Isaac 272db781477SPatrick Sanan .seealso `PetscDualSpaceView()`, `PetscDualSpace`, `PetscObjectSetFromOptions()` 27320cf1dd8SToby Isaac @*/ 27420cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetFromOptions(PetscDualSpace sp) 27520cf1dd8SToby Isaac { 2762df84da0SMatthew G. Knepley DMPolytopeType refCell = DM_POLYTOPE_TRIANGLE; 27720cf1dd8SToby Isaac const char *defaultType; 27820cf1dd8SToby Isaac char name[256]; 279f783ec47SMatthew G. Knepley PetscBool flg; 28020cf1dd8SToby Isaac 28120cf1dd8SToby Isaac PetscFunctionBegin; 28220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 28320cf1dd8SToby Isaac if (!((PetscObject) sp)->type_name) { 28420cf1dd8SToby Isaac defaultType = PETSCDUALSPACELAGRANGE; 28520cf1dd8SToby Isaac } else { 28620cf1dd8SToby Isaac defaultType = ((PetscObject) sp)->type_name; 28720cf1dd8SToby Isaac } 2889566063dSJacob Faibussowitsch if (!PetscSpaceRegisterAllCalled) PetscCall(PetscSpaceRegisterAll()); 28920cf1dd8SToby Isaac 290d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject) sp); 2919566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-petscdualspace_type", "Dual space", "PetscDualSpaceSetType", PetscDualSpaceList, defaultType, name, 256, &flg)); 29220cf1dd8SToby Isaac if (flg) { 2939566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, name)); 29420cf1dd8SToby Isaac } else if (!((PetscObject) sp)->type_name) { 2959566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, defaultType)); 29620cf1dd8SToby Isaac } 2979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_order", "The approximation order", "PetscDualSpaceSetOrder", sp->order, &sp->order, NULL,0)); 2989566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-petscdualspace_form_degree", "The form degree of the dofs", "PetscDualSpaceSetFormDegree", sp->k, &sp->k, NULL)); 2999566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_components", "The number of components", "PetscDualSpaceSetNumComponents", sp->Nc, &sp->Nc, NULL,1)); 300*dbbe0bcdSBarry Smith PetscTryTypeMethod(sp,setfromoptions,PetscOptionsObject); 3019566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-petscdualspace_refcell", "Reference cell shape", "PetscDualSpaceSetReferenceCell", DMPolytopeTypes, (PetscEnum) refCell, (PetscEnum *) &refCell, &flg)); 302063ee4adSMatthew G. Knepley if (flg) { 303063ee4adSMatthew G. Knepley DM K; 304063ee4adSMatthew G. Knepley 3059566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, refCell, &K)); 3069566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(sp, K)); 3079566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 308063ee4adSMatthew G. Knepley } 309063ee4adSMatthew G. Knepley 31020cf1dd8SToby Isaac /* process any options handlers added with PetscObjectAddOptionsHandler() */ 311*dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject) sp,PetscOptionsObject)); 312d0609cedSBarry Smith PetscOptionsEnd(); 313063ee4adSMatthew G. Knepley sp->setfromoptionscalled = PETSC_TRUE; 31420cf1dd8SToby Isaac PetscFunctionReturn(0); 31520cf1dd8SToby Isaac } 31620cf1dd8SToby Isaac 31720cf1dd8SToby Isaac /*@ 31820cf1dd8SToby Isaac PetscDualSpaceSetUp - Construct a basis for the PetscDualSpace 31920cf1dd8SToby Isaac 320d083f849SBarry Smith Collective on sp 32120cf1dd8SToby Isaac 32220cf1dd8SToby Isaac Input Parameter: 32320cf1dd8SToby Isaac . sp - the PetscDualSpace object to setup 32420cf1dd8SToby Isaac 325a4ce7ad1SMatthew G. Knepley Level: intermediate 32620cf1dd8SToby Isaac 327db781477SPatrick Sanan .seealso `PetscDualSpaceView()`, `PetscDualSpaceDestroy()`, `PetscDualSpace` 32820cf1dd8SToby Isaac @*/ 32920cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetUp(PetscDualSpace sp) 33020cf1dd8SToby Isaac { 33120cf1dd8SToby Isaac PetscFunctionBegin; 33220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 33320cf1dd8SToby Isaac if (sp->setupcalled) PetscFunctionReturn(0); 3349566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 33520cf1dd8SToby Isaac sp->setupcalled = PETSC_TRUE; 336*dbbe0bcdSBarry Smith PetscTryTypeMethod(sp,setup); 3379566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 3389566063dSJacob Faibussowitsch if (sp->setfromoptionscalled) PetscCall(PetscDualSpaceViewFromOptions(sp, NULL, "-petscdualspace_view")); 33920cf1dd8SToby Isaac PetscFunctionReturn(0); 34020cf1dd8SToby Isaac } 34120cf1dd8SToby Isaac 342b4457527SToby Isaac static PetscErrorCode PetscDualSpaceClearDMData_Internal(PetscDualSpace sp, DM dm) 343b4457527SToby Isaac { 344b4457527SToby Isaac PetscInt pStart = -1, pEnd = -1, depth = -1; 345b4457527SToby Isaac 346b4457527SToby Isaac PetscFunctionBegin; 347b4457527SToby Isaac if (!dm) PetscFunctionReturn(0); 3489566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 350b4457527SToby Isaac 351b4457527SToby Isaac if (sp->pointSpaces) { 352b4457527SToby Isaac PetscInt i; 353b4457527SToby Isaac 354b4457527SToby Isaac for (i = 0; i < pEnd - pStart; i++) { 3559566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceDestroy(&(sp->pointSpaces[i]))); 356b4457527SToby Isaac } 357b4457527SToby Isaac } 3589566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->pointSpaces)); 359b4457527SToby Isaac 360b4457527SToby Isaac if (sp->heightSpaces) { 361b4457527SToby Isaac PetscInt i; 362b4457527SToby Isaac 363b4457527SToby Isaac for (i = 0; i <= depth; i++) { 3649566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceDestroy(&(sp->heightSpaces[i]))); 365b4457527SToby Isaac } 366b4457527SToby Isaac } 3679566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->heightSpaces)); 368b4457527SToby Isaac 3699566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(sp->pointSection))); 3709566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->intNodes))); 3719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->intDofValues))); 3729566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->intNodeValues))); 3739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->intMat))); 3749566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->allNodes))); 3759566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->allDofValues))); 3769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->allNodeValues))); 3779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->allMat))); 3789566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->numDof)); 379b4457527SToby Isaac PetscFunctionReturn(0); 380b4457527SToby Isaac } 381b4457527SToby Isaac 38220cf1dd8SToby Isaac /*@ 38320cf1dd8SToby Isaac PetscDualSpaceDestroy - Destroys a PetscDualSpace object 38420cf1dd8SToby Isaac 385d083f849SBarry Smith Collective on sp 38620cf1dd8SToby Isaac 38720cf1dd8SToby Isaac Input Parameter: 38820cf1dd8SToby Isaac . sp - the PetscDualSpace object to destroy 38920cf1dd8SToby Isaac 390a4ce7ad1SMatthew G. Knepley Level: beginner 39120cf1dd8SToby Isaac 392db781477SPatrick Sanan .seealso `PetscDualSpaceView()`, `PetscDualSpace()`, `PetscDualSpaceCreate()` 39320cf1dd8SToby Isaac @*/ 39420cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceDestroy(PetscDualSpace *sp) 39520cf1dd8SToby Isaac { 39620cf1dd8SToby Isaac PetscInt dim, f; 397b4457527SToby Isaac DM dm; 39820cf1dd8SToby Isaac 39920cf1dd8SToby Isaac PetscFunctionBegin; 40020cf1dd8SToby Isaac if (!*sp) PetscFunctionReturn(0); 40120cf1dd8SToby Isaac PetscValidHeaderSpecific((*sp), PETSCDUALSPACE_CLASSID, 1); 40220cf1dd8SToby Isaac 403ea78f98cSLisandro Dalcin if (--((PetscObject)(*sp))->refct > 0) {*sp = NULL; PetscFunctionReturn(0);} 40420cf1dd8SToby Isaac ((PetscObject) (*sp))->refct = 0; 40520cf1dd8SToby Isaac 4069566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(*sp, &dim)); 407b4457527SToby Isaac dm = (*sp)->dm; 408b4457527SToby Isaac 409*dbbe0bcdSBarry Smith PetscTryTypeMethod((*sp),destroy); 4109566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceClearDMData_Internal(*sp, dm)); 411b4457527SToby Isaac 41220cf1dd8SToby Isaac for (f = 0; f < dim; ++f) { 4139566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(*sp)->functional[f])); 41420cf1dd8SToby Isaac } 4159566063dSJacob Faibussowitsch PetscCall(PetscFree((*sp)->functional)); 4169566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*sp)->dm)); 4179566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(sp)); 41820cf1dd8SToby Isaac PetscFunctionReturn(0); 41920cf1dd8SToby Isaac } 42020cf1dd8SToby Isaac 42120cf1dd8SToby Isaac /*@ 42220cf1dd8SToby Isaac PetscDualSpaceCreate - Creates an empty PetscDualSpace object. The type can then be set with PetscDualSpaceSetType(). 42320cf1dd8SToby Isaac 424d083f849SBarry Smith Collective 42520cf1dd8SToby Isaac 42620cf1dd8SToby Isaac Input Parameter: 42720cf1dd8SToby Isaac . comm - The communicator for the PetscDualSpace object 42820cf1dd8SToby Isaac 42920cf1dd8SToby Isaac Output Parameter: 43020cf1dd8SToby Isaac . sp - The PetscDualSpace object 43120cf1dd8SToby Isaac 43220cf1dd8SToby Isaac Level: beginner 43320cf1dd8SToby Isaac 434db781477SPatrick Sanan .seealso: `PetscDualSpaceSetType()`, `PETSCDUALSPACELAGRANGE` 43520cf1dd8SToby Isaac @*/ 43620cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceCreate(MPI_Comm comm, PetscDualSpace *sp) 43720cf1dd8SToby Isaac { 43820cf1dd8SToby Isaac PetscDualSpace s; 43920cf1dd8SToby Isaac 44020cf1dd8SToby Isaac PetscFunctionBegin; 44120cf1dd8SToby Isaac PetscValidPointer(sp, 2); 4429566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(FECitation,&FEcite)); 44320cf1dd8SToby Isaac *sp = NULL; 4449566063dSJacob Faibussowitsch PetscCall(PetscFEInitializePackage()); 44520cf1dd8SToby Isaac 4469566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(s, PETSCDUALSPACE_CLASSID, "PetscDualSpace", "Dual Space", "PetscDualSpace", comm, PetscDualSpaceDestroy, PetscDualSpaceView)); 44720cf1dd8SToby Isaac 44820cf1dd8SToby Isaac s->order = 0; 44920cf1dd8SToby Isaac s->Nc = 1; 4504bee2e38SMatthew G. Knepley s->k = 0; 451b4457527SToby Isaac s->spdim = -1; 452b4457527SToby Isaac s->spintdim = -1; 453b4457527SToby Isaac s->uniform = PETSC_TRUE; 45420cf1dd8SToby Isaac s->setupcalled = PETSC_FALSE; 45520cf1dd8SToby Isaac 45620cf1dd8SToby Isaac *sp = s; 45720cf1dd8SToby Isaac PetscFunctionReturn(0); 45820cf1dd8SToby Isaac } 45920cf1dd8SToby Isaac 46020cf1dd8SToby Isaac /*@ 46120cf1dd8SToby Isaac PetscDualSpaceDuplicate - Creates a duplicate PetscDualSpace object, however it is not setup. 46220cf1dd8SToby Isaac 463d083f849SBarry Smith Collective on sp 46420cf1dd8SToby Isaac 46520cf1dd8SToby Isaac Input Parameter: 46620cf1dd8SToby Isaac . sp - The original PetscDualSpace 46720cf1dd8SToby Isaac 46820cf1dd8SToby Isaac Output Parameter: 46920cf1dd8SToby Isaac . spNew - The duplicate PetscDualSpace 47020cf1dd8SToby Isaac 47120cf1dd8SToby Isaac Level: beginner 47220cf1dd8SToby Isaac 473db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `PetscDualSpaceSetType()` 47420cf1dd8SToby Isaac @*/ 47520cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceDuplicate(PetscDualSpace sp, PetscDualSpace *spNew) 47620cf1dd8SToby Isaac { 477b4457527SToby Isaac DM dm; 478b4457527SToby Isaac PetscDualSpaceType type; 479b4457527SToby Isaac const char *name; 48020cf1dd8SToby Isaac 48120cf1dd8SToby Isaac PetscFunctionBegin; 48220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 48320cf1dd8SToby Isaac PetscValidPointer(spNew, 2); 4849566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(PetscObjectComm((PetscObject)sp), spNew)); 4859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) sp, &name)); 4869566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) *spNew, name)); 4879566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetType(sp, &type)); 4889566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(*spNew, type)); 4899566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 4909566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(*spNew, dm)); 491b4457527SToby Isaac 492b4457527SToby Isaac (*spNew)->order = sp->order; 493b4457527SToby Isaac (*spNew)->k = sp->k; 494b4457527SToby Isaac (*spNew)->Nc = sp->Nc; 495b4457527SToby Isaac (*spNew)->uniform = sp->uniform; 496*dbbe0bcdSBarry Smith PetscTryTypeMethod(sp,duplicate , *spNew); 49720cf1dd8SToby Isaac PetscFunctionReturn(0); 49820cf1dd8SToby Isaac } 49920cf1dd8SToby Isaac 50020cf1dd8SToby Isaac /*@ 50120cf1dd8SToby Isaac PetscDualSpaceGetDM - Get the DM representing the reference cell 50220cf1dd8SToby Isaac 50320cf1dd8SToby Isaac Not collective 50420cf1dd8SToby Isaac 50520cf1dd8SToby Isaac Input Parameter: 50620cf1dd8SToby Isaac . sp - The PetscDualSpace 50720cf1dd8SToby Isaac 50820cf1dd8SToby Isaac Output Parameter: 50920cf1dd8SToby Isaac . dm - The reference cell 51020cf1dd8SToby Isaac 51120cf1dd8SToby Isaac Level: intermediate 51220cf1dd8SToby Isaac 513db781477SPatrick Sanan .seealso: `PetscDualSpaceSetDM()`, `PetscDualSpaceCreate()` 51420cf1dd8SToby Isaac @*/ 51520cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetDM(PetscDualSpace sp, DM *dm) 51620cf1dd8SToby Isaac { 51720cf1dd8SToby Isaac PetscFunctionBegin; 51820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 51920cf1dd8SToby Isaac PetscValidPointer(dm, 2); 52020cf1dd8SToby Isaac *dm = sp->dm; 52120cf1dd8SToby Isaac PetscFunctionReturn(0); 52220cf1dd8SToby Isaac } 52320cf1dd8SToby Isaac 52420cf1dd8SToby Isaac /*@ 52520cf1dd8SToby Isaac PetscDualSpaceSetDM - Get the DM representing the reference cell 52620cf1dd8SToby Isaac 52720cf1dd8SToby Isaac Not collective 52820cf1dd8SToby Isaac 52920cf1dd8SToby Isaac Input Parameters: 53020cf1dd8SToby Isaac + sp - The PetscDualSpace 53120cf1dd8SToby Isaac - dm - The reference cell 53220cf1dd8SToby Isaac 53320cf1dd8SToby Isaac Level: intermediate 53420cf1dd8SToby Isaac 535db781477SPatrick Sanan .seealso: `PetscDualSpaceGetDM()`, `PetscDualSpaceCreate()` 53620cf1dd8SToby Isaac @*/ 53720cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetDM(PetscDualSpace sp, DM dm) 53820cf1dd8SToby Isaac { 53920cf1dd8SToby Isaac PetscFunctionBegin; 54020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 54120cf1dd8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 54228b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled,PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change DM after dualspace is set up"); 5439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) dm)); 544b4457527SToby Isaac if (sp->dm && sp->dm != dm) { 5459566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceClearDMData_Internal(sp, sp->dm)); 546b4457527SToby Isaac } 5479566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sp->dm)); 54820cf1dd8SToby Isaac sp->dm = dm; 54920cf1dd8SToby Isaac PetscFunctionReturn(0); 55020cf1dd8SToby Isaac } 55120cf1dd8SToby Isaac 55220cf1dd8SToby Isaac /*@ 55320cf1dd8SToby Isaac PetscDualSpaceGetOrder - Get the order of the dual space 55420cf1dd8SToby Isaac 55520cf1dd8SToby Isaac Not collective 55620cf1dd8SToby Isaac 55720cf1dd8SToby Isaac Input Parameter: 55820cf1dd8SToby Isaac . sp - The PetscDualSpace 55920cf1dd8SToby Isaac 56020cf1dd8SToby Isaac Output Parameter: 56120cf1dd8SToby Isaac . order - The order 56220cf1dd8SToby Isaac 56320cf1dd8SToby Isaac Level: intermediate 56420cf1dd8SToby Isaac 565db781477SPatrick Sanan .seealso: `PetscDualSpaceSetOrder()`, `PetscDualSpaceCreate()` 56620cf1dd8SToby Isaac @*/ 56720cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetOrder(PetscDualSpace sp, PetscInt *order) 56820cf1dd8SToby Isaac { 56920cf1dd8SToby Isaac PetscFunctionBegin; 57020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 571dadcf809SJacob Faibussowitsch PetscValidIntPointer(order, 2); 57220cf1dd8SToby Isaac *order = sp->order; 57320cf1dd8SToby Isaac PetscFunctionReturn(0); 57420cf1dd8SToby Isaac } 57520cf1dd8SToby Isaac 57620cf1dd8SToby Isaac /*@ 57720cf1dd8SToby Isaac PetscDualSpaceSetOrder - Set the order of the dual space 57820cf1dd8SToby Isaac 57920cf1dd8SToby Isaac Not collective 58020cf1dd8SToby Isaac 58120cf1dd8SToby Isaac Input Parameters: 58220cf1dd8SToby Isaac + sp - The PetscDualSpace 58320cf1dd8SToby Isaac - order - The order 58420cf1dd8SToby Isaac 58520cf1dd8SToby Isaac Level: intermediate 58620cf1dd8SToby Isaac 587db781477SPatrick Sanan .seealso: `PetscDualSpaceGetOrder()`, `PetscDualSpaceCreate()` 58820cf1dd8SToby Isaac @*/ 58920cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetOrder(PetscDualSpace sp, PetscInt order) 59020cf1dd8SToby Isaac { 59120cf1dd8SToby Isaac PetscFunctionBegin; 59220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 59328b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled,PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change order after dualspace is set up"); 59420cf1dd8SToby Isaac sp->order = order; 59520cf1dd8SToby Isaac PetscFunctionReturn(0); 59620cf1dd8SToby Isaac } 59720cf1dd8SToby Isaac 59820cf1dd8SToby Isaac /*@ 59920cf1dd8SToby Isaac PetscDualSpaceGetNumComponents - Return the number of components for this space 60020cf1dd8SToby Isaac 60120cf1dd8SToby Isaac Input Parameter: 60220cf1dd8SToby Isaac . sp - The PetscDualSpace 60320cf1dd8SToby Isaac 60420cf1dd8SToby Isaac Output Parameter: 60520cf1dd8SToby Isaac . Nc - The number of components 60620cf1dd8SToby Isaac 60720cf1dd8SToby Isaac Note: A vector space, for example, will have d components, where d is the spatial dimension 60820cf1dd8SToby Isaac 60920cf1dd8SToby Isaac Level: intermediate 61020cf1dd8SToby Isaac 611db781477SPatrick Sanan .seealso: `PetscDualSpaceSetNumComponents()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 61220cf1dd8SToby Isaac @*/ 61320cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetNumComponents(PetscDualSpace sp, PetscInt *Nc) 61420cf1dd8SToby Isaac { 61520cf1dd8SToby Isaac PetscFunctionBegin; 61620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 617dadcf809SJacob Faibussowitsch PetscValidIntPointer(Nc, 2); 61820cf1dd8SToby Isaac *Nc = sp->Nc; 61920cf1dd8SToby Isaac PetscFunctionReturn(0); 62020cf1dd8SToby Isaac } 62120cf1dd8SToby Isaac 62220cf1dd8SToby Isaac /*@ 62320cf1dd8SToby Isaac PetscDualSpaceSetNumComponents - Set the number of components for this space 62420cf1dd8SToby Isaac 62520cf1dd8SToby Isaac Input Parameters: 62620cf1dd8SToby Isaac + sp - The PetscDualSpace 62720cf1dd8SToby Isaac - order - The number of components 62820cf1dd8SToby Isaac 62920cf1dd8SToby Isaac Level: intermediate 63020cf1dd8SToby Isaac 631db781477SPatrick Sanan .seealso: `PetscDualSpaceGetNumComponents()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 63220cf1dd8SToby Isaac @*/ 63320cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetNumComponents(PetscDualSpace sp, PetscInt Nc) 63420cf1dd8SToby Isaac { 63520cf1dd8SToby Isaac PetscFunctionBegin; 63620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 63728b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled,PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 63820cf1dd8SToby Isaac sp->Nc = Nc; 63920cf1dd8SToby Isaac PetscFunctionReturn(0); 64020cf1dd8SToby Isaac } 64120cf1dd8SToby Isaac 64220cf1dd8SToby Isaac /*@ 64320cf1dd8SToby Isaac PetscDualSpaceGetFunctional - Get the i-th basis functional in the dual space 64420cf1dd8SToby Isaac 64520cf1dd8SToby Isaac Not collective 64620cf1dd8SToby Isaac 64720cf1dd8SToby Isaac Input Parameters: 64820cf1dd8SToby Isaac + sp - The PetscDualSpace 64920cf1dd8SToby Isaac - i - The basis number 65020cf1dd8SToby Isaac 65120cf1dd8SToby Isaac Output Parameter: 65220cf1dd8SToby Isaac . functional - The basis functional 65320cf1dd8SToby Isaac 65420cf1dd8SToby Isaac Level: intermediate 65520cf1dd8SToby Isaac 656db781477SPatrick Sanan .seealso: `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()` 65720cf1dd8SToby Isaac @*/ 65820cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetFunctional(PetscDualSpace sp, PetscInt i, PetscQuadrature *functional) 65920cf1dd8SToby Isaac { 66020cf1dd8SToby Isaac PetscInt dim; 66120cf1dd8SToby Isaac 66220cf1dd8SToby Isaac PetscFunctionBegin; 66320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 66420cf1dd8SToby Isaac PetscValidPointer(functional, 3); 6659566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &dim)); 66663a3b9bcSJacob 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); 66720cf1dd8SToby Isaac *functional = sp->functional[i]; 66820cf1dd8SToby Isaac PetscFunctionReturn(0); 66920cf1dd8SToby Isaac } 67020cf1dd8SToby Isaac 67120cf1dd8SToby Isaac /*@ 67220cf1dd8SToby Isaac PetscDualSpaceGetDimension - Get the dimension of the dual space, i.e. the number of basis functionals 67320cf1dd8SToby Isaac 67420cf1dd8SToby Isaac Not collective 67520cf1dd8SToby Isaac 67620cf1dd8SToby Isaac Input Parameter: 67720cf1dd8SToby Isaac . sp - The PetscDualSpace 67820cf1dd8SToby Isaac 67920cf1dd8SToby Isaac Output Parameter: 68020cf1dd8SToby Isaac . dim - The dimension 68120cf1dd8SToby Isaac 68220cf1dd8SToby Isaac Level: intermediate 68320cf1dd8SToby Isaac 684db781477SPatrick Sanan .seealso: `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 68520cf1dd8SToby Isaac @*/ 68620cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetDimension(PetscDualSpace sp, PetscInt *dim) 68720cf1dd8SToby Isaac { 68820cf1dd8SToby Isaac PetscFunctionBegin; 68920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 690dadcf809SJacob Faibussowitsch PetscValidIntPointer(dim, 2); 691b4457527SToby Isaac if (sp->spdim < 0) { 692b4457527SToby Isaac PetscSection section; 693b4457527SToby Isaac 6949566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 695b4457527SToby Isaac if (section) { 6969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &(sp->spdim))); 697b4457527SToby Isaac } else sp->spdim = 0; 698b4457527SToby Isaac } 699b4457527SToby Isaac *dim = sp->spdim; 70020cf1dd8SToby Isaac PetscFunctionReturn(0); 70120cf1dd8SToby Isaac } 70220cf1dd8SToby Isaac 703b4457527SToby Isaac /*@ 704b4457527SToby 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 705b4457527SToby Isaac 706b4457527SToby Isaac Not collective 707b4457527SToby Isaac 708b4457527SToby Isaac Input Parameter: 709b4457527SToby Isaac . sp - The PetscDualSpace 710b4457527SToby Isaac 711b4457527SToby Isaac Output Parameter: 712b4457527SToby Isaac . dim - The dimension 713b4457527SToby Isaac 714b4457527SToby Isaac Level: intermediate 715b4457527SToby Isaac 716db781477SPatrick Sanan .seealso: `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 717b4457527SToby Isaac @*/ 718b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetInteriorDimension(PetscDualSpace sp, PetscInt *intdim) 719b4457527SToby Isaac { 720b4457527SToby Isaac PetscFunctionBegin; 721b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 722dadcf809SJacob Faibussowitsch PetscValidIntPointer(intdim, 2); 723b4457527SToby Isaac if (sp->spintdim < 0) { 724b4457527SToby Isaac PetscSection section; 725b4457527SToby Isaac 7269566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 727b4457527SToby Isaac if (section) { 7289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &(sp->spintdim))); 729b4457527SToby Isaac } else sp->spintdim = 0; 730b4457527SToby Isaac } 731b4457527SToby Isaac *intdim = sp->spintdim; 732b4457527SToby Isaac PetscFunctionReturn(0); 733b4457527SToby Isaac } 734b4457527SToby Isaac 735b4457527SToby Isaac /*@ 736b4457527SToby Isaac PetscDualSpaceGetUniform - Whether this dual space is uniform 737b4457527SToby Isaac 738b4457527SToby Isaac Not collective 739b4457527SToby Isaac 740b4457527SToby Isaac Input Parameters: 741b4457527SToby Isaac . sp - A dual space 742b4457527SToby Isaac 743b4457527SToby Isaac Output Parameters: 744b4457527SToby Isaac . uniform - PETSC_TRUE if (a) the dual space is the same for each point in a stratum of the reference DMPlex, and 745b4457527SToby Isaac (b) every symmetry of each point in the reference DMPlex is also a symmetry of the point's dual space. 746b4457527SToby Isaac 747b4457527SToby Isaac Level: advanced 748b4457527SToby Isaac 749b4457527SToby Isaac Note: all of the usual spaces on simplex or tensor-product elements will be uniform, only reference cells 750b4457527SToby Isaac with non-uniform strata (like trianguar-prisms) or anisotropic hp dual spaces will not be uniform. 751b4457527SToby Isaac 752db781477SPatrick Sanan .seealso: `PetscDualSpaceGetPointSubspace()`, `PetscDualSpaceGetSymmetries()` 753b4457527SToby Isaac @*/ 754b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetUniform(PetscDualSpace sp, PetscBool *uniform) 755b4457527SToby Isaac { 756b4457527SToby Isaac PetscFunctionBegin; 757b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 758dadcf809SJacob Faibussowitsch PetscValidBoolPointer(uniform, 2); 759b4457527SToby Isaac *uniform = sp->uniform; 760b4457527SToby Isaac PetscFunctionReturn(0); 761b4457527SToby Isaac } 762b4457527SToby Isaac 76320cf1dd8SToby Isaac /*@C 76420cf1dd8SToby Isaac PetscDualSpaceGetNumDof - Get the number of degrees of freedom for each spatial (topological) dimension 76520cf1dd8SToby Isaac 76620cf1dd8SToby Isaac Not collective 76720cf1dd8SToby Isaac 76820cf1dd8SToby Isaac Input Parameter: 76920cf1dd8SToby Isaac . sp - The PetscDualSpace 77020cf1dd8SToby Isaac 77120cf1dd8SToby Isaac Output Parameter: 77220cf1dd8SToby Isaac . numDof - An array of length dim+1 which holds the number of dofs for each dimension 77320cf1dd8SToby Isaac 77420cf1dd8SToby Isaac Level: intermediate 77520cf1dd8SToby Isaac 776db781477SPatrick Sanan .seealso: `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 77720cf1dd8SToby Isaac @*/ 77820cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetNumDof(PetscDualSpace sp, const PetscInt **numDof) 77920cf1dd8SToby Isaac { 78020cf1dd8SToby Isaac PetscFunctionBegin; 78120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 78220cf1dd8SToby Isaac PetscValidPointer(numDof, 2); 78328b400f6SJacob 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"); 784b4457527SToby Isaac if (!sp->numDof) { 785b4457527SToby Isaac DM dm; 786b4457527SToby Isaac PetscInt depth, d; 787b4457527SToby Isaac PetscSection section; 788b4457527SToby Isaac 7899566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 7909566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 7919566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth+1,&(sp->numDof))); 7929566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 793b4457527SToby Isaac for (d = 0; d <= depth; d++) { 794b4457527SToby Isaac PetscInt dStart, dEnd; 795b4457527SToby Isaac 7969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 797b4457527SToby Isaac if (dEnd <= dStart) continue; 7989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, dStart, &(sp->numDof[d]))); 799b4457527SToby Isaac 800b4457527SToby Isaac } 801b4457527SToby Isaac } 802b4457527SToby Isaac *numDof = sp->numDof; 80308401ef6SPierre Jolivet PetscCheck(*numDof,PetscObjectComm((PetscObject) sp), PETSC_ERR_LIB, "Empty numDof[] returned from dual space implementation"); 80420cf1dd8SToby Isaac PetscFunctionReturn(0); 80520cf1dd8SToby Isaac } 80620cf1dd8SToby Isaac 807b4457527SToby Isaac /* create the section of the right size and set a permutation for topological ordering */ 808b4457527SToby Isaac PetscErrorCode PetscDualSpaceSectionCreate_Internal(PetscDualSpace sp, PetscSection *topSection) 809b4457527SToby Isaac { 810b4457527SToby Isaac DM dm; 811b4457527SToby Isaac PetscInt pStart, pEnd, cStart, cEnd, c, depth, count, i; 812b4457527SToby Isaac PetscInt *seen, *perm; 813b4457527SToby Isaac PetscSection section; 814b4457527SToby Isaac 815b4457527SToby Isaac PetscFunctionBegin; 816b4457527SToby Isaac dm = sp->dm; 8179566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion)); 8189566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 8209566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &seen)); 8219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &perm)); 8229566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8239566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 824b4457527SToby Isaac for (c = cStart, count = 0; c < cEnd; c++) { 825b4457527SToby Isaac PetscInt closureSize = -1, e; 826b4457527SToby Isaac PetscInt *closure = NULL; 827b4457527SToby Isaac 828b4457527SToby Isaac perm[count++] = c; 829b4457527SToby Isaac seen[c-pStart] = 1; 8309566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 831b4457527SToby Isaac for (e = 0; e < closureSize; e++) { 832b4457527SToby Isaac PetscInt point = closure[2*e]; 833b4457527SToby Isaac 834b4457527SToby Isaac if (seen[point-pStart]) continue; 835b4457527SToby Isaac perm[count++] = point; 836b4457527SToby Isaac seen[point-pStart] = 1; 837b4457527SToby Isaac } 8389566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 839b4457527SToby Isaac } 8401dca8a05SBarry Smith PetscCheck(count == pEnd - pStart,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad topological ordering"); 841b4457527SToby Isaac for (i = 0; i < pEnd - pStart; i++) if (perm[i] != i) break; 842b4457527SToby Isaac if (i < pEnd - pStart) { 843b4457527SToby Isaac IS permIS; 844b4457527SToby Isaac 8459566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pEnd - pStart, perm, PETSC_OWN_POINTER, &permIS)); 8469566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(permIS)); 8479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(section, permIS)); 8489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS)); 849b4457527SToby Isaac } else { 8509566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 851b4457527SToby Isaac } 8529566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 853b4457527SToby Isaac *topSection = section; 854b4457527SToby Isaac PetscFunctionReturn(0); 855b4457527SToby Isaac } 856b4457527SToby Isaac 857b4457527SToby Isaac /* mark boundary points and set up */ 858b4457527SToby Isaac PetscErrorCode PetscDualSpaceSectionSetUp_Internal(PetscDualSpace sp, PetscSection section) 859b4457527SToby Isaac { 860b4457527SToby Isaac DM dm; 861b4457527SToby Isaac DMLabel boundary; 862b4457527SToby Isaac PetscInt pStart, pEnd, p; 863b4457527SToby Isaac 864b4457527SToby Isaac PetscFunctionBegin; 865b4457527SToby Isaac dm = sp->dm; 8669566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF,"boundary",&boundary)); 8679566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp,&dm)); 8689566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm,1,boundary)); 8699566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm,boundary)); 8709566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 871b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 872b4457527SToby Isaac PetscInt bval; 873b4457527SToby Isaac 8749566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(boundary, p, &bval)); 875b4457527SToby Isaac if (bval == 1) { 876b4457527SToby Isaac PetscInt dof; 877b4457527SToby Isaac 8789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 8799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetConstraintDof(section, p, dof)); 880b4457527SToby Isaac } 881b4457527SToby Isaac } 8829566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&boundary)); 8839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 884b4457527SToby Isaac PetscFunctionReturn(0); 885b4457527SToby Isaac } 886b4457527SToby Isaac 887a4ce7ad1SMatthew G. Knepley /*@ 888b4457527SToby Isaac PetscDualSpaceGetSection - Create a PetscSection over the reference cell with the layout from this space 889a4ce7ad1SMatthew G. Knepley 890a4ce7ad1SMatthew G. Knepley Collective on sp 891a4ce7ad1SMatthew G. Knepley 892a4ce7ad1SMatthew G. Knepley Input Parameters: 893f0fc11ceSJed Brown . sp - The PetscDualSpace 894a4ce7ad1SMatthew G. Knepley 895a4ce7ad1SMatthew G. Knepley Output Parameter: 896a4ce7ad1SMatthew G. Knepley . section - The section 897a4ce7ad1SMatthew G. Knepley 898a4ce7ad1SMatthew G. Knepley Level: advanced 899a4ce7ad1SMatthew G. Knepley 900db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `DMPLEX` 901a4ce7ad1SMatthew G. Knepley @*/ 902b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetSection(PetscDualSpace sp, PetscSection *section) 90320cf1dd8SToby Isaac { 904b4457527SToby Isaac PetscInt pStart, pEnd, p; 905b4457527SToby Isaac 906b4457527SToby Isaac PetscFunctionBegin; 90778f1d139SRomain Beucher if (!sp->dm) { 90878f1d139SRomain Beucher *section = NULL; 90978f1d139SRomain Beucher PetscFunctionReturn(0); 91078f1d139SRomain Beucher } 911b4457527SToby Isaac if (!sp->pointSection) { 912b4457527SToby Isaac /* mark the boundary */ 9139566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionCreate_Internal(sp, &(sp->pointSection))); 9149566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(sp->dm,&pStart,&pEnd)); 915b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 916b4457527SToby Isaac PetscDualSpace psp; 917b4457527SToby Isaac 9189566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, p, &psp)); 919b4457527SToby Isaac if (psp) { 920b4457527SToby Isaac PetscInt dof; 921b4457527SToby Isaac 9229566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorDimension(psp, &dof)); 9239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sp->pointSection,p,dof)); 924b4457527SToby Isaac } 925b4457527SToby Isaac } 9269566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionSetUp_Internal(sp,sp->pointSection)); 927b4457527SToby Isaac } 928b4457527SToby Isaac *section = sp->pointSection; 929b4457527SToby Isaac PetscFunctionReturn(0); 930b4457527SToby Isaac } 931b4457527SToby Isaac 932b4457527SToby Isaac /* this assumes that all of the point dual spaces store their interior dofs first, which is true when the point DMs 933b4457527SToby Isaac * have one cell */ 934b4457527SToby Isaac PetscErrorCode PetscDualSpacePushForwardSubspaces_Internal(PetscDualSpace sp, PetscInt sStart, PetscInt sEnd) 935b4457527SToby Isaac { 936b4457527SToby Isaac PetscReal *sv0, *v0, *J; 937b4457527SToby Isaac PetscSection section; 938b4457527SToby Isaac PetscInt dim, s, k; 93920cf1dd8SToby Isaac DM dm; 94020cf1dd8SToby Isaac 94120cf1dd8SToby Isaac PetscFunctionBegin; 9429566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 9439566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9449566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 9459566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim, &sv0, dim*dim, &J)); 9469566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFormDegree(sp, &k)); 947b4457527SToby Isaac for (s = sStart; s < sEnd; s++) { 948b4457527SToby Isaac PetscReal detJ, hdetJ; 949b4457527SToby Isaac PetscDualSpace ssp; 950b4457527SToby Isaac PetscInt dof, off, f, sdim; 951b4457527SToby Isaac PetscInt i, j; 952b4457527SToby Isaac DM sdm; 95320cf1dd8SToby Isaac 9549566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, s, &ssp)); 955b4457527SToby Isaac if (!ssp) continue; 9569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, s, &dof)); 9579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, s, &off)); 958b4457527SToby Isaac /* get the first vertex of the reference cell */ 9599566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(ssp, &sdm)); 9609566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sdm, &sdim)); 9619566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(sdm, 0, sv0, NULL, NULL, &hdetJ)); 9629566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, s, v0, J, NULL, &detJ)); 963b4457527SToby Isaac /* compactify Jacobian */ 964b4457527SToby Isaac for (i = 0; i < dim; i++) for (j = 0; j < sdim; j++) J[i* sdim + j] = J[i * dim + j]; 965b4457527SToby Isaac for (f = 0; f < dof; f++) { 966b4457527SToby Isaac PetscQuadrature fn; 96720cf1dd8SToby Isaac 9689566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(ssp, f, &fn)); 9699566063dSJacob Faibussowitsch PetscCall(PetscQuadraturePushForward(fn, dim, sv0, v0, J, k, &(sp->functional[off+f]))); 97020cf1dd8SToby Isaac } 97120cf1dd8SToby Isaac } 9729566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, sv0, J)); 97320cf1dd8SToby Isaac PetscFunctionReturn(0); 97420cf1dd8SToby Isaac } 97520cf1dd8SToby Isaac 97620cf1dd8SToby Isaac /*@C 97720cf1dd8SToby Isaac PetscDualSpaceApply - Apply a functional from the dual space basis to an input function 97820cf1dd8SToby Isaac 97920cf1dd8SToby Isaac Input Parameters: 98020cf1dd8SToby Isaac + sp - The PetscDualSpace object 98120cf1dd8SToby Isaac . f - The basis functional index 98220cf1dd8SToby Isaac . time - The time 98320cf1dd8SToby 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) 98420cf1dd8SToby Isaac . numComp - The number of components for the function 98520cf1dd8SToby Isaac . func - The input function 98620cf1dd8SToby Isaac - ctx - A context for the function 98720cf1dd8SToby Isaac 98820cf1dd8SToby Isaac Output Parameter: 98920cf1dd8SToby Isaac . value - numComp output values 99020cf1dd8SToby Isaac 99120cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 99220cf1dd8SToby Isaac 99320cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 99420cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 99520cf1dd8SToby Isaac 996a4ce7ad1SMatthew G. Knepley Level: beginner 99720cf1dd8SToby Isaac 998db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 99920cf1dd8SToby Isaac @*/ 100020cf1dd8SToby Isaac 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) 100120cf1dd8SToby Isaac { 100220cf1dd8SToby Isaac PetscFunctionBegin; 100320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 100420cf1dd8SToby Isaac PetscValidPointer(cgeom, 4); 1005dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 1006*dbbe0bcdSBarry Smith PetscUseTypeMethod(sp,apply , f, time, cgeom, numComp, func, ctx, value); 100720cf1dd8SToby Isaac PetscFunctionReturn(0); 100820cf1dd8SToby Isaac } 100920cf1dd8SToby Isaac 101020cf1dd8SToby Isaac /*@C 1011b4457527SToby Isaac PetscDualSpaceApplyAll - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetAllData() 101220cf1dd8SToby Isaac 101320cf1dd8SToby Isaac Input Parameters: 101420cf1dd8SToby Isaac + sp - The PetscDualSpace object 1015b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetAllData() 101620cf1dd8SToby Isaac 101720cf1dd8SToby Isaac Output Parameter: 101820cf1dd8SToby Isaac . spValue - The values of all dual space functionals 101920cf1dd8SToby Isaac 1020a4ce7ad1SMatthew G. Knepley Level: beginner 102120cf1dd8SToby Isaac 1022db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 102320cf1dd8SToby Isaac @*/ 102420cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceApplyAll(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 102520cf1dd8SToby Isaac { 102620cf1dd8SToby Isaac PetscFunctionBegin; 102720cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1028*dbbe0bcdSBarry Smith PetscUseTypeMethod(sp,applyall , pointEval, spValue); 102920cf1dd8SToby Isaac PetscFunctionReturn(0); 103020cf1dd8SToby Isaac } 103120cf1dd8SToby Isaac 103220cf1dd8SToby Isaac /*@C 1033b4457527SToby Isaac PetscDualSpaceApplyInterior - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetInteriorData() 1034b4457527SToby Isaac 1035b4457527SToby Isaac Input Parameters: 1036b4457527SToby Isaac + sp - The PetscDualSpace object 1037b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetInteriorData() 1038b4457527SToby Isaac 1039b4457527SToby Isaac Output Parameter: 1040b4457527SToby Isaac . spValue - The values of interior dual space functionals 1041b4457527SToby Isaac 1042b4457527SToby Isaac Level: beginner 1043b4457527SToby Isaac 1044db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1045b4457527SToby Isaac @*/ 1046b4457527SToby Isaac PetscErrorCode PetscDualSpaceApplyInterior(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1047b4457527SToby Isaac { 1048b4457527SToby Isaac PetscFunctionBegin; 1049b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1050*dbbe0bcdSBarry Smith PetscUseTypeMethod(sp,applyint , pointEval, spValue); 1051b4457527SToby Isaac PetscFunctionReturn(0); 1052b4457527SToby Isaac } 1053b4457527SToby Isaac 1054b4457527SToby Isaac /*@C 105520cf1dd8SToby Isaac PetscDualSpaceApplyDefault - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional. 105620cf1dd8SToby Isaac 105720cf1dd8SToby Isaac Input Parameters: 105820cf1dd8SToby Isaac + sp - The PetscDualSpace object 105920cf1dd8SToby Isaac . f - The basis functional index 106020cf1dd8SToby Isaac . time - The time 106120cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian) 106220cf1dd8SToby Isaac . Nc - The number of components for the function 106320cf1dd8SToby Isaac . func - The input function 106420cf1dd8SToby Isaac - ctx - A context for the function 106520cf1dd8SToby Isaac 106620cf1dd8SToby Isaac Output Parameter: 106720cf1dd8SToby Isaac . value - The output value 106820cf1dd8SToby Isaac 106920cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 107020cf1dd8SToby Isaac 107120cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 107220cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 107320cf1dd8SToby Isaac 107420cf1dd8SToby Isaac and the idea is to evaluate the functional as an integral 107520cf1dd8SToby Isaac 107620cf1dd8SToby Isaac $ n(f) = int dx n(x) . f(x) 107720cf1dd8SToby Isaac 107820cf1dd8SToby Isaac where both n and f have Nc components. 107920cf1dd8SToby Isaac 1080a4ce7ad1SMatthew G. Knepley Level: beginner 108120cf1dd8SToby Isaac 1082db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 108320cf1dd8SToby Isaac @*/ 108420cf1dd8SToby Isaac 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) 108520cf1dd8SToby Isaac { 108620cf1dd8SToby Isaac DM dm; 108720cf1dd8SToby Isaac PetscQuadrature n; 108820cf1dd8SToby Isaac const PetscReal *points, *weights; 108920cf1dd8SToby Isaac PetscReal x[3]; 109020cf1dd8SToby Isaac PetscScalar *val; 109120cf1dd8SToby Isaac PetscInt dim, dE, qNc, c, Nq, q; 109220cf1dd8SToby Isaac PetscBool isAffine; 109320cf1dd8SToby Isaac 109420cf1dd8SToby Isaac PetscFunctionBegin; 109520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1096dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 10979566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 10989566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 10999566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, &dim, &qNc, &Nq, &points, &weights)); 110063a3b9bcSJacob 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); 110163a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc,PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 11029566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 110320cf1dd8SToby Isaac *value = 0.0; 110420cf1dd8SToby Isaac isAffine = cgeom->isAffine; 110520cf1dd8SToby Isaac dE = cgeom->dimEmbed; 110620cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 110720cf1dd8SToby Isaac if (isAffine) { 110820cf1dd8SToby Isaac CoordinatesRefToReal(dE, cgeom->dim, cgeom->xi, cgeom->v, cgeom->J, &points[q*dim], x); 11099566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, x, Nc, val, ctx)); 111020cf1dd8SToby Isaac } else { 11119566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, &cgeom->v[dE*q], Nc, val, ctx)); 111220cf1dd8SToby Isaac } 111320cf1dd8SToby Isaac for (c = 0; c < Nc; ++c) { 111420cf1dd8SToby Isaac *value += val[c]*weights[q*Nc+c]; 111520cf1dd8SToby Isaac } 111620cf1dd8SToby Isaac } 11179566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 111820cf1dd8SToby Isaac PetscFunctionReturn(0); 111920cf1dd8SToby Isaac } 112020cf1dd8SToby Isaac 112120cf1dd8SToby Isaac /*@C 1122b4457527SToby Isaac PetscDualSpaceApplyAllDefault - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetAllData() 112320cf1dd8SToby Isaac 112420cf1dd8SToby Isaac Input Parameters: 112520cf1dd8SToby Isaac + sp - The PetscDualSpace object 1126b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetAllData() 112720cf1dd8SToby Isaac 112820cf1dd8SToby Isaac Output Parameter: 112920cf1dd8SToby Isaac . spValue - The values of all dual space functionals 113020cf1dd8SToby Isaac 1131a4ce7ad1SMatthew G. Knepley Level: beginner 113220cf1dd8SToby Isaac 1133db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 113420cf1dd8SToby Isaac @*/ 113520cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceApplyAllDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 113620cf1dd8SToby Isaac { 1137b4457527SToby Isaac Vec pointValues, dofValues; 1138b4457527SToby Isaac Mat allMat; 113920cf1dd8SToby Isaac 114020cf1dd8SToby Isaac PetscFunctionBegin; 114120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 114220cf1dd8SToby Isaac PetscValidScalarPointer(pointEval, 2); 1143064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11449566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetAllData(sp, NULL, &allMat)); 1145b4457527SToby Isaac if (!(sp->allNodeValues)) { 11469566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(allMat, &(sp->allNodeValues), NULL)); 114720cf1dd8SToby Isaac } 1148b4457527SToby Isaac pointValues = sp->allNodeValues; 1149b4457527SToby Isaac if (!(sp->allDofValues)) { 11509566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(allMat, NULL, &(sp->allDofValues))); 115120cf1dd8SToby Isaac } 1152b4457527SToby Isaac dofValues = sp->allDofValues; 11539566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11549566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11559566063dSJacob Faibussowitsch PetscCall(MatMult(allMat, pointValues, dofValues)); 11569566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11579566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 1158b4457527SToby Isaac PetscFunctionReturn(0); 115920cf1dd8SToby Isaac } 1160b4457527SToby Isaac 1161b4457527SToby Isaac /*@C 1162b4457527SToby Isaac PetscDualSpaceApplyInteriorDefault - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetInteriorData() 1163b4457527SToby Isaac 1164b4457527SToby Isaac Input Parameters: 1165b4457527SToby Isaac + sp - The PetscDualSpace object 1166b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetInteriorData() 1167b4457527SToby Isaac 1168b4457527SToby Isaac Output Parameter: 1169b4457527SToby Isaac . spValue - The values of interior dual space functionals 1170b4457527SToby Isaac 1171b4457527SToby Isaac Level: beginner 1172b4457527SToby Isaac 1173db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1174b4457527SToby Isaac @*/ 1175b4457527SToby Isaac PetscErrorCode PetscDualSpaceApplyInteriorDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1176b4457527SToby Isaac { 1177b4457527SToby Isaac Vec pointValues, dofValues; 1178b4457527SToby Isaac Mat intMat; 1179b4457527SToby Isaac 1180b4457527SToby Isaac PetscFunctionBegin; 1181b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1182b4457527SToby Isaac PetscValidScalarPointer(pointEval, 2); 1183064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11849566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(sp, NULL, &intMat)); 1185b4457527SToby Isaac if (!(sp->intNodeValues)) { 11869566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(intMat, &(sp->intNodeValues), NULL)); 1187b4457527SToby Isaac } 1188b4457527SToby Isaac pointValues = sp->intNodeValues; 1189b4457527SToby Isaac if (!(sp->intDofValues)) { 11909566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(intMat, NULL, &(sp->intDofValues))); 1191b4457527SToby Isaac } 1192b4457527SToby Isaac dofValues = sp->intDofValues; 11939566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11949566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11959566063dSJacob Faibussowitsch PetscCall(MatMult(intMat, pointValues, dofValues)); 11969566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11979566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 119820cf1dd8SToby Isaac PetscFunctionReturn(0); 119920cf1dd8SToby Isaac } 120020cf1dd8SToby Isaac 1201a4ce7ad1SMatthew G. Knepley /*@ 1202b4457527SToby Isaac PetscDualSpaceGetAllData - Get all quadrature nodes from this space, and the matrix that sends quadrature node values to degree-of-freedom values 1203a4ce7ad1SMatthew G. Knepley 1204a4ce7ad1SMatthew G. Knepley Input Parameter: 1205a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1206a4ce7ad1SMatthew G. Knepley 1207d8d19677SJose E. Roman Output Parameters: 1208b4457527SToby Isaac + allNodes - A PetscQuadrature object containing all evaluation nodes 1209b4457527SToby Isaac - allMat - A Mat for the node-to-dof transformation 1210a4ce7ad1SMatthew G. Knepley 1211a4ce7ad1SMatthew G. Knepley Level: advanced 1212a4ce7ad1SMatthew G. Knepley 1213db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1214a4ce7ad1SMatthew G. Knepley @*/ 1215b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetAllData(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 121620cf1dd8SToby Isaac { 121720cf1dd8SToby Isaac PetscFunctionBegin; 121820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1219b4457527SToby Isaac if (allNodes) PetscValidPointer(allNodes,2); 1220b4457527SToby Isaac if (allMat) PetscValidPointer(allMat,3); 1221b4457527SToby Isaac if ((!sp->allNodes || !sp->allMat) && sp->ops->createalldata) { 1222b4457527SToby Isaac PetscQuadrature qpoints; 1223b4457527SToby Isaac Mat amat; 1224b4457527SToby Isaac 1225*dbbe0bcdSBarry Smith PetscUseTypeMethod(sp,createalldata ,&qpoints,&amat); 12269566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->allNodes))); 12279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->allMat))); 1228b4457527SToby Isaac sp->allNodes = qpoints; 1229b4457527SToby Isaac sp->allMat = amat; 123020cf1dd8SToby Isaac } 1231b4457527SToby Isaac if (allNodes) *allNodes = sp->allNodes; 1232b4457527SToby Isaac if (allMat) *allMat = sp->allMat; 123320cf1dd8SToby Isaac PetscFunctionReturn(0); 123420cf1dd8SToby Isaac } 123520cf1dd8SToby Isaac 1236a4ce7ad1SMatthew G. Knepley /*@ 1237b4457527SToby Isaac PetscDualSpaceCreateAllDataDefault - Create all evaluation nodes and the node-to-dof matrix by examining functionals 1238a4ce7ad1SMatthew G. Knepley 1239a4ce7ad1SMatthew G. Knepley Input Parameter: 1240a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1241a4ce7ad1SMatthew G. Knepley 1242d8d19677SJose E. Roman Output Parameters: 1243b4457527SToby Isaac + allNodes - A PetscQuadrature object containing all evaluation nodes 1244b4457527SToby Isaac - allMat - A Mat for the node-to-dof transformation 1245a4ce7ad1SMatthew G. Knepley 1246a4ce7ad1SMatthew G. Knepley Level: advanced 1247a4ce7ad1SMatthew G. Knepley 1248db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1249a4ce7ad1SMatthew G. Knepley @*/ 1250b4457527SToby Isaac PetscErrorCode PetscDualSpaceCreateAllDataDefault(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 125120cf1dd8SToby Isaac { 125220cf1dd8SToby Isaac PetscInt spdim; 125320cf1dd8SToby Isaac PetscInt numPoints, offset; 125420cf1dd8SToby Isaac PetscReal *points; 125520cf1dd8SToby Isaac PetscInt f, dim; 1256b4457527SToby Isaac PetscInt Nc, nrows, ncols; 1257b4457527SToby Isaac PetscInt maxNumPoints; 125820cf1dd8SToby Isaac PetscQuadrature q; 1259b4457527SToby Isaac Mat A; 126020cf1dd8SToby Isaac 126120cf1dd8SToby Isaac PetscFunctionBegin; 12629566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 12639566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp,&spdim)); 126420cf1dd8SToby Isaac if (!spdim) { 12659566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF,allNodes)); 12669566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes,0,0,0,NULL,NULL)); 126720cf1dd8SToby Isaac } 1268b4457527SToby Isaac nrows = spdim; 12699566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp,0,&q)); 12709566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q,&dim,NULL,&numPoints,NULL,NULL)); 1271b4457527SToby Isaac maxNumPoints = numPoints; 127220cf1dd8SToby Isaac for (f = 1; f < spdim; f++) { 127320cf1dd8SToby Isaac PetscInt Np; 127420cf1dd8SToby Isaac 12759566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp,f,&q)); 12769566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q,NULL,NULL,&Np,NULL,NULL)); 127720cf1dd8SToby Isaac numPoints += Np; 1278b4457527SToby Isaac maxNumPoints = PetscMax(maxNumPoints,Np); 127920cf1dd8SToby Isaac } 1280b4457527SToby Isaac ncols = numPoints * Nc; 12819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim*numPoints,&points)); 12829566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, nrows, ncols, maxNumPoints * Nc, NULL, &A)); 128320cf1dd8SToby Isaac for (f = 0, offset = 0; f < spdim; f++) { 1284b4457527SToby Isaac const PetscReal *p, *w; 128520cf1dd8SToby Isaac PetscInt Np, i; 1286b4457527SToby Isaac PetscInt fnc; 128720cf1dd8SToby Isaac 12889566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp,f,&q)); 12899566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q,NULL,&fnc,&Np,&p,&w)); 129008401ef6SPierre Jolivet PetscCheck(fnc == Nc,PETSC_COMM_SELF, PETSC_ERR_PLIB, "functional component mismatch"); 1291b4457527SToby Isaac for (i = 0; i < Np * dim; i++) { 1292b4457527SToby Isaac points[offset* dim + i] = p[i]; 1293b4457527SToby Isaac } 1294b4457527SToby Isaac for (i = 0; i < Np * Nc; i++) { 12959566063dSJacob Faibussowitsch PetscCall(MatSetValue(A, f, offset * Nc, w[i], INSERT_VALUES)); 1296b4457527SToby Isaac } 1297b4457527SToby Isaac offset += Np; 1298b4457527SToby Isaac } 12999566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 13009566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 13019566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF,allNodes)); 13029566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes,dim,0,numPoints,points,NULL)); 1303b4457527SToby Isaac *allMat = A; 1304b4457527SToby Isaac PetscFunctionReturn(0); 1305b4457527SToby Isaac } 1306b4457527SToby Isaac 1307b4457527SToby Isaac /*@ 1308b4457527SToby Isaac PetscDualSpaceGetInteriorData - Get all quadrature points necessary to compute the interior degrees of freedom from 1309b4457527SToby Isaac this space, as well as the matrix that computes the degrees of freedom from the quadrature values. Degrees of 1310b4457527SToby Isaac freedom are interior degrees of freedom if they belong (by PetscDualSpaceGetSection()) to interior points in the 1311b4457527SToby Isaac reference DMPlex: complementary boundary degrees of freedom are marked as constrained in the section returned by 1312b4457527SToby Isaac PetscDualSpaceGetSection()). 1313b4457527SToby Isaac 1314b4457527SToby Isaac Input Parameter: 1315b4457527SToby Isaac . sp - The dualspace 1316b4457527SToby Isaac 1317d8d19677SJose E. Roman Output Parameters: 1318b4457527SToby Isaac + intNodes - A PetscQuadrature object containing all evaluation points needed to evaluate interior degrees of freedom 1319b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1320b4457527SToby Isaac the size of the constrained layout (PetscSectionGetConstrainStorageSize()) of the dual space section, 1321b4457527SToby Isaac npoints is the number of points in intNodes and nc is PetscDualSpaceGetNumComponents(). 1322b4457527SToby Isaac 1323b4457527SToby Isaac Level: advanced 1324b4457527SToby Isaac 1325db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceGetNumComponents()`, `PetscQuadratureGetData()` 1326b4457527SToby Isaac @*/ 1327b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetInteriorData(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1328b4457527SToby Isaac { 1329b4457527SToby Isaac PetscFunctionBegin; 1330b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1331b4457527SToby Isaac if (intNodes) PetscValidPointer(intNodes,2); 1332b4457527SToby Isaac if (intMat) PetscValidPointer(intMat,3); 1333b4457527SToby Isaac if ((!sp->intNodes || !sp->intMat) && sp->ops->createintdata) { 1334b4457527SToby Isaac PetscQuadrature qpoints; 1335b4457527SToby Isaac Mat imat; 1336b4457527SToby Isaac 1337*dbbe0bcdSBarry Smith PetscUseTypeMethod(sp,createintdata ,&qpoints,&imat); 13389566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->intNodes))); 13399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->intMat))); 1340b4457527SToby Isaac sp->intNodes = qpoints; 1341b4457527SToby Isaac sp->intMat = imat; 1342b4457527SToby Isaac } 1343b4457527SToby Isaac if (intNodes) *intNodes = sp->intNodes; 1344b4457527SToby Isaac if (intMat) *intMat = sp->intMat; 1345b4457527SToby Isaac PetscFunctionReturn(0); 1346b4457527SToby Isaac } 1347b4457527SToby Isaac 1348b4457527SToby Isaac /*@ 1349b4457527SToby Isaac PetscDualSpaceCreateInteriorDataDefault - Create quadrature points by examining interior functionals and create the matrix mapping quadrature point values to interior dual space values 1350b4457527SToby Isaac 1351b4457527SToby Isaac Input Parameter: 1352b4457527SToby Isaac . sp - The dualspace 1353b4457527SToby Isaac 1354d8d19677SJose E. Roman Output Parameters: 1355b4457527SToby Isaac + intNodes - A PetscQuadrature object containing all evaluation points needed to evaluate interior degrees of freedom 1356b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1357b4457527SToby Isaac the size of the constrained layout (PetscSectionGetConstrainStorageSize()) of the dual space section, 1358b4457527SToby Isaac npoints is the number of points in allNodes and nc is PetscDualSpaceGetNumComponents(). 1359b4457527SToby Isaac 1360b4457527SToby Isaac Level: advanced 1361b4457527SToby Isaac 1362db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `PetscDualSpaceGetInteriorData()` 1363b4457527SToby Isaac @*/ 1364b4457527SToby Isaac PetscErrorCode PetscDualSpaceCreateInteriorDataDefault(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1365b4457527SToby Isaac { 1366b4457527SToby Isaac DM dm; 1367b4457527SToby Isaac PetscInt spdim0; 1368b4457527SToby Isaac PetscInt Nc; 1369b4457527SToby Isaac PetscInt pStart, pEnd, p, f; 1370b4457527SToby Isaac PetscSection section; 1371b4457527SToby Isaac PetscInt numPoints, offset, matoffset; 1372b4457527SToby Isaac PetscReal *points; 1373b4457527SToby Isaac PetscInt dim; 1374b4457527SToby Isaac PetscInt *nnz; 1375b4457527SToby Isaac PetscQuadrature q; 1376b4457527SToby Isaac Mat imat; 1377b4457527SToby Isaac 1378b4457527SToby Isaac PetscFunctionBegin; 1379b4457527SToby Isaac PetscValidHeaderSpecific(sp,PETSCDUALSPACE_CLASSID,1); 13809566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 13819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &spdim0)); 1382b4457527SToby Isaac if (!spdim0) { 1383b4457527SToby Isaac *intNodes = NULL; 1384b4457527SToby Isaac *intMat = NULL; 1385b4457527SToby Isaac PetscFunctionReturn(0); 1386b4457527SToby Isaac } 13879566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 13889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 13899566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 13909566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 13919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(spdim0, &nnz)); 1392b4457527SToby Isaac for (p = pStart, f = 0, numPoints = 0; p < pEnd; p++) { 1393b4457527SToby Isaac PetscInt dof, cdof, off, d; 1394b4457527SToby Isaac 13959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 13969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1397b4457527SToby Isaac if (!(dof - cdof)) continue; 13989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1399b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1400b4457527SToby Isaac PetscInt Np; 1401b4457527SToby Isaac 14029566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp,off,&q)); 14039566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q,NULL,NULL,&Np,NULL,NULL)); 1404b4457527SToby Isaac nnz[f] = Np * Nc; 1405b4457527SToby Isaac numPoints += Np; 1406b4457527SToby Isaac } 1407b4457527SToby Isaac } 14089566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, spdim0, numPoints * Nc, 0, nnz, &imat)); 14099566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 14109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim*numPoints,&points)); 1411b4457527SToby Isaac for (p = pStart, f = 0, offset = 0, matoffset = 0; p < pEnd; p++) { 1412b4457527SToby Isaac PetscInt dof, cdof, off, d; 1413b4457527SToby Isaac 14149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 14159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1416b4457527SToby Isaac if (!(dof - cdof)) continue; 14179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1418b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1419b4457527SToby Isaac const PetscReal *p; 1420b4457527SToby Isaac const PetscReal *w; 1421b4457527SToby Isaac PetscInt Np, i; 1422b4457527SToby Isaac 14239566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp,off,&q)); 14249566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q,NULL,NULL,&Np,&p,&w)); 142520cf1dd8SToby Isaac for (i = 0; i < Np * dim; i++) { 142620cf1dd8SToby Isaac points[offset + i] = p[i]; 142720cf1dd8SToby Isaac } 1428b4457527SToby Isaac for (i = 0; i < Np * Nc; i++) { 14299566063dSJacob Faibussowitsch PetscCall(MatSetValue(imat, f, matoffset + i, w[i],INSERT_VALUES)); 143020cf1dd8SToby Isaac } 1431b4457527SToby Isaac offset += Np * dim; 1432b4457527SToby Isaac matoffset += Np * Nc; 1433b4457527SToby Isaac } 1434b4457527SToby Isaac } 14359566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF,intNodes)); 14369566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*intNodes,dim,0,numPoints,points,NULL)); 14379566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(imat, MAT_FINAL_ASSEMBLY)); 14389566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(imat, MAT_FINAL_ASSEMBLY)); 1439b4457527SToby Isaac *intMat = imat; 144020cf1dd8SToby Isaac PetscFunctionReturn(0); 144120cf1dd8SToby Isaac } 144220cf1dd8SToby Isaac 14434f9ab2b4SJed Brown /*@ 14444f9ab2b4SJed Brown PetscDualSpaceEqual - Determine if a dual space is equivalent 14454f9ab2b4SJed Brown 14464f9ab2b4SJed Brown Input Parameters: 14474f9ab2b4SJed Brown + A - A PetscDualSpace object 14484f9ab2b4SJed Brown - B - Another PetscDualSpace object 14494f9ab2b4SJed Brown 14504f9ab2b4SJed Brown Output Parameter: 14514f9ab2b4SJed Brown . equal - PETSC_TRUE if the dual spaces are equivalent 14524f9ab2b4SJed Brown 14534f9ab2b4SJed Brown Level: advanced 14544f9ab2b4SJed Brown 1455db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 14564f9ab2b4SJed Brown @*/ 14574f9ab2b4SJed Brown PetscErrorCode PetscDualSpaceEqual(PetscDualSpace A, PetscDualSpace B, PetscBool *equal) 14584f9ab2b4SJed Brown { 14594f9ab2b4SJed Brown PetscInt sizeA, sizeB, dimA, dimB; 14604f9ab2b4SJed Brown const PetscInt *dofA, *dofB; 14614f9ab2b4SJed Brown PetscQuadrature quadA, quadB; 14624f9ab2b4SJed Brown Mat matA, matB; 14634f9ab2b4SJed Brown 14644f9ab2b4SJed Brown PetscFunctionBegin; 14654f9ab2b4SJed Brown PetscValidHeaderSpecific(A,PETSCDUALSPACE_CLASSID,1); 14664f9ab2b4SJed Brown PetscValidHeaderSpecific(B,PETSCDUALSPACE_CLASSID,2); 14674f9ab2b4SJed Brown PetscValidBoolPointer(equal,3); 14684f9ab2b4SJed Brown *equal = PETSC_FALSE; 14699566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(A, &sizeA)); 14709566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(B, &sizeB)); 14714f9ab2b4SJed Brown if (sizeB != sizeA) { 14724f9ab2b4SJed Brown PetscFunctionReturn(0); 14734f9ab2b4SJed Brown } 14749566063dSJacob Faibussowitsch PetscCall(DMGetDimension(A->dm, &dimA)); 14759566063dSJacob Faibussowitsch PetscCall(DMGetDimension(B->dm, &dimB)); 14764f9ab2b4SJed Brown if (dimA != dimB) { 14774f9ab2b4SJed Brown PetscFunctionReturn(0); 14784f9ab2b4SJed Brown } 14794f9ab2b4SJed Brown 14809566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(A, &dofA)); 14819566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(B, &dofB)); 14824f9ab2b4SJed Brown for (PetscInt d=0; d<dimA; d++) { 14834f9ab2b4SJed Brown if (dofA[d] != dofB[d]) { 14844f9ab2b4SJed Brown PetscFunctionReturn(0); 14854f9ab2b4SJed Brown } 14864f9ab2b4SJed Brown } 14874f9ab2b4SJed Brown 14889566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(A, &quadA, &matA)); 14899566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(B, &quadB, &matB)); 14904f9ab2b4SJed Brown if (!quadA && !quadB) { 14914f9ab2b4SJed Brown *equal = PETSC_TRUE; 14924f9ab2b4SJed Brown } else if (quadA && quadB) { 14939566063dSJacob Faibussowitsch PetscCall(PetscQuadratureEqual(quadA, quadB, equal)); 14944f9ab2b4SJed Brown if (*equal == PETSC_FALSE) PetscFunctionReturn(0); 14954f9ab2b4SJed Brown if (!matA && !matB) PetscFunctionReturn(0); 14969566063dSJacob Faibussowitsch if (matA && matB) PetscCall(MatEqual(matA, matB, equal)); 14974f9ab2b4SJed Brown else *equal = PETSC_FALSE; 14984f9ab2b4SJed Brown } 14994f9ab2b4SJed Brown PetscFunctionReturn(0); 15004f9ab2b4SJed Brown } 15014f9ab2b4SJed Brown 150220cf1dd8SToby Isaac /*@C 150320cf1dd8SToby Isaac PetscDualSpaceApplyFVM - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional at the cell centroid. 150420cf1dd8SToby Isaac 150520cf1dd8SToby Isaac Input Parameters: 150620cf1dd8SToby Isaac + sp - The PetscDualSpace object 150720cf1dd8SToby Isaac . f - The basis functional index 150820cf1dd8SToby Isaac . time - The time 150920cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we currently just use the centroid 151020cf1dd8SToby Isaac . Nc - The number of components for the function 151120cf1dd8SToby Isaac . func - The input function 151220cf1dd8SToby Isaac - ctx - A context for the function 151320cf1dd8SToby Isaac 151420cf1dd8SToby Isaac Output Parameter: 151520cf1dd8SToby Isaac . value - The output value (scalar) 151620cf1dd8SToby Isaac 151720cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 151820cf1dd8SToby Isaac 151920cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 152020cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 152120cf1dd8SToby Isaac 152220cf1dd8SToby Isaac and the idea is to evaluate the functional as an integral 152320cf1dd8SToby Isaac 152420cf1dd8SToby Isaac $ n(f) = int dx n(x) . f(x) 152520cf1dd8SToby Isaac 152620cf1dd8SToby Isaac where both n and f have Nc components. 152720cf1dd8SToby Isaac 1528a4ce7ad1SMatthew G. Knepley Level: beginner 152920cf1dd8SToby Isaac 1530db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 153120cf1dd8SToby Isaac @*/ 153220cf1dd8SToby Isaac 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) 153320cf1dd8SToby Isaac { 153420cf1dd8SToby Isaac DM dm; 153520cf1dd8SToby Isaac PetscQuadrature n; 153620cf1dd8SToby Isaac const PetscReal *points, *weights; 153720cf1dd8SToby Isaac PetscScalar *val; 153820cf1dd8SToby Isaac PetscInt dimEmbed, qNc, c, Nq, q; 153920cf1dd8SToby Isaac 154020cf1dd8SToby Isaac PetscFunctionBegin; 154120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1542dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 15439566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 15449566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 15459566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 15469566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, NULL, &qNc, &Nq, &points, &weights)); 154763a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc,PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 15489566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 154920cf1dd8SToby Isaac *value = 0.; 155020cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 15519566063dSJacob Faibussowitsch PetscCall((*func)(dimEmbed, time, cgeom->centroid, Nc, val, ctx)); 155220cf1dd8SToby Isaac for (c = 0; c < Nc; ++c) { 155320cf1dd8SToby Isaac *value += val[c]*weights[q*Nc+c]; 155420cf1dd8SToby Isaac } 155520cf1dd8SToby Isaac } 15569566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 155720cf1dd8SToby Isaac PetscFunctionReturn(0); 155820cf1dd8SToby Isaac } 155920cf1dd8SToby Isaac 156020cf1dd8SToby Isaac /*@ 156120cf1dd8SToby Isaac PetscDualSpaceGetHeightSubspace - Get the subset of the dual space basis that is supported on a mesh point of a 156220cf1dd8SToby Isaac given height. This assumes that the reference cell is symmetric over points of this height. 156320cf1dd8SToby Isaac 156420cf1dd8SToby Isaac If the dual space is not defined on mesh points of the given height (e.g. if the space is discontinuous and 156520cf1dd8SToby Isaac pointwise values are not defined on the element boundaries), or if the implementation of PetscDualSpace does not 156620cf1dd8SToby Isaac support extracting subspaces, then NULL is returned. 156720cf1dd8SToby Isaac 156820cf1dd8SToby Isaac This does not increment the reference count on the returned dual space, and the user should not destroy it. 156920cf1dd8SToby Isaac 157020cf1dd8SToby Isaac Not collective 157120cf1dd8SToby Isaac 157220cf1dd8SToby Isaac Input Parameters: 157320cf1dd8SToby Isaac + sp - the PetscDualSpace object 157420cf1dd8SToby Isaac - height - the height of the mesh point for which the subspace is desired 157520cf1dd8SToby Isaac 157620cf1dd8SToby Isaac Output Parameter: 157720cf1dd8SToby Isaac . subsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 157820cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 157920cf1dd8SToby Isaac 158020cf1dd8SToby Isaac Level: advanced 158120cf1dd8SToby Isaac 1582db781477SPatrick Sanan .seealso: `PetscSpaceGetHeightSubspace()`, `PetscDualSpace` 158320cf1dd8SToby Isaac @*/ 158420cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetHeightSubspace(PetscDualSpace sp, PetscInt height, PetscDualSpace *subsp) 158520cf1dd8SToby Isaac { 1586b4457527SToby Isaac PetscInt depth = -1, cStart, cEnd; 1587b4457527SToby Isaac DM dm; 158820cf1dd8SToby Isaac 158920cf1dd8SToby Isaac PetscFunctionBegin; 159020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1591064a246eSJacob Faibussowitsch PetscValidPointer(subsp,3); 159208401ef6SPierre 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"); 159320cf1dd8SToby Isaac *subsp = NULL; 1594b4457527SToby Isaac dm = sp->dm; 15959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 15961dca8a05SBarry Smith PetscCheck(height >= 0 && height <= depth,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid height"); 15979566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm,0,&cStart,&cEnd)); 1598b4457527SToby Isaac if (height == 0 && cEnd == cStart + 1) { 1599b4457527SToby Isaac *subsp = sp; 1600b4457527SToby Isaac PetscFunctionReturn(0); 1601b4457527SToby Isaac } 1602b4457527SToby Isaac if (!sp->heightSpaces) { 1603b4457527SToby Isaac PetscInt h; 16049566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth+1, &(sp->heightSpaces))); 1605b4457527SToby Isaac 1606b4457527SToby Isaac for (h = 0; h <= depth; h++) { 1607b4457527SToby Isaac if (h == 0 && cEnd == cStart + 1) continue; 16089566063dSJacob Faibussowitsch if (sp->ops->createheightsubspace) PetscCall((*sp->ops->createheightsubspace)(sp,height,&(sp->heightSpaces[h]))); 1609b4457527SToby Isaac else if (sp->pointSpaces) { 1610b4457527SToby Isaac PetscInt hStart, hEnd; 1611b4457527SToby Isaac 16129566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm,h,&hStart,&hEnd)); 1613b4457527SToby Isaac if (hEnd > hStart) { 1614665f567fSMatthew G. Knepley const char *name; 1615665f567fSMatthew G. Knepley 16169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(sp->pointSpaces[hStart]))); 1617665f567fSMatthew G. Knepley if (sp->pointSpaces[hStart]) { 16189566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) sp, &name)); 16199566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) sp->pointSpaces[hStart], name)); 1620665f567fSMatthew G. Knepley } 1621b4457527SToby Isaac sp->heightSpaces[h] = sp->pointSpaces[hStart]; 1622b4457527SToby Isaac } 1623b4457527SToby Isaac } 1624b4457527SToby Isaac } 1625b4457527SToby Isaac } 1626b4457527SToby Isaac *subsp = sp->heightSpaces[height]; 162720cf1dd8SToby Isaac PetscFunctionReturn(0); 162820cf1dd8SToby Isaac } 162920cf1dd8SToby Isaac 163020cf1dd8SToby Isaac /*@ 163120cf1dd8SToby Isaac PetscDualSpaceGetPointSubspace - Get the subset of the dual space basis that is supported on a particular mesh point. 163220cf1dd8SToby Isaac 163320cf1dd8SToby Isaac If the dual space is not defined on the mesh point (e.g. if the space is discontinuous and pointwise values are not 163420cf1dd8SToby Isaac defined on the element boundaries), or if the implementation of PetscDualSpace does not support extracting 163520cf1dd8SToby Isaac subspaces, then NULL is returned. 163620cf1dd8SToby Isaac 163720cf1dd8SToby Isaac This does not increment the reference count on the returned dual space, and the user should not destroy it. 163820cf1dd8SToby Isaac 163920cf1dd8SToby Isaac Not collective 164020cf1dd8SToby Isaac 164120cf1dd8SToby Isaac Input Parameters: 164220cf1dd8SToby Isaac + sp - the PetscDualSpace object 164320cf1dd8SToby Isaac - point - the point (in the dual space's DM) for which the subspace is desired 164420cf1dd8SToby Isaac 164520cf1dd8SToby Isaac Output Parameters: 164620cf1dd8SToby Isaac bdsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 164720cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 164820cf1dd8SToby Isaac 164920cf1dd8SToby Isaac Level: advanced 165020cf1dd8SToby Isaac 1651db781477SPatrick Sanan .seealso: `PetscDualSpace` 165220cf1dd8SToby Isaac @*/ 165320cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetPointSubspace(PetscDualSpace sp, PetscInt point, PetscDualSpace *bdsp) 165420cf1dd8SToby Isaac { 1655b4457527SToby Isaac PetscInt pStart = 0, pEnd = 0, cStart, cEnd; 1656b4457527SToby Isaac DM dm; 165720cf1dd8SToby Isaac 165820cf1dd8SToby Isaac PetscFunctionBegin; 165920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1660064a246eSJacob Faibussowitsch PetscValidPointer(bdsp,3); 166120cf1dd8SToby Isaac *bdsp = NULL; 1662b4457527SToby Isaac dm = sp->dm; 16639566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 16641dca8a05SBarry Smith PetscCheck(point >= pStart && point <= pEnd,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid point"); 16659566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm,0,&cStart,&cEnd)); 1666b4457527SToby 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 */ 1667b4457527SToby Isaac *bdsp = sp; 1668b4457527SToby Isaac PetscFunctionReturn(0); 1669b4457527SToby Isaac } 1670b4457527SToby Isaac if (!sp->pointSpaces) { 1671b4457527SToby Isaac PetscInt p; 16729566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &(sp->pointSpaces))); 167320cf1dd8SToby Isaac 1674b4457527SToby Isaac for (p = 0; p < pEnd - pStart; p++) { 1675b4457527SToby Isaac if (p + pStart == cStart && cEnd == cStart + 1) continue; 16769566063dSJacob Faibussowitsch if (sp->ops->createpointsubspace) PetscCall((*sp->ops->createpointsubspace)(sp,p+pStart,&(sp->pointSpaces[p]))); 1677b4457527SToby Isaac else if (sp->heightSpaces || sp->ops->createheightsubspace) { 1678b4457527SToby Isaac PetscInt dim, depth, height; 1679b4457527SToby Isaac DMLabel label; 1680b4457527SToby Isaac 16819566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm,&dim)); 16829566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm,&label)); 16839566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label,p+pStart,&depth)); 168420cf1dd8SToby Isaac height = dim - depth; 16859566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(sp, height, &(sp->pointSpaces[p]))); 16869566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sp->pointSpaces[p])); 168720cf1dd8SToby Isaac } 1688b4457527SToby Isaac } 1689b4457527SToby Isaac } 1690b4457527SToby Isaac *bdsp = sp->pointSpaces[point - pStart]; 169120cf1dd8SToby Isaac PetscFunctionReturn(0); 169220cf1dd8SToby Isaac } 169320cf1dd8SToby Isaac 16946f905325SMatthew G. Knepley /*@C 16956f905325SMatthew G. Knepley PetscDualSpaceGetSymmetries - Returns a description of the symmetries of this basis 16966f905325SMatthew G. Knepley 16976f905325SMatthew G. Knepley Not collective 16986f905325SMatthew G. Knepley 16996f905325SMatthew G. Knepley Input Parameter: 17006f905325SMatthew G. Knepley . sp - the PetscDualSpace object 17016f905325SMatthew G. Knepley 17026f905325SMatthew G. Knepley Output Parameters: 1703b4457527SToby Isaac + perms - Permutations of the interior degrees of freedom, parameterized by the point orientation 1704b4457527SToby Isaac - flips - Sign reversal of the interior degrees of freedom, parameterized by the point orientation 17056f905325SMatthew G. Knepley 17066f905325SMatthew G. Knepley Note: The permutation and flip arrays are organized in the following way 17076f905325SMatthew G. Knepley $ perms[p][ornt][dof # on point] = new local dof # 17086f905325SMatthew G. Knepley $ flips[p][ornt][dof # on point] = reversal or not 17096f905325SMatthew G. Knepley 17106f905325SMatthew G. Knepley Level: developer 17116f905325SMatthew G. Knepley 17126f905325SMatthew G. Knepley @*/ 17136f905325SMatthew G. Knepley PetscErrorCode PetscDualSpaceGetSymmetries(PetscDualSpace sp, const PetscInt ****perms, const PetscScalar ****flips) 17146f905325SMatthew G. Knepley { 17156f905325SMatthew G. Knepley PetscFunctionBegin; 17166f905325SMatthew G. Knepley PetscValidHeaderSpecific(sp,PETSCDUALSPACE_CLASSID,1); 17176f905325SMatthew G. Knepley if (perms) {PetscValidPointer(perms,2); *perms = NULL;} 17186f905325SMatthew G. Knepley if (flips) {PetscValidPointer(flips,3); *flips = NULL;} 17199566063dSJacob Faibussowitsch if (sp->ops->getsymmetries) PetscCall((sp->ops->getsymmetries)(sp,perms,flips)); 17206f905325SMatthew G. Knepley PetscFunctionReturn(0); 17216f905325SMatthew G. Knepley } 17224bee2e38SMatthew G. Knepley 17234bee2e38SMatthew G. Knepley /*@ 1724b4457527SToby Isaac PetscDualSpaceGetFormDegree - Get the form degree k for the k-form the describes the pushforwards/pullbacks of this 1725b4457527SToby Isaac dual space's functionals. 1726b4457527SToby Isaac 1727b4457527SToby Isaac Input Parameter: 1728b4457527SToby Isaac . dsp - The PetscDualSpace 1729b4457527SToby Isaac 1730b4457527SToby Isaac Output Parameter: 1731b4457527SToby 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 1732b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1733b4457527SToby 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). 1734b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1735b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1736b4457527SToby Isaac but are stored as 1-forms. 1737b4457527SToby Isaac 1738b4457527SToby Isaac Level: developer 1739b4457527SToby Isaac 1740db781477SPatrick Sanan .seealso: `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 1741b4457527SToby Isaac @*/ 1742b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetFormDegree(PetscDualSpace dsp, PetscInt *k) 1743b4457527SToby Isaac { 1744b4457527SToby Isaac PetscFunctionBeginHot; 1745b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1746dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1747b4457527SToby Isaac *k = dsp->k; 1748b4457527SToby Isaac PetscFunctionReturn(0); 1749b4457527SToby Isaac } 1750b4457527SToby Isaac 1751b4457527SToby Isaac /*@ 1752b4457527SToby Isaac PetscDualSpaceSetFormDegree - Set the form degree k for the k-form the describes the pushforwards/pullbacks of this 1753b4457527SToby Isaac dual space's functionals. 1754b4457527SToby Isaac 1755d8d19677SJose E. Roman Input Parameters: 1756b4457527SToby Isaac + dsp - The PetscDualSpace 1757b4457527SToby 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 1758b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1759b4457527SToby 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). 1760b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1761b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1762b4457527SToby Isaac but are stored as 1-forms. 1763b4457527SToby Isaac 1764b4457527SToby Isaac Level: developer 1765b4457527SToby Isaac 1766db781477SPatrick Sanan .seealso: `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 1767b4457527SToby Isaac @*/ 1768b4457527SToby Isaac PetscErrorCode PetscDualSpaceSetFormDegree(PetscDualSpace dsp, PetscInt k) 1769b4457527SToby Isaac { 1770b4457527SToby Isaac PetscInt dim; 1771b4457527SToby Isaac 1772b4457527SToby Isaac PetscFunctionBeginHot; 1773b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 177428b400f6SJacob Faibussowitsch PetscCheck(!dsp->setupcalled,PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 1775b4457527SToby Isaac dim = dsp->dm->dim; 17761dca8a05SBarry 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); 1777b4457527SToby Isaac dsp->k = k; 1778b4457527SToby Isaac PetscFunctionReturn(0); 1779b4457527SToby Isaac } 1780b4457527SToby Isaac 1781b4457527SToby Isaac /*@ 17824bee2e38SMatthew G. Knepley PetscDualSpaceGetDeRahm - Get the k-simplex associated with the functionals in this dual space 17834bee2e38SMatthew G. Knepley 17844bee2e38SMatthew G. Knepley Input Parameter: 17854bee2e38SMatthew G. Knepley . dsp - The PetscDualSpace 17864bee2e38SMatthew G. Knepley 17874bee2e38SMatthew G. Knepley Output Parameter: 17884bee2e38SMatthew G. Knepley . k - The simplex dimension 17894bee2e38SMatthew G. Knepley 1790a4ce7ad1SMatthew G. Knepley Level: developer 17914bee2e38SMatthew G. Knepley 17924bee2e38SMatthew G. Knepley Note: Currently supported values are 17934bee2e38SMatthew G. Knepley $ 0: These are H_1 methods that only transform coordinates 17944bee2e38SMatthew G. Knepley $ 1: These are Hcurl methods that transform functions using the covariant Piola transform (COVARIANT_PIOLA_TRANSFORM) 17954bee2e38SMatthew G. Knepley $ 2: These are the same as 1 17964bee2e38SMatthew G. Knepley $ 3: These are Hdiv methods that transform functions using the contravariant Piola transform (CONTRAVARIANT_PIOLA_TRANSFORM) 17974bee2e38SMatthew G. Knepley 1798db781477SPatrick Sanan .seealso: `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 17994bee2e38SMatthew G. Knepley @*/ 18004bee2e38SMatthew G. Knepley PetscErrorCode PetscDualSpaceGetDeRahm(PetscDualSpace dsp, PetscInt *k) 18014bee2e38SMatthew G. Knepley { 1802b4457527SToby Isaac PetscInt dim; 1803b4457527SToby Isaac 18044bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18054bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1806dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1807b4457527SToby Isaac dim = dsp->dm->dim; 1808b4457527SToby Isaac if (!dsp->k) *k = IDENTITY_TRANSFORM; 1809b4457527SToby Isaac else if (dsp->k == 1) *k = COVARIANT_PIOLA_TRANSFORM; 1810b4457527SToby Isaac else if (dsp->k == -(dim - 1)) *k = CONTRAVARIANT_PIOLA_TRANSFORM; 1811b4457527SToby Isaac else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unsupported transformation"); 18124bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 18134bee2e38SMatthew G. Knepley } 18144bee2e38SMatthew G. Knepley 18154bee2e38SMatthew G. Knepley /*@C 18164bee2e38SMatthew G. Knepley PetscDualSpaceTransform - Transform the function values 18174bee2e38SMatthew G. Knepley 18184bee2e38SMatthew G. Knepley Input Parameters: 18194bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 18204bee2e38SMatthew G. Knepley . trans - The type of transform 18214bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18224bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18234bee2e38SMatthew G. Knepley . Nv - The number of function samples 18244bee2e38SMatthew G. Knepley . Nc - The number of function components 18254bee2e38SMatthew G. Knepley - vals - The function values 18264bee2e38SMatthew G. Knepley 18274bee2e38SMatthew G. Knepley Output Parameter: 18284bee2e38SMatthew G. Knepley . vals - The transformed function values 18294bee2e38SMatthew G. Knepley 1830a4ce7ad1SMatthew G. Knepley Level: intermediate 18314bee2e38SMatthew G. Knepley 1832f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18332edcad52SToby Isaac 1834db781477SPatrick Sanan .seealso: `PetscDualSpaceTransformGradient()`, `PetscDualSpaceTransformHessian()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 18354bee2e38SMatthew G. Knepley @*/ 18364bee2e38SMatthew G. Knepley PetscErrorCode PetscDualSpaceTransform(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 18374bee2e38SMatthew G. Knepley { 1838b4457527SToby Isaac PetscReal Jstar[9] = {0}; 1839b4457527SToby Isaac PetscInt dim, v, c, Nk; 18404bee2e38SMatthew G. Knepley 18414bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18424bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18434bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1844dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 1845b4457527SToby Isaac /* TODO: not handling dimEmbed != dim right now */ 18462ae266adSMatthew G. Knepley dim = dsp->dm->dim; 1847b4457527SToby Isaac /* No change needed for 0-forms */ 1848b4457527SToby Isaac if (!dsp->k) PetscFunctionReturn(0); 18499566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(dsp->k), &Nk)); 1850b4457527SToby Isaac /* TODO: use fegeom->isAffine */ 18519566063dSJacob Faibussowitsch PetscCall(PetscDTAltVPullbackMatrix(dim, dim, isInverse ? fegeom->J : fegeom->invJ, dsp->k, Jstar)); 18524bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1853b4457527SToby Isaac switch (Nk) { 1854b4457527SToby Isaac case 1: 1855b4457527SToby Isaac for (c = 0; c < Nc; c++) vals[v*Nc + c] *= Jstar[0]; 18564bee2e38SMatthew G. Knepley break; 1857b4457527SToby Isaac case 2: 1858b4457527SToby Isaac for (c = 0; c < Nc; c += 2) DMPlex_Mult2DReal_Internal(Jstar, 1, &vals[v*Nc + c], &vals[v*Nc + c]); 18594bee2e38SMatthew G. Knepley break; 1860b4457527SToby Isaac case 3: 1861b4457527SToby Isaac for (c = 0; c < Nc; c += 3) DMPlex_Mult3DReal_Internal(Jstar, 1, &vals[v*Nc + c], &vals[v*Nc + c]); 1862b4457527SToby Isaac break; 186363a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported form size %" PetscInt_FMT " for transformation", Nk); 1864b4457527SToby Isaac } 18654bee2e38SMatthew G. Knepley } 18664bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 18674bee2e38SMatthew G. Knepley } 1868b4457527SToby Isaac 18694bee2e38SMatthew G. Knepley /*@C 18704bee2e38SMatthew G. Knepley PetscDualSpaceTransformGradient - Transform the function gradient values 18714bee2e38SMatthew G. Knepley 18724bee2e38SMatthew G. Knepley Input Parameters: 18734bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 18744bee2e38SMatthew G. Knepley . trans - The type of transform 18754bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18764bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18774bee2e38SMatthew G. Knepley . Nv - The number of function gradient samples 18784bee2e38SMatthew G. Knepley . Nc - The number of function components 18794bee2e38SMatthew G. Knepley - vals - The function gradient values 18804bee2e38SMatthew G. Knepley 18814bee2e38SMatthew G. Knepley Output Parameter: 1882f9244615SMatthew G. Knepley . vals - The transformed function gradient values 18834bee2e38SMatthew G. Knepley 1884a4ce7ad1SMatthew G. Knepley Level: intermediate 18854bee2e38SMatthew G. Knepley 1886f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18872edcad52SToby Isaac 1888db781477SPatrick Sanan .seealso: `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 18894bee2e38SMatthew G. Knepley @*/ 18904bee2e38SMatthew G. Knepley PetscErrorCode PetscDualSpaceTransformGradient(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 18914bee2e38SMatthew G. Knepley { 189227f02ce8SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 189327f02ce8SMatthew G. Knepley PetscInt v, c, d; 18944bee2e38SMatthew G. Knepley 18954bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18964bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18974bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1898dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 189927f02ce8SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 190063a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 190127f02ce8SMatthew G. Knepley #endif 19024bee2e38SMatthew G. Knepley /* Transform gradient */ 190327f02ce8SMatthew G. Knepley if (dim == dE) { 19044bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19054bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 19064bee2e38SMatthew G. Knepley switch (dim) 19074bee2e38SMatthew G. Knepley { 1908100a78e1SStefano Zampini case 1: vals[(v*Nc+c)*dim] *= fegeom->invJ[0];break; 19096142fa51SMatthew G. Knepley case 2: DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, 1, &vals[(v*Nc+c)*dim], &vals[(v*Nc+c)*dim]);break; 19106142fa51SMatthew G. Knepley case 3: DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, 1, &vals[(v*Nc+c)*dim], &vals[(v*Nc+c)*dim]);break; 191163a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19124bee2e38SMatthew G. Knepley } 19134bee2e38SMatthew G. Knepley } 19144bee2e38SMatthew G. Knepley } 191527f02ce8SMatthew G. Knepley } else { 191627f02ce8SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 191727f02ce8SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 191827f02ce8SMatthew G. Knepley DMPlex_MultTransposeReal_Internal(fegeom->invJ, dim, dE, 1, &vals[(v*Nc+c)*dE], &vals[(v*Nc+c)*dE]); 191927f02ce8SMatthew G. Knepley } 192027f02ce8SMatthew G. Knepley } 192127f02ce8SMatthew G. Knepley } 19224bee2e38SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 19234bee2e38SMatthew G. Knepley if (Nc == 1 || Nc != dim) PetscFunctionReturn(0); 19244bee2e38SMatthew G. Knepley switch (trans) { 19254bee2e38SMatthew G. Knepley case IDENTITY_TRANSFORM: break; 19264bee2e38SMatthew G. Knepley case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 19274bee2e38SMatthew G. Knepley if (isInverse) { 19284bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19294bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19304bee2e38SMatthew G. Knepley switch (dim) 19314bee2e38SMatthew G. Knepley { 19326142fa51SMatthew G. Knepley case 2: DMPlex_MultTranspose2DReal_Internal(fegeom->J, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 19336142fa51SMatthew G. Knepley case 3: DMPlex_MultTranspose3DReal_Internal(fegeom->J, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 193463a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19354bee2e38SMatthew G. Knepley } 19364bee2e38SMatthew G. Knepley } 19374bee2e38SMatthew G. Knepley } 19384bee2e38SMatthew G. Knepley } else { 19394bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19404bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19414bee2e38SMatthew G. Knepley switch (dim) 19424bee2e38SMatthew G. Knepley { 19436142fa51SMatthew G. Knepley case 2: DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 19446142fa51SMatthew G. Knepley case 3: DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 194563a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19464bee2e38SMatthew G. Knepley } 19474bee2e38SMatthew G. Knepley } 19484bee2e38SMatthew G. Knepley } 19494bee2e38SMatthew G. Knepley } 19504bee2e38SMatthew G. Knepley break; 19514bee2e38SMatthew G. Knepley case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 19524bee2e38SMatthew G. Knepley if (isInverse) { 19534bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19544bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19554bee2e38SMatthew G. Knepley switch (dim) 19564bee2e38SMatthew G. Knepley { 19576142fa51SMatthew G. Knepley case 2: DMPlex_Mult2DReal_Internal(fegeom->invJ, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 19586142fa51SMatthew G. Knepley case 3: DMPlex_Mult3DReal_Internal(fegeom->invJ, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 195963a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19604bee2e38SMatthew G. Knepley } 19614bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v*Nc+c)*dim+d] *= fegeom->detJ[0]; 19624bee2e38SMatthew G. Knepley } 19634bee2e38SMatthew G. Knepley } 19644bee2e38SMatthew G. Knepley } else { 19654bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19664bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19674bee2e38SMatthew G. Knepley switch (dim) 19684bee2e38SMatthew G. Knepley { 19696142fa51SMatthew G. Knepley case 2: DMPlex_Mult2DReal_Internal(fegeom->J, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 19706142fa51SMatthew G. Knepley case 3: DMPlex_Mult3DReal_Internal(fegeom->J, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 197163a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19724bee2e38SMatthew G. Knepley } 19734bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v*Nc+c)*dim+d] /= fegeom->detJ[0]; 19744bee2e38SMatthew G. Knepley } 19754bee2e38SMatthew G. Knepley } 19764bee2e38SMatthew G. Knepley } 19774bee2e38SMatthew G. Knepley break; 19784bee2e38SMatthew G. Knepley } 19794bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 19804bee2e38SMatthew G. Knepley } 19814bee2e38SMatthew G. Knepley 19824bee2e38SMatthew G. Knepley /*@C 1983f9244615SMatthew G. Knepley PetscDualSpaceTransformHessian - Transform the function Hessian values 1984f9244615SMatthew G. Knepley 1985f9244615SMatthew G. Knepley Input Parameters: 1986f9244615SMatthew G. Knepley + dsp - The PetscDualSpace 1987f9244615SMatthew G. Knepley . trans - The type of transform 1988f9244615SMatthew G. Knepley . isInverse - Flag to invert the transform 1989f9244615SMatthew G. Knepley . fegeom - The cell geometry 1990f9244615SMatthew G. Knepley . Nv - The number of function Hessian samples 1991f9244615SMatthew G. Knepley . Nc - The number of function components 1992f9244615SMatthew G. Knepley - vals - The function gradient values 1993f9244615SMatthew G. Knepley 1994f9244615SMatthew G. Knepley Output Parameter: 1995f9244615SMatthew G. Knepley . vals - The transformed function Hessian values 1996f9244615SMatthew G. Knepley 1997f9244615SMatthew G. Knepley Level: intermediate 1998f9244615SMatthew G. Knepley 1999f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2000f9244615SMatthew G. Knepley 2001db781477SPatrick Sanan .seealso: `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 2002f9244615SMatthew G. Knepley @*/ 2003f9244615SMatthew G. Knepley PetscErrorCode PetscDualSpaceTransformHessian(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 2004f9244615SMatthew G. Knepley { 2005f9244615SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 2006f9244615SMatthew G. Knepley PetscInt v, c; 2007f9244615SMatthew G. Knepley 2008f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2009f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2010f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 4); 2011dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 2012f9244615SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 201363a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 2014f9244615SMatthew G. Knepley #endif 2015f9244615SMatthew G. Knepley /* Transform Hessian: J^{-T}_{ik} J^{-T}_{jl} H(f)_{kl} = J^{-T}_{ik} H(f)_{kl} J^{-1}_{lj} */ 2016f9244615SMatthew G. Knepley if (dim == dE) { 2017f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2018f9244615SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 2019f9244615SMatthew G. Knepley switch (dim) 2020f9244615SMatthew G. Knepley { 2021f9244615SMatthew G. Knepley case 1: vals[(v*Nc+c)*dim*dim] *= PetscSqr(fegeom->invJ[0]);break; 2022f9244615SMatthew G. Knepley case 2: DMPlex_PTAP2DReal_Internal(fegeom->invJ, &vals[(v*Nc+c)*dim*dim], &vals[(v*Nc+c)*dim*dim]);break; 2023f9244615SMatthew G. Knepley case 3: DMPlex_PTAP3DReal_Internal(fegeom->invJ, &vals[(v*Nc+c)*dim*dim], &vals[(v*Nc+c)*dim*dim]);break; 202463a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 2025f9244615SMatthew G. Knepley } 2026f9244615SMatthew G. Knepley } 2027f9244615SMatthew G. Knepley } 2028f9244615SMatthew G. Knepley } else { 2029f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2030f9244615SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 2031f9244615SMatthew G. Knepley DMPlex_PTAPReal_Internal(fegeom->invJ, dim, dE, &vals[(v*Nc+c)*dE*dE], &vals[(v*Nc+c)*dE*dE]); 2032f9244615SMatthew G. Knepley } 2033f9244615SMatthew G. Knepley } 2034f9244615SMatthew G. Knepley } 2035f9244615SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 2036f9244615SMatthew G. Knepley if (Nc == 1 || Nc != dim) PetscFunctionReturn(0); 2037f9244615SMatthew G. Knepley switch (trans) { 2038f9244615SMatthew G. Knepley case IDENTITY_TRANSFORM: break; 2039f9244615SMatthew G. Knepley case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 2040f9244615SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2041f9244615SMatthew G. Knepley case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 2042f9244615SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2043f9244615SMatthew G. Knepley } 2044f9244615SMatthew G. Knepley PetscFunctionReturn(0); 2045f9244615SMatthew G. Knepley } 2046f9244615SMatthew G. Knepley 2047f9244615SMatthew G. Knepley /*@C 20484bee2e38SMatthew 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. 20494bee2e38SMatthew G. Knepley 20504bee2e38SMatthew G. Knepley Input Parameters: 20514bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 20524bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 20534bee2e38SMatthew G. Knepley . Nq - The number of function samples 20544bee2e38SMatthew G. Knepley . Nc - The number of function components 20554bee2e38SMatthew G. Knepley - pointEval - The function values 20564bee2e38SMatthew G. Knepley 20574bee2e38SMatthew G. Knepley Output Parameter: 20584bee2e38SMatthew G. Knepley . pointEval - The transformed function values 20594bee2e38SMatthew G. Knepley 20604bee2e38SMatthew G. Knepley Level: advanced 20614bee2e38SMatthew G. Knepley 20624bee2e38SMatthew 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. 20634bee2e38SMatthew G. Knepley 20642edcad52SToby Isaac Note: This only handles tranformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 20652edcad52SToby Isaac 2066db781477SPatrick Sanan .seealso: `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 20674bee2e38SMatthew G. Knepley @*/ 20682edcad52SToby Isaac PetscErrorCode PetscDualSpacePullback(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 20694bee2e38SMatthew G. Knepley { 20704bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2071b4457527SToby Isaac PetscInt k; 20724bee2e38SMatthew G. Knepley 20734bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 20744bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 20754bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2076dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 20774bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 20784bee2e38SMatthew G. Knepley This determines their transformation properties. */ 20799566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 2080b4457527SToby Isaac switch (k) 20814bee2e38SMatthew G. Knepley { 20824bee2e38SMatthew G. Knepley case 0: /* H^1 point evaluations */ 20834bee2e38SMatthew G. Knepley trans = IDENTITY_TRANSFORM;break; 20844bee2e38SMatthew G. Knepley case 1: /* Hcurl preserves tangential edge traces */ 20854bee2e38SMatthew G. Knepley trans = COVARIANT_PIOLA_TRANSFORM;break; 2086b4457527SToby Isaac case 2: 20874bee2e38SMatthew G. Knepley case 3: /* Hdiv preserve normal traces */ 20884bee2e38SMatthew G. Knepley trans = CONTRAVARIANT_PIOLA_TRANSFORM;break; 208963a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 20904bee2e38SMatthew G. Knepley } 20919566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_TRUE, fegeom, Nq, Nc, pointEval)); 20924bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 20934bee2e38SMatthew G. Knepley } 20944bee2e38SMatthew G. Knepley 20954bee2e38SMatthew G. Knepley /*@C 20964bee2e38SMatthew 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. 20974bee2e38SMatthew G. Knepley 20984bee2e38SMatthew G. Knepley Input Parameters: 20994bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 21004bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21014bee2e38SMatthew G. Knepley . Nq - The number of function samples 21024bee2e38SMatthew G. Knepley . Nc - The number of function components 21034bee2e38SMatthew G. Knepley - pointEval - The function values 21044bee2e38SMatthew G. Knepley 21054bee2e38SMatthew G. Knepley Output Parameter: 21064bee2e38SMatthew G. Knepley . pointEval - The transformed function values 21074bee2e38SMatthew G. Knepley 21084bee2e38SMatthew G. Knepley Level: advanced 21094bee2e38SMatthew G. Knepley 21104bee2e38SMatthew 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. 21114bee2e38SMatthew G. Knepley 2112f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21132edcad52SToby Isaac 2114db781477SPatrick Sanan .seealso: `PetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 21154bee2e38SMatthew G. Knepley @*/ 21162edcad52SToby Isaac PetscErrorCode PetscDualSpacePushforward(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 21174bee2e38SMatthew G. Knepley { 21184bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2119b4457527SToby Isaac PetscInt k; 21204bee2e38SMatthew G. Knepley 21214bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21224bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 21234bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2124dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 21254bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 21264bee2e38SMatthew G. Knepley This determines their transformation properties. */ 21279566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 2128b4457527SToby Isaac switch (k) 21294bee2e38SMatthew G. Knepley { 21304bee2e38SMatthew G. Knepley case 0: /* H^1 point evaluations */ 21314bee2e38SMatthew G. Knepley trans = IDENTITY_TRANSFORM;break; 21324bee2e38SMatthew G. Knepley case 1: /* Hcurl preserves tangential edge traces */ 21334bee2e38SMatthew G. Knepley trans = COVARIANT_PIOLA_TRANSFORM;break; 2134b4457527SToby Isaac case 2: 21354bee2e38SMatthew G. Knepley case 3: /* Hdiv preserve normal traces */ 21364bee2e38SMatthew G. Knepley trans = CONTRAVARIANT_PIOLA_TRANSFORM;break; 213763a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 21384bee2e38SMatthew G. Knepley } 21399566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 21404bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 21414bee2e38SMatthew G. Knepley } 21424bee2e38SMatthew G. Knepley 21434bee2e38SMatthew G. Knepley /*@C 21444bee2e38SMatthew 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. 21454bee2e38SMatthew G. Knepley 21464bee2e38SMatthew G. Knepley Input Parameters: 21474bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 21484bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21494bee2e38SMatthew G. Knepley . Nq - The number of function gradient samples 21504bee2e38SMatthew G. Knepley . Nc - The number of function components 21514bee2e38SMatthew G. Knepley - pointEval - The function gradient values 21524bee2e38SMatthew G. Knepley 21534bee2e38SMatthew G. Knepley Output Parameter: 21544bee2e38SMatthew G. Knepley . pointEval - The transformed function gradient values 21554bee2e38SMatthew G. Knepley 21564bee2e38SMatthew G. Knepley Level: advanced 21574bee2e38SMatthew G. Knepley 21584bee2e38SMatthew 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. 21594bee2e38SMatthew G. Knepley 2160f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21612edcad52SToby Isaac 2162db781477SPatrick Sanan .seealso: `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2163dc0529c6SBarry Smith @*/ 21642edcad52SToby Isaac PetscErrorCode PetscDualSpacePushforwardGradient(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 21654bee2e38SMatthew G. Knepley { 21664bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2167b4457527SToby Isaac PetscInt k; 21684bee2e38SMatthew G. Knepley 21694bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21704bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 21714bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2172dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 21734bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 21744bee2e38SMatthew G. Knepley This determines their transformation properties. */ 21759566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 2176b4457527SToby Isaac switch (k) 21774bee2e38SMatthew G. Knepley { 21784bee2e38SMatthew G. Knepley case 0: /* H^1 point evaluations */ 21794bee2e38SMatthew G. Knepley trans = IDENTITY_TRANSFORM;break; 21804bee2e38SMatthew G. Knepley case 1: /* Hcurl preserves tangential edge traces */ 21814bee2e38SMatthew G. Knepley trans = COVARIANT_PIOLA_TRANSFORM;break; 2182b4457527SToby Isaac case 2: 21834bee2e38SMatthew G. Knepley case 3: /* Hdiv preserve normal traces */ 21844bee2e38SMatthew G. Knepley trans = CONTRAVARIANT_PIOLA_TRANSFORM;break; 218563a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 21864bee2e38SMatthew G. Knepley } 21879566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformGradient(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 21884bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 21894bee2e38SMatthew G. Knepley } 2190f9244615SMatthew G. Knepley 2191f9244615SMatthew G. Knepley /*@C 2192f9244615SMatthew 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. 2193f9244615SMatthew G. Knepley 2194f9244615SMatthew G. Knepley Input Parameters: 2195f9244615SMatthew G. Knepley + dsp - The PetscDualSpace 2196f9244615SMatthew G. Knepley . fegeom - The geometry for this cell 2197f9244615SMatthew G. Knepley . Nq - The number of function Hessian samples 2198f9244615SMatthew G. Knepley . Nc - The number of function components 2199f9244615SMatthew G. Knepley - pointEval - The function gradient values 2200f9244615SMatthew G. Knepley 2201f9244615SMatthew G. Knepley Output Parameter: 2202f9244615SMatthew G. Knepley . pointEval - The transformed function Hessian values 2203f9244615SMatthew G. Knepley 2204f9244615SMatthew G. Knepley Level: advanced 2205f9244615SMatthew G. Knepley 2206f9244615SMatthew 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. 2207f9244615SMatthew G. Knepley 2208f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2209f9244615SMatthew G. Knepley 2210db781477SPatrick Sanan .seealso: `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2211f9244615SMatthew G. Knepley @*/ 2212f9244615SMatthew G. Knepley PetscErrorCode PetscDualSpacePushforwardHessian(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2213f9244615SMatthew G. Knepley { 2214f9244615SMatthew G. Knepley PetscDualSpaceTransformType trans; 2215f9244615SMatthew G. Knepley PetscInt k; 2216f9244615SMatthew G. Knepley 2217f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2218f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2219f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2220dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 2221f9244615SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 2222f9244615SMatthew G. Knepley This determines their transformation properties. */ 22239566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 2224f9244615SMatthew G. Knepley switch (k) 2225f9244615SMatthew G. Knepley { 2226f9244615SMatthew G. Knepley case 0: /* H^1 point evaluations */ 2227f9244615SMatthew G. Knepley trans = IDENTITY_TRANSFORM;break; 2228f9244615SMatthew G. Knepley case 1: /* Hcurl preserves tangential edge traces */ 2229f9244615SMatthew G. Knepley trans = COVARIANT_PIOLA_TRANSFORM;break; 2230f9244615SMatthew G. Knepley case 2: 2231f9244615SMatthew G. Knepley case 3: /* Hdiv preserve normal traces */ 2232f9244615SMatthew G. Knepley trans = CONTRAVARIANT_PIOLA_TRANSFORM;break; 223363a3b9bcSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 2234f9244615SMatthew G. Knepley } 22359566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformHessian(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 2236f9244615SMatthew G. Knepley PetscFunctionReturn(0); 2237f9244615SMatthew G. Knepley } 2238