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 */ 28*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceLatticePointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) 29*d71ae5a4SJacob Faibussowitsch { 306f905325SMatthew G. Knepley PetscFunctionBegin; 316f905325SMatthew G. Knepley while (len--) { 326f905325SMatthew G. Knepley max -= tup[len]; 336f905325SMatthew G. Knepley if (!max) { 346f905325SMatthew G. Knepley tup[len] = 0; 356f905325SMatthew G. Knepley break; 366f905325SMatthew G. Knepley } 376f905325SMatthew G. Knepley } 386f905325SMatthew G. Knepley tup[++len]++; 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 */ 59*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTensorPointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) 60*d71ae5a4SJacob Faibussowitsch { 616f905325SMatthew G. Knepley PetscInt i; 626f905325SMatthew G. Knepley 636f905325SMatthew G. Knepley PetscFunctionBegin; 646f905325SMatthew G. Knepley for (i = 0; i < len; i++) { 656f905325SMatthew G. Knepley if (tup[i] < max) { 666f905325SMatthew G. Knepley break; 676f905325SMatthew G. Knepley } else { 686f905325SMatthew G. Knepley tup[i] = 0; 696f905325SMatthew G. Knepley } 706f905325SMatthew G. Knepley } 716f905325SMatthew G. Knepley tup[i]++; 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 @*/ 107*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceRegister(const char sname[], PetscErrorCode (*function)(PetscDualSpace)) 108*d71ae5a4SJacob Faibussowitsch { 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 @*/ 130*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetType(PetscDualSpace sp, PetscDualSpaceType name) 131*d71ae5a4SJacob Faibussowitsch { 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 144dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, destroy); 14520cf1dd8SToby Isaac sp->ops->destroy = NULL; 146dbbe0bcdSBarry 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 @*/ 167*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetType(PetscDualSpace sp, PetscDualSpaceType *name) 168*d71ae5a4SJacob Faibussowitsch { 16920cf1dd8SToby Isaac PetscFunctionBegin; 17020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 17120cf1dd8SToby Isaac PetscValidPointer(name, 2); 17248a46eb9SPierre Jolivet if (!PetscDualSpaceRegisterAllCalled) PetscCall(PetscDualSpaceRegisterAll()); 17320cf1dd8SToby Isaac *name = ((PetscObject)sp)->type_name; 17420cf1dd8SToby Isaac PetscFunctionReturn(0); 17520cf1dd8SToby Isaac } 17620cf1dd8SToby Isaac 177*d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDualSpaceView_ASCII(PetscDualSpace sp, PetscViewer v) 178*d71ae5a4SJacob Faibussowitsch { 179221d6281SMatthew G. Knepley PetscViewerFormat format; 180221d6281SMatthew G. Knepley PetscInt pdim, f; 181221d6281SMatthew G. Knepley 182221d6281SMatthew G. Knepley PetscFunctionBegin; 1839566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &pdim)); 1849566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)sp, v)); 1859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 186b4457527SToby Isaac if (sp->k) { 18763a3b9bcSJacob 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)); 188b4457527SToby Isaac } else { 18963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual space with %" PetscInt_FMT " components, size %" PetscInt_FMT "\n", sp->Nc, pdim)); 190b4457527SToby Isaac } 191dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, view, v); 1929566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(v, &format)); 193221d6281SMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 195221d6281SMatthew G. Knepley for (f = 0; f < pdim; ++f) { 19663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual basis vector %" PetscInt_FMT "\n", f)); 1979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 1989566063dSJacob Faibussowitsch PetscCall(PetscQuadratureView(sp->functional[f], v)); 1999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 200221d6281SMatthew G. Knepley } 2019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 202221d6281SMatthew G. Knepley } 2039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 204221d6281SMatthew G. Knepley PetscFunctionReturn(0); 205221d6281SMatthew G. Knepley } 206221d6281SMatthew G. Knepley 207fe2efc57SMark /*@C 208fe2efc57SMark PetscDualSpaceViewFromOptions - View from Options 209fe2efc57SMark 210fe2efc57SMark Collective on PetscDualSpace 211fe2efc57SMark 212fe2efc57SMark Input Parameters: 213fe2efc57SMark + A - the PetscDualSpace object 214736c3998SJose E. Roman . obj - Optional object, proivides prefix 215736c3998SJose E. Roman - name - command line option 216fe2efc57SMark 217fe2efc57SMark Level: intermediate 218db781477SPatrick Sanan .seealso: `PetscDualSpace`, `PetscDualSpaceView()`, `PetscObjectViewFromOptions()`, `PetscDualSpaceCreate()` 219fe2efc57SMark @*/ 220*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceViewFromOptions(PetscDualSpace A, PetscObject obj, const char name[]) 221*d71ae5a4SJacob Faibussowitsch { 222fe2efc57SMark PetscFunctionBegin; 223fe2efc57SMark PetscValidHeaderSpecific(A, PETSCDUALSPACE_CLASSID, 1); 2249566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 225fe2efc57SMark PetscFunctionReturn(0); 226fe2efc57SMark } 227fe2efc57SMark 22820cf1dd8SToby Isaac /*@ 22920cf1dd8SToby Isaac PetscDualSpaceView - Views a PetscDualSpace 23020cf1dd8SToby Isaac 231d083f849SBarry Smith Collective on sp 23220cf1dd8SToby Isaac 233d8d19677SJose E. Roman Input Parameters: 23420cf1dd8SToby Isaac + sp - the PetscDualSpace object to view 23520cf1dd8SToby Isaac - v - the viewer 23620cf1dd8SToby Isaac 237a4ce7ad1SMatthew G. Knepley Level: beginner 23820cf1dd8SToby Isaac 239db781477SPatrick Sanan .seealso `PetscDualSpaceDestroy()`, `PetscDualSpace` 24020cf1dd8SToby Isaac @*/ 241*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceView(PetscDualSpace sp, PetscViewer v) 242*d71ae5a4SJacob Faibussowitsch { 243d9bac1caSLisandro Dalcin PetscBool iascii; 24420cf1dd8SToby Isaac 24520cf1dd8SToby Isaac PetscFunctionBegin; 24620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 247d9bac1caSLisandro Dalcin if (v) PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2); 2489566063dSJacob Faibussowitsch if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sp), &v)); 2499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii)); 2509566063dSJacob Faibussowitsch if (iascii) PetscCall(PetscDualSpaceView_ASCII(sp, v)); 25120cf1dd8SToby Isaac PetscFunctionReturn(0); 25220cf1dd8SToby Isaac } 25320cf1dd8SToby Isaac 25420cf1dd8SToby Isaac /*@ 25520cf1dd8SToby Isaac PetscDualSpaceSetFromOptions - sets parameters in a PetscDualSpace from the options database 25620cf1dd8SToby Isaac 257d083f849SBarry Smith Collective on sp 25820cf1dd8SToby Isaac 25920cf1dd8SToby Isaac Input Parameter: 26020cf1dd8SToby Isaac . sp - the PetscDualSpace object to set options for 26120cf1dd8SToby Isaac 26220cf1dd8SToby Isaac Options Database: 2638f2aacc6SMatthew G. Knepley + -petscdualspace_order <order> - the approximation order of the space 264fe36a153SMatthew G. Knepley . -petscdualspace_form_degree <deg> - the form degree, say 0 for point evaluations, or 2 for area integrals 2658f2aacc6SMatthew G. Knepley . -petscdualspace_components <c> - the number of components, say d for a vector field 2668f2aacc6SMatthew G. Knepley - -petscdualspace_refcell <celltype> - Reference cell type name 26720cf1dd8SToby Isaac 268a4ce7ad1SMatthew G. Knepley Level: intermediate 26920cf1dd8SToby Isaac 270db781477SPatrick Sanan .seealso `PetscDualSpaceView()`, `PetscDualSpace`, `PetscObjectSetFromOptions()` 27120cf1dd8SToby Isaac @*/ 272*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetFromOptions(PetscDualSpace sp) 273*d71ae5a4SJacob Faibussowitsch { 2742df84da0SMatthew G. Knepley DMPolytopeType refCell = DM_POLYTOPE_TRIANGLE; 27520cf1dd8SToby Isaac const char *defaultType; 27620cf1dd8SToby Isaac char name[256]; 277f783ec47SMatthew G. Knepley PetscBool flg; 27820cf1dd8SToby Isaac 27920cf1dd8SToby Isaac PetscFunctionBegin; 28020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 28120cf1dd8SToby Isaac if (!((PetscObject)sp)->type_name) { 28220cf1dd8SToby Isaac defaultType = PETSCDUALSPACELAGRANGE; 28320cf1dd8SToby Isaac } else { 28420cf1dd8SToby Isaac defaultType = ((PetscObject)sp)->type_name; 28520cf1dd8SToby Isaac } 2869566063dSJacob Faibussowitsch if (!PetscSpaceRegisterAllCalled) PetscCall(PetscSpaceRegisterAll()); 28720cf1dd8SToby Isaac 288d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)sp); 2899566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-petscdualspace_type", "Dual space", "PetscDualSpaceSetType", PetscDualSpaceList, defaultType, name, 256, &flg)); 29020cf1dd8SToby Isaac if (flg) { 2919566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, name)); 29220cf1dd8SToby Isaac } else if (!((PetscObject)sp)->type_name) { 2939566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, defaultType)); 29420cf1dd8SToby Isaac } 2959566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_order", "The approximation order", "PetscDualSpaceSetOrder", sp->order, &sp->order, NULL, 0)); 2969566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-petscdualspace_form_degree", "The form degree of the dofs", "PetscDualSpaceSetFormDegree", sp->k, &sp->k, NULL)); 2979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_components", "The number of components", "PetscDualSpaceSetNumComponents", sp->Nc, &sp->Nc, NULL, 1)); 298dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, setfromoptions, PetscOptionsObject); 2999566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-petscdualspace_refcell", "Reference cell shape", "PetscDualSpaceSetReferenceCell", DMPolytopeTypes, (PetscEnum)refCell, (PetscEnum *)&refCell, &flg)); 300063ee4adSMatthew G. Knepley if (flg) { 301063ee4adSMatthew G. Knepley DM K; 302063ee4adSMatthew G. Knepley 3039566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, refCell, &K)); 3049566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(sp, K)); 3059566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 306063ee4adSMatthew G. Knepley } 307063ee4adSMatthew G. Knepley 30820cf1dd8SToby Isaac /* process any options handlers added with PetscObjectAddOptionsHandler() */ 309dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)sp, PetscOptionsObject)); 310d0609cedSBarry Smith PetscOptionsEnd(); 311063ee4adSMatthew G. Knepley sp->setfromoptionscalled = PETSC_TRUE; 31220cf1dd8SToby Isaac PetscFunctionReturn(0); 31320cf1dd8SToby Isaac } 31420cf1dd8SToby Isaac 31520cf1dd8SToby Isaac /*@ 31620cf1dd8SToby Isaac PetscDualSpaceSetUp - Construct a basis for the PetscDualSpace 31720cf1dd8SToby Isaac 318d083f849SBarry Smith Collective on sp 31920cf1dd8SToby Isaac 32020cf1dd8SToby Isaac Input Parameter: 32120cf1dd8SToby Isaac . sp - the PetscDualSpace object to setup 32220cf1dd8SToby Isaac 323a4ce7ad1SMatthew G. Knepley Level: intermediate 32420cf1dd8SToby Isaac 325db781477SPatrick Sanan .seealso `PetscDualSpaceView()`, `PetscDualSpaceDestroy()`, `PetscDualSpace` 32620cf1dd8SToby Isaac @*/ 327*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetUp(PetscDualSpace sp) 328*d71ae5a4SJacob Faibussowitsch { 32920cf1dd8SToby Isaac PetscFunctionBegin; 33020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 33120cf1dd8SToby Isaac if (sp->setupcalled) PetscFunctionReturn(0); 3329566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 33320cf1dd8SToby Isaac sp->setupcalled = PETSC_TRUE; 334dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, setup); 3359566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 3369566063dSJacob Faibussowitsch if (sp->setfromoptionscalled) PetscCall(PetscDualSpaceViewFromOptions(sp, NULL, "-petscdualspace_view")); 33720cf1dd8SToby Isaac PetscFunctionReturn(0); 33820cf1dd8SToby Isaac } 33920cf1dd8SToby Isaac 340*d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDualSpaceClearDMData_Internal(PetscDualSpace sp, DM dm) 341*d71ae5a4SJacob Faibussowitsch { 342b4457527SToby Isaac PetscInt pStart = -1, pEnd = -1, depth = -1; 343b4457527SToby Isaac 344b4457527SToby Isaac PetscFunctionBegin; 345b4457527SToby Isaac if (!dm) PetscFunctionReturn(0); 3469566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3479566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 348b4457527SToby Isaac 349b4457527SToby Isaac if (sp->pointSpaces) { 350b4457527SToby Isaac PetscInt i; 351b4457527SToby Isaac 35248a46eb9SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) PetscCall(PetscDualSpaceDestroy(&(sp->pointSpaces[i]))); 353b4457527SToby Isaac } 3549566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->pointSpaces)); 355b4457527SToby Isaac 356b4457527SToby Isaac if (sp->heightSpaces) { 357b4457527SToby Isaac PetscInt i; 358b4457527SToby Isaac 35948a46eb9SPierre Jolivet for (i = 0; i <= depth; i++) PetscCall(PetscDualSpaceDestroy(&(sp->heightSpaces[i]))); 360b4457527SToby Isaac } 3619566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->heightSpaces)); 362b4457527SToby Isaac 3639566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(sp->pointSection))); 3649566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->intNodes))); 3659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->intDofValues))); 3669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->intNodeValues))); 3679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->intMat))); 3689566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->allNodes))); 3699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->allDofValues))); 3709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->allNodeValues))); 3719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->allMat))); 3729566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->numDof)); 373b4457527SToby Isaac PetscFunctionReturn(0); 374b4457527SToby Isaac } 375b4457527SToby Isaac 37620cf1dd8SToby Isaac /*@ 37720cf1dd8SToby Isaac PetscDualSpaceDestroy - Destroys a PetscDualSpace object 37820cf1dd8SToby Isaac 379d083f849SBarry Smith Collective on sp 38020cf1dd8SToby Isaac 38120cf1dd8SToby Isaac Input Parameter: 38220cf1dd8SToby Isaac . sp - the PetscDualSpace object to destroy 38320cf1dd8SToby Isaac 384a4ce7ad1SMatthew G. Knepley Level: beginner 38520cf1dd8SToby Isaac 386db781477SPatrick Sanan .seealso `PetscDualSpaceView()`, `PetscDualSpace()`, `PetscDualSpaceCreate()` 38720cf1dd8SToby Isaac @*/ 388*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceDestroy(PetscDualSpace *sp) 389*d71ae5a4SJacob Faibussowitsch { 39020cf1dd8SToby Isaac PetscInt dim, f; 391b4457527SToby Isaac DM dm; 39220cf1dd8SToby Isaac 39320cf1dd8SToby Isaac PetscFunctionBegin; 39420cf1dd8SToby Isaac if (!*sp) PetscFunctionReturn(0); 39520cf1dd8SToby Isaac PetscValidHeaderSpecific((*sp), PETSCDUALSPACE_CLASSID, 1); 39620cf1dd8SToby Isaac 3979371c9d4SSatish Balay if (--((PetscObject)(*sp))->refct > 0) { 3989371c9d4SSatish Balay *sp = NULL; 3999371c9d4SSatish Balay PetscFunctionReturn(0); 4009371c9d4SSatish Balay } 40120cf1dd8SToby Isaac ((PetscObject)(*sp))->refct = 0; 40220cf1dd8SToby Isaac 4039566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(*sp, &dim)); 404b4457527SToby Isaac dm = (*sp)->dm; 405b4457527SToby Isaac 406dbbe0bcdSBarry Smith PetscTryTypeMethod((*sp), destroy); 4079566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceClearDMData_Internal(*sp, dm)); 408b4457527SToby Isaac 40948a46eb9SPierre Jolivet for (f = 0; f < dim; ++f) PetscCall(PetscQuadratureDestroy(&(*sp)->functional[f])); 4109566063dSJacob Faibussowitsch PetscCall(PetscFree((*sp)->functional)); 4119566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*sp)->dm)); 4129566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(sp)); 41320cf1dd8SToby Isaac PetscFunctionReturn(0); 41420cf1dd8SToby Isaac } 41520cf1dd8SToby Isaac 41620cf1dd8SToby Isaac /*@ 41720cf1dd8SToby Isaac PetscDualSpaceCreate - Creates an empty PetscDualSpace object. The type can then be set with PetscDualSpaceSetType(). 41820cf1dd8SToby Isaac 419d083f849SBarry Smith Collective 42020cf1dd8SToby Isaac 42120cf1dd8SToby Isaac Input Parameter: 42220cf1dd8SToby Isaac . comm - The communicator for the PetscDualSpace object 42320cf1dd8SToby Isaac 42420cf1dd8SToby Isaac Output Parameter: 42520cf1dd8SToby Isaac . sp - The PetscDualSpace object 42620cf1dd8SToby Isaac 42720cf1dd8SToby Isaac Level: beginner 42820cf1dd8SToby Isaac 429db781477SPatrick Sanan .seealso: `PetscDualSpaceSetType()`, `PETSCDUALSPACELAGRANGE` 43020cf1dd8SToby Isaac @*/ 431*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreate(MPI_Comm comm, PetscDualSpace *sp) 432*d71ae5a4SJacob Faibussowitsch { 43320cf1dd8SToby Isaac PetscDualSpace s; 43420cf1dd8SToby Isaac 43520cf1dd8SToby Isaac PetscFunctionBegin; 43620cf1dd8SToby Isaac PetscValidPointer(sp, 2); 4379566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(FECitation, &FEcite)); 43820cf1dd8SToby Isaac *sp = NULL; 4399566063dSJacob Faibussowitsch PetscCall(PetscFEInitializePackage()); 44020cf1dd8SToby Isaac 4419566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(s, PETSCDUALSPACE_CLASSID, "PetscDualSpace", "Dual Space", "PetscDualSpace", comm, PetscDualSpaceDestroy, PetscDualSpaceView)); 44220cf1dd8SToby Isaac 44320cf1dd8SToby Isaac s->order = 0; 44420cf1dd8SToby Isaac s->Nc = 1; 4454bee2e38SMatthew G. Knepley s->k = 0; 446b4457527SToby Isaac s->spdim = -1; 447b4457527SToby Isaac s->spintdim = -1; 448b4457527SToby Isaac s->uniform = PETSC_TRUE; 44920cf1dd8SToby Isaac s->setupcalled = PETSC_FALSE; 45020cf1dd8SToby Isaac 45120cf1dd8SToby Isaac *sp = s; 45220cf1dd8SToby Isaac PetscFunctionReturn(0); 45320cf1dd8SToby Isaac } 45420cf1dd8SToby Isaac 45520cf1dd8SToby Isaac /*@ 45620cf1dd8SToby Isaac PetscDualSpaceDuplicate - Creates a duplicate PetscDualSpace object, however it is not setup. 45720cf1dd8SToby Isaac 458d083f849SBarry Smith Collective on sp 45920cf1dd8SToby Isaac 46020cf1dd8SToby Isaac Input Parameter: 46120cf1dd8SToby Isaac . sp - The original PetscDualSpace 46220cf1dd8SToby Isaac 46320cf1dd8SToby Isaac Output Parameter: 46420cf1dd8SToby Isaac . spNew - The duplicate PetscDualSpace 46520cf1dd8SToby Isaac 46620cf1dd8SToby Isaac Level: beginner 46720cf1dd8SToby Isaac 468db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `PetscDualSpaceSetType()` 46920cf1dd8SToby Isaac @*/ 470*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceDuplicate(PetscDualSpace sp, PetscDualSpace *spNew) 471*d71ae5a4SJacob Faibussowitsch { 472b4457527SToby Isaac DM dm; 473b4457527SToby Isaac PetscDualSpaceType type; 474b4457527SToby Isaac const char *name; 47520cf1dd8SToby Isaac 47620cf1dd8SToby Isaac PetscFunctionBegin; 47720cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 47820cf1dd8SToby Isaac PetscValidPointer(spNew, 2); 4799566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(PetscObjectComm((PetscObject)sp), spNew)); 4809566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name)); 4819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*spNew, name)); 4829566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetType(sp, &type)); 4839566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(*spNew, type)); 4849566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 4859566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(*spNew, dm)); 486b4457527SToby Isaac 487b4457527SToby Isaac (*spNew)->order = sp->order; 488b4457527SToby Isaac (*spNew)->k = sp->k; 489b4457527SToby Isaac (*spNew)->Nc = sp->Nc; 490b4457527SToby Isaac (*spNew)->uniform = sp->uniform; 491dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, duplicate, *spNew); 49220cf1dd8SToby Isaac PetscFunctionReturn(0); 49320cf1dd8SToby Isaac } 49420cf1dd8SToby Isaac 49520cf1dd8SToby Isaac /*@ 49620cf1dd8SToby Isaac PetscDualSpaceGetDM - Get the DM representing the reference cell 49720cf1dd8SToby Isaac 49820cf1dd8SToby Isaac Not collective 49920cf1dd8SToby Isaac 50020cf1dd8SToby Isaac Input Parameter: 50120cf1dd8SToby Isaac . sp - The PetscDualSpace 50220cf1dd8SToby Isaac 50320cf1dd8SToby Isaac Output Parameter: 50420cf1dd8SToby Isaac . dm - The reference cell 50520cf1dd8SToby Isaac 50620cf1dd8SToby Isaac Level: intermediate 50720cf1dd8SToby Isaac 508db781477SPatrick Sanan .seealso: `PetscDualSpaceSetDM()`, `PetscDualSpaceCreate()` 50920cf1dd8SToby Isaac @*/ 510*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDM(PetscDualSpace sp, DM *dm) 511*d71ae5a4SJacob Faibussowitsch { 51220cf1dd8SToby Isaac PetscFunctionBegin; 51320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 51420cf1dd8SToby Isaac PetscValidPointer(dm, 2); 51520cf1dd8SToby Isaac *dm = sp->dm; 51620cf1dd8SToby Isaac PetscFunctionReturn(0); 51720cf1dd8SToby Isaac } 51820cf1dd8SToby Isaac 51920cf1dd8SToby Isaac /*@ 52020cf1dd8SToby Isaac PetscDualSpaceSetDM - Get the DM representing the reference cell 52120cf1dd8SToby Isaac 52220cf1dd8SToby Isaac Not collective 52320cf1dd8SToby Isaac 52420cf1dd8SToby Isaac Input Parameters: 52520cf1dd8SToby Isaac + sp - The PetscDualSpace 52620cf1dd8SToby Isaac - dm - The reference cell 52720cf1dd8SToby Isaac 52820cf1dd8SToby Isaac Level: intermediate 52920cf1dd8SToby Isaac 530db781477SPatrick Sanan .seealso: `PetscDualSpaceGetDM()`, `PetscDualSpaceCreate()` 53120cf1dd8SToby Isaac @*/ 532*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetDM(PetscDualSpace sp, DM dm) 533*d71ae5a4SJacob Faibussowitsch { 53420cf1dd8SToby Isaac PetscFunctionBegin; 53520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 53620cf1dd8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 53728b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change DM after dualspace is set up"); 5389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 53948a46eb9SPierre Jolivet if (sp->dm && sp->dm != dm) PetscCall(PetscDualSpaceClearDMData_Internal(sp, sp->dm)); 5409566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sp->dm)); 54120cf1dd8SToby Isaac sp->dm = dm; 54220cf1dd8SToby Isaac PetscFunctionReturn(0); 54320cf1dd8SToby Isaac } 54420cf1dd8SToby Isaac 54520cf1dd8SToby Isaac /*@ 54620cf1dd8SToby Isaac PetscDualSpaceGetOrder - Get the order of the dual space 54720cf1dd8SToby Isaac 54820cf1dd8SToby Isaac Not collective 54920cf1dd8SToby Isaac 55020cf1dd8SToby Isaac Input Parameter: 55120cf1dd8SToby Isaac . sp - The PetscDualSpace 55220cf1dd8SToby Isaac 55320cf1dd8SToby Isaac Output Parameter: 55420cf1dd8SToby Isaac . order - The order 55520cf1dd8SToby Isaac 55620cf1dd8SToby Isaac Level: intermediate 55720cf1dd8SToby Isaac 558db781477SPatrick Sanan .seealso: `PetscDualSpaceSetOrder()`, `PetscDualSpaceCreate()` 55920cf1dd8SToby Isaac @*/ 560*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetOrder(PetscDualSpace sp, PetscInt *order) 561*d71ae5a4SJacob Faibussowitsch { 56220cf1dd8SToby Isaac PetscFunctionBegin; 56320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 564dadcf809SJacob Faibussowitsch PetscValidIntPointer(order, 2); 56520cf1dd8SToby Isaac *order = sp->order; 56620cf1dd8SToby Isaac PetscFunctionReturn(0); 56720cf1dd8SToby Isaac } 56820cf1dd8SToby Isaac 56920cf1dd8SToby Isaac /*@ 57020cf1dd8SToby Isaac PetscDualSpaceSetOrder - Set the order of the dual space 57120cf1dd8SToby Isaac 57220cf1dd8SToby Isaac Not collective 57320cf1dd8SToby Isaac 57420cf1dd8SToby Isaac Input Parameters: 57520cf1dd8SToby Isaac + sp - The PetscDualSpace 57620cf1dd8SToby Isaac - order - The order 57720cf1dd8SToby Isaac 57820cf1dd8SToby Isaac Level: intermediate 57920cf1dd8SToby Isaac 580db781477SPatrick Sanan .seealso: `PetscDualSpaceGetOrder()`, `PetscDualSpaceCreate()` 58120cf1dd8SToby Isaac @*/ 582*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetOrder(PetscDualSpace sp, PetscInt order) 583*d71ae5a4SJacob Faibussowitsch { 58420cf1dd8SToby Isaac PetscFunctionBegin; 58520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 58628b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change order after dualspace is set up"); 58720cf1dd8SToby Isaac sp->order = order; 58820cf1dd8SToby Isaac PetscFunctionReturn(0); 58920cf1dd8SToby Isaac } 59020cf1dd8SToby Isaac 59120cf1dd8SToby Isaac /*@ 59220cf1dd8SToby Isaac PetscDualSpaceGetNumComponents - Return the number of components for this space 59320cf1dd8SToby Isaac 59420cf1dd8SToby Isaac Input Parameter: 59520cf1dd8SToby Isaac . sp - The PetscDualSpace 59620cf1dd8SToby Isaac 59720cf1dd8SToby Isaac Output Parameter: 59820cf1dd8SToby Isaac . Nc - The number of components 59920cf1dd8SToby Isaac 60020cf1dd8SToby Isaac Note: A vector space, for example, will have d components, where d is the spatial dimension 60120cf1dd8SToby Isaac 60220cf1dd8SToby Isaac Level: intermediate 60320cf1dd8SToby Isaac 604db781477SPatrick Sanan .seealso: `PetscDualSpaceSetNumComponents()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 60520cf1dd8SToby Isaac @*/ 606*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetNumComponents(PetscDualSpace sp, PetscInt *Nc) 607*d71ae5a4SJacob Faibussowitsch { 60820cf1dd8SToby Isaac PetscFunctionBegin; 60920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 610dadcf809SJacob Faibussowitsch PetscValidIntPointer(Nc, 2); 61120cf1dd8SToby Isaac *Nc = sp->Nc; 61220cf1dd8SToby Isaac PetscFunctionReturn(0); 61320cf1dd8SToby Isaac } 61420cf1dd8SToby Isaac 61520cf1dd8SToby Isaac /*@ 61620cf1dd8SToby Isaac PetscDualSpaceSetNumComponents - Set the number of components for this space 61720cf1dd8SToby Isaac 61820cf1dd8SToby Isaac Input Parameters: 61920cf1dd8SToby Isaac + sp - The PetscDualSpace 62020cf1dd8SToby Isaac - order - The number of components 62120cf1dd8SToby Isaac 62220cf1dd8SToby Isaac Level: intermediate 62320cf1dd8SToby Isaac 624db781477SPatrick Sanan .seealso: `PetscDualSpaceGetNumComponents()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 62520cf1dd8SToby Isaac @*/ 626*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetNumComponents(PetscDualSpace sp, PetscInt Nc) 627*d71ae5a4SJacob Faibussowitsch { 62820cf1dd8SToby Isaac PetscFunctionBegin; 62920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 63028b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 63120cf1dd8SToby Isaac sp->Nc = Nc; 63220cf1dd8SToby Isaac PetscFunctionReturn(0); 63320cf1dd8SToby Isaac } 63420cf1dd8SToby Isaac 63520cf1dd8SToby Isaac /*@ 63620cf1dd8SToby Isaac PetscDualSpaceGetFunctional - Get the i-th basis functional in the dual space 63720cf1dd8SToby Isaac 63820cf1dd8SToby Isaac Not collective 63920cf1dd8SToby Isaac 64020cf1dd8SToby Isaac Input Parameters: 64120cf1dd8SToby Isaac + sp - The PetscDualSpace 64220cf1dd8SToby Isaac - i - The basis number 64320cf1dd8SToby Isaac 64420cf1dd8SToby Isaac Output Parameter: 64520cf1dd8SToby Isaac . functional - The basis functional 64620cf1dd8SToby Isaac 64720cf1dd8SToby Isaac Level: intermediate 64820cf1dd8SToby Isaac 649db781477SPatrick Sanan .seealso: `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()` 65020cf1dd8SToby Isaac @*/ 651*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetFunctional(PetscDualSpace sp, PetscInt i, PetscQuadrature *functional) 652*d71ae5a4SJacob Faibussowitsch { 65320cf1dd8SToby Isaac PetscInt dim; 65420cf1dd8SToby Isaac 65520cf1dd8SToby Isaac PetscFunctionBegin; 65620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 65720cf1dd8SToby Isaac PetscValidPointer(functional, 3); 6589566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &dim)); 65963a3b9bcSJacob 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); 66020cf1dd8SToby Isaac *functional = sp->functional[i]; 66120cf1dd8SToby Isaac PetscFunctionReturn(0); 66220cf1dd8SToby Isaac } 66320cf1dd8SToby Isaac 66420cf1dd8SToby Isaac /*@ 66520cf1dd8SToby Isaac PetscDualSpaceGetDimension - Get the dimension of the dual space, i.e. the number of basis functionals 66620cf1dd8SToby Isaac 66720cf1dd8SToby Isaac Not collective 66820cf1dd8SToby Isaac 66920cf1dd8SToby Isaac Input Parameter: 67020cf1dd8SToby Isaac . sp - The PetscDualSpace 67120cf1dd8SToby Isaac 67220cf1dd8SToby Isaac Output Parameter: 67320cf1dd8SToby Isaac . dim - The dimension 67420cf1dd8SToby Isaac 67520cf1dd8SToby Isaac Level: intermediate 67620cf1dd8SToby Isaac 677db781477SPatrick Sanan .seealso: `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 67820cf1dd8SToby Isaac @*/ 679*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDimension(PetscDualSpace sp, PetscInt *dim) 680*d71ae5a4SJacob Faibussowitsch { 68120cf1dd8SToby Isaac PetscFunctionBegin; 68220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 683dadcf809SJacob Faibussowitsch PetscValidIntPointer(dim, 2); 684b4457527SToby Isaac if (sp->spdim < 0) { 685b4457527SToby Isaac PetscSection section; 686b4457527SToby Isaac 6879566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 688b4457527SToby Isaac if (section) { 6899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &(sp->spdim))); 690b4457527SToby Isaac } else sp->spdim = 0; 691b4457527SToby Isaac } 692b4457527SToby Isaac *dim = sp->spdim; 69320cf1dd8SToby Isaac PetscFunctionReturn(0); 69420cf1dd8SToby Isaac } 69520cf1dd8SToby Isaac 696b4457527SToby Isaac /*@ 697b4457527SToby 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 698b4457527SToby Isaac 699b4457527SToby Isaac Not collective 700b4457527SToby Isaac 701b4457527SToby Isaac Input Parameter: 702b4457527SToby Isaac . sp - The PetscDualSpace 703b4457527SToby Isaac 704b4457527SToby Isaac Output Parameter: 705b4457527SToby Isaac . dim - The dimension 706b4457527SToby Isaac 707b4457527SToby Isaac Level: intermediate 708b4457527SToby Isaac 709db781477SPatrick Sanan .seealso: `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 710b4457527SToby Isaac @*/ 711*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetInteriorDimension(PetscDualSpace sp, PetscInt *intdim) 712*d71ae5a4SJacob Faibussowitsch { 713b4457527SToby Isaac PetscFunctionBegin; 714b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 715dadcf809SJacob Faibussowitsch PetscValidIntPointer(intdim, 2); 716b4457527SToby Isaac if (sp->spintdim < 0) { 717b4457527SToby Isaac PetscSection section; 718b4457527SToby Isaac 7199566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 720b4457527SToby Isaac if (section) { 7219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &(sp->spintdim))); 722b4457527SToby Isaac } else sp->spintdim = 0; 723b4457527SToby Isaac } 724b4457527SToby Isaac *intdim = sp->spintdim; 725b4457527SToby Isaac PetscFunctionReturn(0); 726b4457527SToby Isaac } 727b4457527SToby Isaac 728b4457527SToby Isaac /*@ 729b4457527SToby Isaac PetscDualSpaceGetUniform - Whether this dual space is uniform 730b4457527SToby Isaac 731b4457527SToby Isaac Not collective 732b4457527SToby Isaac 733b4457527SToby Isaac Input Parameters: 734b4457527SToby Isaac . sp - A dual space 735b4457527SToby Isaac 736b4457527SToby Isaac Output Parameters: 737b4457527SToby Isaac . uniform - PETSC_TRUE if (a) the dual space is the same for each point in a stratum of the reference DMPlex, and 738b4457527SToby Isaac (b) every symmetry of each point in the reference DMPlex is also a symmetry of the point's dual space. 739b4457527SToby Isaac 740b4457527SToby Isaac Level: advanced 741b4457527SToby Isaac 742b4457527SToby Isaac Note: all of the usual spaces on simplex or tensor-product elements will be uniform, only reference cells 743b4457527SToby Isaac with non-uniform strata (like trianguar-prisms) or anisotropic hp dual spaces will not be uniform. 744b4457527SToby Isaac 745db781477SPatrick Sanan .seealso: `PetscDualSpaceGetPointSubspace()`, `PetscDualSpaceGetSymmetries()` 746b4457527SToby Isaac @*/ 747*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetUniform(PetscDualSpace sp, PetscBool *uniform) 748*d71ae5a4SJacob Faibussowitsch { 749b4457527SToby Isaac PetscFunctionBegin; 750b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 751dadcf809SJacob Faibussowitsch PetscValidBoolPointer(uniform, 2); 752b4457527SToby Isaac *uniform = sp->uniform; 753b4457527SToby Isaac PetscFunctionReturn(0); 754b4457527SToby Isaac } 755b4457527SToby Isaac 75620cf1dd8SToby Isaac /*@C 75720cf1dd8SToby Isaac PetscDualSpaceGetNumDof - Get the number of degrees of freedom for each spatial (topological) dimension 75820cf1dd8SToby Isaac 75920cf1dd8SToby Isaac Not collective 76020cf1dd8SToby Isaac 76120cf1dd8SToby Isaac Input Parameter: 76220cf1dd8SToby Isaac . sp - The PetscDualSpace 76320cf1dd8SToby Isaac 76420cf1dd8SToby Isaac Output Parameter: 76520cf1dd8SToby Isaac . numDof - An array of length dim+1 which holds the number of dofs for each dimension 76620cf1dd8SToby Isaac 76720cf1dd8SToby Isaac Level: intermediate 76820cf1dd8SToby Isaac 769db781477SPatrick Sanan .seealso: `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 77020cf1dd8SToby Isaac @*/ 771*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetNumDof(PetscDualSpace sp, const PetscInt **numDof) 772*d71ae5a4SJacob Faibussowitsch { 77320cf1dd8SToby Isaac PetscFunctionBegin; 77420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 77520cf1dd8SToby Isaac PetscValidPointer(numDof, 2); 77628b400f6SJacob 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"); 777b4457527SToby Isaac if (!sp->numDof) { 778b4457527SToby Isaac DM dm; 779b4457527SToby Isaac PetscInt depth, d; 780b4457527SToby Isaac PetscSection section; 781b4457527SToby Isaac 7829566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 7839566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 7849566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth + 1, &(sp->numDof))); 7859566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 786b4457527SToby Isaac for (d = 0; d <= depth; d++) { 787b4457527SToby Isaac PetscInt dStart, dEnd; 788b4457527SToby Isaac 7899566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 790b4457527SToby Isaac if (dEnd <= dStart) continue; 7919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, dStart, &(sp->numDof[d]))); 792b4457527SToby Isaac } 793b4457527SToby Isaac } 794b4457527SToby Isaac *numDof = sp->numDof; 79508401ef6SPierre Jolivet PetscCheck(*numDof, PetscObjectComm((PetscObject)sp), PETSC_ERR_LIB, "Empty numDof[] returned from dual space implementation"); 79620cf1dd8SToby Isaac PetscFunctionReturn(0); 79720cf1dd8SToby Isaac } 79820cf1dd8SToby Isaac 799b4457527SToby Isaac /* create the section of the right size and set a permutation for topological ordering */ 800*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSectionCreate_Internal(PetscDualSpace sp, PetscSection *topSection) 801*d71ae5a4SJacob Faibussowitsch { 802b4457527SToby Isaac DM dm; 803b4457527SToby Isaac PetscInt pStart, pEnd, cStart, cEnd, c, depth, count, i; 804b4457527SToby Isaac PetscInt *seen, *perm; 805b4457527SToby Isaac PetscSection section; 806b4457527SToby Isaac 807b4457527SToby Isaac PetscFunctionBegin; 808b4457527SToby Isaac dm = sp->dm; 8099566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion)); 8109566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 8129566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &seen)); 8139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &perm)); 8149566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8159566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 816b4457527SToby Isaac for (c = cStart, count = 0; c < cEnd; c++) { 817b4457527SToby Isaac PetscInt closureSize = -1, e; 818b4457527SToby Isaac PetscInt *closure = NULL; 819b4457527SToby Isaac 820b4457527SToby Isaac perm[count++] = c; 821b4457527SToby Isaac seen[c - pStart] = 1; 8229566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 823b4457527SToby Isaac for (e = 0; e < closureSize; e++) { 824b4457527SToby Isaac PetscInt point = closure[2 * e]; 825b4457527SToby Isaac 826b4457527SToby Isaac if (seen[point - pStart]) continue; 827b4457527SToby Isaac perm[count++] = point; 828b4457527SToby Isaac seen[point - pStart] = 1; 829b4457527SToby Isaac } 8309566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 831b4457527SToby Isaac } 8321dca8a05SBarry Smith PetscCheck(count == pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad topological ordering"); 8339371c9d4SSatish Balay for (i = 0; i < pEnd - pStart; i++) 8349371c9d4SSatish Balay if (perm[i] != i) break; 835b4457527SToby Isaac if (i < pEnd - pStart) { 836b4457527SToby Isaac IS permIS; 837b4457527SToby Isaac 8389566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pEnd - pStart, perm, PETSC_OWN_POINTER, &permIS)); 8399566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(permIS)); 8409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(section, permIS)); 8419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS)); 842b4457527SToby Isaac } else { 8439566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 844b4457527SToby Isaac } 8459566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 846b4457527SToby Isaac *topSection = section; 847b4457527SToby Isaac PetscFunctionReturn(0); 848b4457527SToby Isaac } 849b4457527SToby Isaac 850b4457527SToby Isaac /* mark boundary points and set up */ 851*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSectionSetUp_Internal(PetscDualSpace sp, PetscSection section) 852*d71ae5a4SJacob Faibussowitsch { 853b4457527SToby Isaac DM dm; 854b4457527SToby Isaac DMLabel boundary; 855b4457527SToby Isaac PetscInt pStart, pEnd, p; 856b4457527SToby Isaac 857b4457527SToby Isaac PetscFunctionBegin; 858b4457527SToby Isaac dm = sp->dm; 8599566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "boundary", &boundary)); 8609566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 8619566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, 1, boundary)); 8629566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, boundary)); 8639566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 864b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 865b4457527SToby Isaac PetscInt bval; 866b4457527SToby Isaac 8679566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(boundary, p, &bval)); 868b4457527SToby Isaac if (bval == 1) { 869b4457527SToby Isaac PetscInt dof; 870b4457527SToby Isaac 8719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 8729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetConstraintDof(section, p, dof)); 873b4457527SToby Isaac } 874b4457527SToby Isaac } 8759566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&boundary)); 8769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 877b4457527SToby Isaac PetscFunctionReturn(0); 878b4457527SToby Isaac } 879b4457527SToby Isaac 880a4ce7ad1SMatthew G. Knepley /*@ 881b4457527SToby Isaac PetscDualSpaceGetSection - Create a PetscSection over the reference cell with the layout from this space 882a4ce7ad1SMatthew G. Knepley 883a4ce7ad1SMatthew G. Knepley Collective on sp 884a4ce7ad1SMatthew G. Knepley 885a4ce7ad1SMatthew G. Knepley Input Parameters: 886f0fc11ceSJed Brown . sp - The PetscDualSpace 887a4ce7ad1SMatthew G. Knepley 888a4ce7ad1SMatthew G. Knepley Output Parameter: 889a4ce7ad1SMatthew G. Knepley . section - The section 890a4ce7ad1SMatthew G. Knepley 891a4ce7ad1SMatthew G. Knepley Level: advanced 892a4ce7ad1SMatthew G. Knepley 893db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `DMPLEX` 894a4ce7ad1SMatthew G. Knepley @*/ 895*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetSection(PetscDualSpace sp, PetscSection *section) 896*d71ae5a4SJacob Faibussowitsch { 897b4457527SToby Isaac PetscInt pStart, pEnd, p; 898b4457527SToby Isaac 899b4457527SToby Isaac PetscFunctionBegin; 90078f1d139SRomain Beucher if (!sp->dm) { 90178f1d139SRomain Beucher *section = NULL; 90278f1d139SRomain Beucher PetscFunctionReturn(0); 90378f1d139SRomain Beucher } 904b4457527SToby Isaac if (!sp->pointSection) { 905b4457527SToby Isaac /* mark the boundary */ 9069566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionCreate_Internal(sp, &(sp->pointSection))); 9079566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(sp->dm, &pStart, &pEnd)); 908b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 909b4457527SToby Isaac PetscDualSpace psp; 910b4457527SToby Isaac 9119566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, p, &psp)); 912b4457527SToby Isaac if (psp) { 913b4457527SToby Isaac PetscInt dof; 914b4457527SToby Isaac 9159566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorDimension(psp, &dof)); 9169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sp->pointSection, p, dof)); 917b4457527SToby Isaac } 918b4457527SToby Isaac } 9199566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionSetUp_Internal(sp, sp->pointSection)); 920b4457527SToby Isaac } 921b4457527SToby Isaac *section = sp->pointSection; 922b4457527SToby Isaac PetscFunctionReturn(0); 923b4457527SToby Isaac } 924b4457527SToby Isaac 925b4457527SToby Isaac /* this assumes that all of the point dual spaces store their interior dofs first, which is true when the point DMs 926b4457527SToby Isaac * have one cell */ 927*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushForwardSubspaces_Internal(PetscDualSpace sp, PetscInt sStart, PetscInt sEnd) 928*d71ae5a4SJacob Faibussowitsch { 929b4457527SToby Isaac PetscReal *sv0, *v0, *J; 930b4457527SToby Isaac PetscSection section; 931b4457527SToby Isaac PetscInt dim, s, k; 93220cf1dd8SToby Isaac DM dm; 93320cf1dd8SToby Isaac 93420cf1dd8SToby Isaac PetscFunctionBegin; 9359566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 9369566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9379566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 9389566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim, &sv0, dim * dim, &J)); 9399566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFormDegree(sp, &k)); 940b4457527SToby Isaac for (s = sStart; s < sEnd; s++) { 941b4457527SToby Isaac PetscReal detJ, hdetJ; 942b4457527SToby Isaac PetscDualSpace ssp; 943b4457527SToby Isaac PetscInt dof, off, f, sdim; 944b4457527SToby Isaac PetscInt i, j; 945b4457527SToby Isaac DM sdm; 94620cf1dd8SToby Isaac 9479566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, s, &ssp)); 948b4457527SToby Isaac if (!ssp) continue; 9499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, s, &dof)); 9509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, s, &off)); 951b4457527SToby Isaac /* get the first vertex of the reference cell */ 9529566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(ssp, &sdm)); 9539566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sdm, &sdim)); 9549566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(sdm, 0, sv0, NULL, NULL, &hdetJ)); 9559566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, s, v0, J, NULL, &detJ)); 956b4457527SToby Isaac /* compactify Jacobian */ 9579371c9d4SSatish Balay for (i = 0; i < dim; i++) 9589371c9d4SSatish Balay for (j = 0; j < sdim; j++) J[i * sdim + j] = J[i * dim + j]; 959b4457527SToby Isaac for (f = 0; f < dof; f++) { 960b4457527SToby Isaac PetscQuadrature fn; 96120cf1dd8SToby Isaac 9629566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(ssp, f, &fn)); 9639566063dSJacob Faibussowitsch PetscCall(PetscQuadraturePushForward(fn, dim, sv0, v0, J, k, &(sp->functional[off + f]))); 96420cf1dd8SToby Isaac } 96520cf1dd8SToby Isaac } 9669566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, sv0, J)); 96720cf1dd8SToby Isaac PetscFunctionReturn(0); 96820cf1dd8SToby Isaac } 96920cf1dd8SToby Isaac 97020cf1dd8SToby Isaac /*@C 97120cf1dd8SToby Isaac PetscDualSpaceApply - Apply a functional from the dual space basis to an input function 97220cf1dd8SToby Isaac 97320cf1dd8SToby Isaac Input Parameters: 97420cf1dd8SToby Isaac + sp - The PetscDualSpace object 97520cf1dd8SToby Isaac . f - The basis functional index 97620cf1dd8SToby Isaac . time - The time 97720cf1dd8SToby 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) 97820cf1dd8SToby Isaac . numComp - The number of components for the function 97920cf1dd8SToby Isaac . func - The input function 98020cf1dd8SToby Isaac - ctx - A context for the function 98120cf1dd8SToby Isaac 98220cf1dd8SToby Isaac Output Parameter: 98320cf1dd8SToby Isaac . value - numComp output values 98420cf1dd8SToby Isaac 98520cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 98620cf1dd8SToby Isaac 98720cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 98820cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 98920cf1dd8SToby Isaac 990a4ce7ad1SMatthew G. Knepley Level: beginner 99120cf1dd8SToby Isaac 992db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 99320cf1dd8SToby Isaac @*/ 994*d71ae5a4SJacob Faibussowitsch 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) 995*d71ae5a4SJacob Faibussowitsch { 99620cf1dd8SToby Isaac PetscFunctionBegin; 99720cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 99820cf1dd8SToby Isaac PetscValidPointer(cgeom, 4); 999dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 1000dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, apply, f, time, cgeom, numComp, func, ctx, value); 100120cf1dd8SToby Isaac PetscFunctionReturn(0); 100220cf1dd8SToby Isaac } 100320cf1dd8SToby Isaac 100420cf1dd8SToby Isaac /*@C 1005b4457527SToby Isaac PetscDualSpaceApplyAll - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetAllData() 100620cf1dd8SToby Isaac 100720cf1dd8SToby Isaac Input Parameters: 100820cf1dd8SToby Isaac + sp - The PetscDualSpace object 1009b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetAllData() 101020cf1dd8SToby Isaac 101120cf1dd8SToby Isaac Output Parameter: 101220cf1dd8SToby Isaac . spValue - The values of all dual space functionals 101320cf1dd8SToby Isaac 1014a4ce7ad1SMatthew G. Knepley Level: beginner 101520cf1dd8SToby Isaac 1016db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 101720cf1dd8SToby Isaac @*/ 1018*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyAll(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1019*d71ae5a4SJacob Faibussowitsch { 102020cf1dd8SToby Isaac PetscFunctionBegin; 102120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1022dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyall, pointEval, spValue); 102320cf1dd8SToby Isaac PetscFunctionReturn(0); 102420cf1dd8SToby Isaac } 102520cf1dd8SToby Isaac 102620cf1dd8SToby Isaac /*@C 1027b4457527SToby Isaac PetscDualSpaceApplyInterior - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetInteriorData() 1028b4457527SToby Isaac 1029b4457527SToby Isaac Input Parameters: 1030b4457527SToby Isaac + sp - The PetscDualSpace object 1031b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetInteriorData() 1032b4457527SToby Isaac 1033b4457527SToby Isaac Output Parameter: 1034b4457527SToby Isaac . spValue - The values of interior dual space functionals 1035b4457527SToby Isaac 1036b4457527SToby Isaac Level: beginner 1037b4457527SToby Isaac 1038db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1039b4457527SToby Isaac @*/ 1040*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyInterior(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1041*d71ae5a4SJacob Faibussowitsch { 1042b4457527SToby Isaac PetscFunctionBegin; 1043b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1044dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyint, pointEval, spValue); 1045b4457527SToby Isaac PetscFunctionReturn(0); 1046b4457527SToby Isaac } 1047b4457527SToby Isaac 1048b4457527SToby Isaac /*@C 104920cf1dd8SToby Isaac PetscDualSpaceApplyDefault - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional. 105020cf1dd8SToby Isaac 105120cf1dd8SToby Isaac Input Parameters: 105220cf1dd8SToby Isaac + sp - The PetscDualSpace object 105320cf1dd8SToby Isaac . f - The basis functional index 105420cf1dd8SToby Isaac . time - The time 105520cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian) 105620cf1dd8SToby Isaac . Nc - The number of components for the function 105720cf1dd8SToby Isaac . func - The input function 105820cf1dd8SToby Isaac - ctx - A context for the function 105920cf1dd8SToby Isaac 106020cf1dd8SToby Isaac Output Parameter: 106120cf1dd8SToby Isaac . value - The output value 106220cf1dd8SToby Isaac 106320cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 106420cf1dd8SToby Isaac 106520cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 106620cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 106720cf1dd8SToby Isaac 106820cf1dd8SToby Isaac and the idea is to evaluate the functional as an integral 106920cf1dd8SToby Isaac 107020cf1dd8SToby Isaac $ n(f) = int dx n(x) . f(x) 107120cf1dd8SToby Isaac 107220cf1dd8SToby Isaac where both n and f have Nc components. 107320cf1dd8SToby Isaac 1074a4ce7ad1SMatthew G. Knepley Level: beginner 107520cf1dd8SToby Isaac 1076db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 107720cf1dd8SToby Isaac @*/ 1078*d71ae5a4SJacob Faibussowitsch 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) 1079*d71ae5a4SJacob Faibussowitsch { 108020cf1dd8SToby Isaac DM dm; 108120cf1dd8SToby Isaac PetscQuadrature n; 108220cf1dd8SToby Isaac const PetscReal *points, *weights; 108320cf1dd8SToby Isaac PetscReal x[3]; 108420cf1dd8SToby Isaac PetscScalar *val; 108520cf1dd8SToby Isaac PetscInt dim, dE, qNc, c, Nq, q; 108620cf1dd8SToby Isaac PetscBool isAffine; 108720cf1dd8SToby Isaac 108820cf1dd8SToby Isaac PetscFunctionBegin; 108920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1090dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 10919566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 10929566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 10939566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, &dim, &qNc, &Nq, &points, &weights)); 109463a3b9bcSJacob 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); 109563a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 10969566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 109720cf1dd8SToby Isaac *value = 0.0; 109820cf1dd8SToby Isaac isAffine = cgeom->isAffine; 109920cf1dd8SToby Isaac dE = cgeom->dimEmbed; 110020cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 110120cf1dd8SToby Isaac if (isAffine) { 110220cf1dd8SToby Isaac CoordinatesRefToReal(dE, cgeom->dim, cgeom->xi, cgeom->v, cgeom->J, &points[q * dim], x); 11039566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, x, Nc, val, ctx)); 110420cf1dd8SToby Isaac } else { 11059566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, &cgeom->v[dE * q], Nc, val, ctx)); 110620cf1dd8SToby Isaac } 1107ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) *value += val[c] * weights[q * Nc + c]; 110820cf1dd8SToby Isaac } 11099566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 111020cf1dd8SToby Isaac PetscFunctionReturn(0); 111120cf1dd8SToby Isaac } 111220cf1dd8SToby Isaac 111320cf1dd8SToby Isaac /*@C 1114b4457527SToby Isaac PetscDualSpaceApplyAllDefault - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetAllData() 111520cf1dd8SToby Isaac 111620cf1dd8SToby Isaac Input Parameters: 111720cf1dd8SToby Isaac + sp - The PetscDualSpace object 1118b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetAllData() 111920cf1dd8SToby Isaac 112020cf1dd8SToby Isaac Output Parameter: 112120cf1dd8SToby Isaac . spValue - The values of all dual space functionals 112220cf1dd8SToby Isaac 1123a4ce7ad1SMatthew G. Knepley Level: beginner 112420cf1dd8SToby Isaac 1125db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 112620cf1dd8SToby Isaac @*/ 1127*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyAllDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1128*d71ae5a4SJacob Faibussowitsch { 1129b4457527SToby Isaac Vec pointValues, dofValues; 1130b4457527SToby Isaac Mat allMat; 113120cf1dd8SToby Isaac 113220cf1dd8SToby Isaac PetscFunctionBegin; 113320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 113420cf1dd8SToby Isaac PetscValidScalarPointer(pointEval, 2); 1135064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11369566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetAllData(sp, NULL, &allMat)); 113748a46eb9SPierre Jolivet if (!(sp->allNodeValues)) PetscCall(MatCreateVecs(allMat, &(sp->allNodeValues), NULL)); 1138b4457527SToby Isaac pointValues = sp->allNodeValues; 113948a46eb9SPierre Jolivet if (!(sp->allDofValues)) PetscCall(MatCreateVecs(allMat, NULL, &(sp->allDofValues))); 1140b4457527SToby Isaac dofValues = sp->allDofValues; 11419566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11429566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11439566063dSJacob Faibussowitsch PetscCall(MatMult(allMat, pointValues, dofValues)); 11449566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11459566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 1146b4457527SToby Isaac PetscFunctionReturn(0); 114720cf1dd8SToby Isaac } 1148b4457527SToby Isaac 1149b4457527SToby Isaac /*@C 1150b4457527SToby Isaac PetscDualSpaceApplyInteriorDefault - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetInteriorData() 1151b4457527SToby Isaac 1152b4457527SToby Isaac Input Parameters: 1153b4457527SToby Isaac + sp - The PetscDualSpace object 1154b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetInteriorData() 1155b4457527SToby Isaac 1156b4457527SToby Isaac Output Parameter: 1157b4457527SToby Isaac . spValue - The values of interior dual space functionals 1158b4457527SToby Isaac 1159b4457527SToby Isaac Level: beginner 1160b4457527SToby Isaac 1161db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1162b4457527SToby Isaac @*/ 1163*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyInteriorDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1164*d71ae5a4SJacob Faibussowitsch { 1165b4457527SToby Isaac Vec pointValues, dofValues; 1166b4457527SToby Isaac Mat intMat; 1167b4457527SToby Isaac 1168b4457527SToby Isaac PetscFunctionBegin; 1169b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1170b4457527SToby Isaac PetscValidScalarPointer(pointEval, 2); 1171064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11729566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(sp, NULL, &intMat)); 117348a46eb9SPierre Jolivet if (!(sp->intNodeValues)) PetscCall(MatCreateVecs(intMat, &(sp->intNodeValues), NULL)); 1174b4457527SToby Isaac pointValues = sp->intNodeValues; 117548a46eb9SPierre Jolivet if (!(sp->intDofValues)) PetscCall(MatCreateVecs(intMat, NULL, &(sp->intDofValues))); 1176b4457527SToby Isaac dofValues = sp->intDofValues; 11779566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11789566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11799566063dSJacob Faibussowitsch PetscCall(MatMult(intMat, pointValues, dofValues)); 11809566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11819566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 118220cf1dd8SToby Isaac PetscFunctionReturn(0); 118320cf1dd8SToby Isaac } 118420cf1dd8SToby Isaac 1185a4ce7ad1SMatthew G. Knepley /*@ 1186b4457527SToby Isaac PetscDualSpaceGetAllData - Get all quadrature nodes from this space, and the matrix that sends quadrature node values to degree-of-freedom values 1187a4ce7ad1SMatthew G. Knepley 1188a4ce7ad1SMatthew G. Knepley Input Parameter: 1189a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1190a4ce7ad1SMatthew G. Knepley 1191d8d19677SJose E. Roman Output Parameters: 1192b4457527SToby Isaac + allNodes - A PetscQuadrature object containing all evaluation nodes 1193b4457527SToby Isaac - allMat - A Mat for the node-to-dof transformation 1194a4ce7ad1SMatthew G. Knepley 1195a4ce7ad1SMatthew G. Knepley Level: advanced 1196a4ce7ad1SMatthew G. Knepley 1197db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1198a4ce7ad1SMatthew G. Knepley @*/ 1199*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetAllData(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 1200*d71ae5a4SJacob Faibussowitsch { 120120cf1dd8SToby Isaac PetscFunctionBegin; 120220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1203b4457527SToby Isaac if (allNodes) PetscValidPointer(allNodes, 2); 1204b4457527SToby Isaac if (allMat) PetscValidPointer(allMat, 3); 1205b4457527SToby Isaac if ((!sp->allNodes || !sp->allMat) && sp->ops->createalldata) { 1206b4457527SToby Isaac PetscQuadrature qpoints; 1207b4457527SToby Isaac Mat amat; 1208b4457527SToby Isaac 1209dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createalldata, &qpoints, &amat); 12109566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->allNodes))); 12119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->allMat))); 1212b4457527SToby Isaac sp->allNodes = qpoints; 1213b4457527SToby Isaac sp->allMat = amat; 121420cf1dd8SToby Isaac } 1215b4457527SToby Isaac if (allNodes) *allNodes = sp->allNodes; 1216b4457527SToby Isaac if (allMat) *allMat = sp->allMat; 121720cf1dd8SToby Isaac PetscFunctionReturn(0); 121820cf1dd8SToby Isaac } 121920cf1dd8SToby Isaac 1220a4ce7ad1SMatthew G. Knepley /*@ 1221b4457527SToby Isaac PetscDualSpaceCreateAllDataDefault - Create all evaluation nodes and the node-to-dof matrix by examining functionals 1222a4ce7ad1SMatthew G. Knepley 1223a4ce7ad1SMatthew G. Knepley Input Parameter: 1224a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1225a4ce7ad1SMatthew G. Knepley 1226d8d19677SJose E. Roman Output Parameters: 1227b4457527SToby Isaac + allNodes - A PetscQuadrature object containing all evaluation nodes 1228b4457527SToby Isaac - allMat - A Mat for the node-to-dof transformation 1229a4ce7ad1SMatthew G. Knepley 1230a4ce7ad1SMatthew G. Knepley Level: advanced 1231a4ce7ad1SMatthew G. Knepley 1232db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 1233a4ce7ad1SMatthew G. Knepley @*/ 1234*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreateAllDataDefault(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 1235*d71ae5a4SJacob Faibussowitsch { 123620cf1dd8SToby Isaac PetscInt spdim; 123720cf1dd8SToby Isaac PetscInt numPoints, offset; 123820cf1dd8SToby Isaac PetscReal *points; 123920cf1dd8SToby Isaac PetscInt f, dim; 1240b4457527SToby Isaac PetscInt Nc, nrows, ncols; 1241b4457527SToby Isaac PetscInt maxNumPoints; 124220cf1dd8SToby Isaac PetscQuadrature q; 1243b4457527SToby Isaac Mat A; 124420cf1dd8SToby Isaac 124520cf1dd8SToby Isaac PetscFunctionBegin; 12469566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 12479566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &spdim)); 124820cf1dd8SToby Isaac if (!spdim) { 12499566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes)); 12509566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, 0, 0, 0, NULL, NULL)); 125120cf1dd8SToby Isaac } 1252b4457527SToby Isaac nrows = spdim; 12539566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, 0, &q)); 12549566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, NULL, &numPoints, NULL, NULL)); 1255b4457527SToby Isaac maxNumPoints = numPoints; 125620cf1dd8SToby Isaac for (f = 1; f < spdim; f++) { 125720cf1dd8SToby Isaac PetscInt Np; 125820cf1dd8SToby Isaac 12599566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q)); 12609566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL)); 126120cf1dd8SToby Isaac numPoints += Np; 1262b4457527SToby Isaac maxNumPoints = PetscMax(maxNumPoints, Np); 126320cf1dd8SToby Isaac } 1264b4457527SToby Isaac ncols = numPoints * Nc; 12659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points)); 12669566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, nrows, ncols, maxNumPoints * Nc, NULL, &A)); 126720cf1dd8SToby Isaac for (f = 0, offset = 0; f < spdim; f++) { 1268b4457527SToby Isaac const PetscReal *p, *w; 126920cf1dd8SToby Isaac PetscInt Np, i; 1270b4457527SToby Isaac PetscInt fnc; 127120cf1dd8SToby Isaac 12729566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q)); 12739566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, &fnc, &Np, &p, &w)); 127408401ef6SPierre Jolivet PetscCheck(fnc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "functional component mismatch"); 1275ad540459SPierre Jolivet for (i = 0; i < Np * dim; i++) points[offset * dim + i] = p[i]; 127648a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(A, f, offset * Nc, w[i], INSERT_VALUES)); 1277b4457527SToby Isaac offset += Np; 1278b4457527SToby Isaac } 12799566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 12809566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 12819566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes)); 12829566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, dim, 0, numPoints, points, NULL)); 1283b4457527SToby Isaac *allMat = A; 1284b4457527SToby Isaac PetscFunctionReturn(0); 1285b4457527SToby Isaac } 1286b4457527SToby Isaac 1287b4457527SToby Isaac /*@ 1288b4457527SToby Isaac PetscDualSpaceGetInteriorData - Get all quadrature points necessary to compute the interior degrees of freedom from 1289b4457527SToby Isaac this space, as well as the matrix that computes the degrees of freedom from the quadrature values. Degrees of 1290b4457527SToby Isaac freedom are interior degrees of freedom if they belong (by PetscDualSpaceGetSection()) to interior points in the 1291b4457527SToby Isaac reference DMPlex: complementary boundary degrees of freedom are marked as constrained in the section returned by 1292b4457527SToby Isaac PetscDualSpaceGetSection()). 1293b4457527SToby Isaac 1294b4457527SToby Isaac Input Parameter: 1295b4457527SToby Isaac . sp - The dualspace 1296b4457527SToby Isaac 1297d8d19677SJose E. Roman Output Parameters: 1298b4457527SToby Isaac + intNodes - A PetscQuadrature object containing all evaluation points needed to evaluate interior degrees of freedom 1299b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1300b4457527SToby Isaac the size of the constrained layout (PetscSectionGetConstrainStorageSize()) of the dual space section, 1301b4457527SToby Isaac npoints is the number of points in intNodes and nc is PetscDualSpaceGetNumComponents(). 1302b4457527SToby Isaac 1303b4457527SToby Isaac Level: advanced 1304b4457527SToby Isaac 1305db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceGetNumComponents()`, `PetscQuadratureGetData()` 1306b4457527SToby Isaac @*/ 1307*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetInteriorData(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1308*d71ae5a4SJacob Faibussowitsch { 1309b4457527SToby Isaac PetscFunctionBegin; 1310b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1311b4457527SToby Isaac if (intNodes) PetscValidPointer(intNodes, 2); 1312b4457527SToby Isaac if (intMat) PetscValidPointer(intMat, 3); 1313b4457527SToby Isaac if ((!sp->intNodes || !sp->intMat) && sp->ops->createintdata) { 1314b4457527SToby Isaac PetscQuadrature qpoints; 1315b4457527SToby Isaac Mat imat; 1316b4457527SToby Isaac 1317dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createintdata, &qpoints, &imat); 13189566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->intNodes))); 13199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->intMat))); 1320b4457527SToby Isaac sp->intNodes = qpoints; 1321b4457527SToby Isaac sp->intMat = imat; 1322b4457527SToby Isaac } 1323b4457527SToby Isaac if (intNodes) *intNodes = sp->intNodes; 1324b4457527SToby Isaac if (intMat) *intMat = sp->intMat; 1325b4457527SToby Isaac PetscFunctionReturn(0); 1326b4457527SToby Isaac } 1327b4457527SToby Isaac 1328b4457527SToby Isaac /*@ 1329b4457527SToby Isaac PetscDualSpaceCreateInteriorDataDefault - Create quadrature points by examining interior functionals and create the matrix mapping quadrature point values to interior dual space values 1330b4457527SToby Isaac 1331b4457527SToby Isaac Input Parameter: 1332b4457527SToby Isaac . sp - The dualspace 1333b4457527SToby Isaac 1334d8d19677SJose E. Roman Output Parameters: 1335b4457527SToby Isaac + intNodes - A PetscQuadrature object containing all evaluation points needed to evaluate interior degrees of freedom 1336b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1337b4457527SToby Isaac the size of the constrained layout (PetscSectionGetConstrainStorageSize()) of the dual space section, 1338b4457527SToby Isaac npoints is the number of points in allNodes and nc is PetscDualSpaceGetNumComponents(). 1339b4457527SToby Isaac 1340b4457527SToby Isaac Level: advanced 1341b4457527SToby Isaac 1342db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()`, `PetscDualSpaceGetInteriorData()` 1343b4457527SToby Isaac @*/ 1344*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreateInteriorDataDefault(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1345*d71ae5a4SJacob Faibussowitsch { 1346b4457527SToby Isaac DM dm; 1347b4457527SToby Isaac PetscInt spdim0; 1348b4457527SToby Isaac PetscInt Nc; 1349b4457527SToby Isaac PetscInt pStart, pEnd, p, f; 1350b4457527SToby Isaac PetscSection section; 1351b4457527SToby Isaac PetscInt numPoints, offset, matoffset; 1352b4457527SToby Isaac PetscReal *points; 1353b4457527SToby Isaac PetscInt dim; 1354b4457527SToby Isaac PetscInt *nnz; 1355b4457527SToby Isaac PetscQuadrature q; 1356b4457527SToby Isaac Mat imat; 1357b4457527SToby Isaac 1358b4457527SToby Isaac PetscFunctionBegin; 1359b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 13609566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 13619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &spdim0)); 1362b4457527SToby Isaac if (!spdim0) { 1363b4457527SToby Isaac *intNodes = NULL; 1364b4457527SToby Isaac *intMat = NULL; 1365b4457527SToby Isaac PetscFunctionReturn(0); 1366b4457527SToby Isaac } 13679566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 13689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 13699566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 13709566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 13719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(spdim0, &nnz)); 1372b4457527SToby Isaac for (p = pStart, f = 0, numPoints = 0; p < pEnd; p++) { 1373b4457527SToby Isaac PetscInt dof, cdof, off, d; 1374b4457527SToby Isaac 13759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 13769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1377b4457527SToby Isaac if (!(dof - cdof)) continue; 13789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1379b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1380b4457527SToby Isaac PetscInt Np; 1381b4457527SToby Isaac 13829566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q)); 13839566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL)); 1384b4457527SToby Isaac nnz[f] = Np * Nc; 1385b4457527SToby Isaac numPoints += Np; 1386b4457527SToby Isaac } 1387b4457527SToby Isaac } 13889566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, spdim0, numPoints * Nc, 0, nnz, &imat)); 13899566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 13909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points)); 1391b4457527SToby Isaac for (p = pStart, f = 0, offset = 0, matoffset = 0; p < pEnd; p++) { 1392b4457527SToby Isaac PetscInt dof, cdof, off, d; 1393b4457527SToby Isaac 13949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 13959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1396b4457527SToby Isaac if (!(dof - cdof)) continue; 13979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1398b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1399b4457527SToby Isaac const PetscReal *p; 1400b4457527SToby Isaac const PetscReal *w; 1401b4457527SToby Isaac PetscInt Np, i; 1402b4457527SToby Isaac 14039566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q)); 14049566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, &p, &w)); 1405ad540459SPierre Jolivet for (i = 0; i < Np * dim; i++) points[offset + i] = p[i]; 140648a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(imat, f, matoffset + i, w[i], INSERT_VALUES)); 1407b4457527SToby Isaac offset += Np * dim; 1408b4457527SToby Isaac matoffset += Np * Nc; 1409b4457527SToby Isaac } 1410b4457527SToby Isaac } 14119566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, intNodes)); 14129566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*intNodes, dim, 0, numPoints, points, NULL)); 14139566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(imat, MAT_FINAL_ASSEMBLY)); 14149566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(imat, MAT_FINAL_ASSEMBLY)); 1415b4457527SToby Isaac *intMat = imat; 141620cf1dd8SToby Isaac PetscFunctionReturn(0); 141720cf1dd8SToby Isaac } 141820cf1dd8SToby Isaac 14194f9ab2b4SJed Brown /*@ 14204f9ab2b4SJed Brown PetscDualSpaceEqual - Determine if a dual space is equivalent 14214f9ab2b4SJed Brown 14224f9ab2b4SJed Brown Input Parameters: 14234f9ab2b4SJed Brown + A - A PetscDualSpace object 14244f9ab2b4SJed Brown - B - Another PetscDualSpace object 14254f9ab2b4SJed Brown 14264f9ab2b4SJed Brown Output Parameter: 14274f9ab2b4SJed Brown . equal - PETSC_TRUE if the dual spaces are equivalent 14284f9ab2b4SJed Brown 14294f9ab2b4SJed Brown Level: advanced 14304f9ab2b4SJed Brown 1431db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 14324f9ab2b4SJed Brown @*/ 1433*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceEqual(PetscDualSpace A, PetscDualSpace B, PetscBool *equal) 1434*d71ae5a4SJacob Faibussowitsch { 14354f9ab2b4SJed Brown PetscInt sizeA, sizeB, dimA, dimB; 14364f9ab2b4SJed Brown const PetscInt *dofA, *dofB; 14374f9ab2b4SJed Brown PetscQuadrature quadA, quadB; 14384f9ab2b4SJed Brown Mat matA, matB; 14394f9ab2b4SJed Brown 14404f9ab2b4SJed Brown PetscFunctionBegin; 14414f9ab2b4SJed Brown PetscValidHeaderSpecific(A, PETSCDUALSPACE_CLASSID, 1); 14424f9ab2b4SJed Brown PetscValidHeaderSpecific(B, PETSCDUALSPACE_CLASSID, 2); 14434f9ab2b4SJed Brown PetscValidBoolPointer(equal, 3); 14444f9ab2b4SJed Brown *equal = PETSC_FALSE; 14459566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(A, &sizeA)); 14469566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(B, &sizeB)); 1447ad540459SPierre Jolivet if (sizeB != sizeA) PetscFunctionReturn(0); 14489566063dSJacob Faibussowitsch PetscCall(DMGetDimension(A->dm, &dimA)); 14499566063dSJacob Faibussowitsch PetscCall(DMGetDimension(B->dm, &dimB)); 1450ad540459SPierre Jolivet if (dimA != dimB) PetscFunctionReturn(0); 14514f9ab2b4SJed Brown 14529566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(A, &dofA)); 14539566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(B, &dofB)); 14544f9ab2b4SJed Brown for (PetscInt d = 0; d < dimA; d++) { 1455ad540459SPierre Jolivet if (dofA[d] != dofB[d]) PetscFunctionReturn(0); 14564f9ab2b4SJed Brown } 14574f9ab2b4SJed Brown 14589566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(A, &quadA, &matA)); 14599566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(B, &quadB, &matB)); 14604f9ab2b4SJed Brown if (!quadA && !quadB) { 14614f9ab2b4SJed Brown *equal = PETSC_TRUE; 14624f9ab2b4SJed Brown } else if (quadA && quadB) { 14639566063dSJacob Faibussowitsch PetscCall(PetscQuadratureEqual(quadA, quadB, equal)); 14644f9ab2b4SJed Brown if (*equal == PETSC_FALSE) PetscFunctionReturn(0); 14654f9ab2b4SJed Brown if (!matA && !matB) PetscFunctionReturn(0); 14669566063dSJacob Faibussowitsch if (matA && matB) PetscCall(MatEqual(matA, matB, equal)); 14674f9ab2b4SJed Brown else *equal = PETSC_FALSE; 14684f9ab2b4SJed Brown } 14694f9ab2b4SJed Brown PetscFunctionReturn(0); 14704f9ab2b4SJed Brown } 14714f9ab2b4SJed Brown 147220cf1dd8SToby Isaac /*@C 147320cf1dd8SToby Isaac PetscDualSpaceApplyFVM - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional at the cell centroid. 147420cf1dd8SToby Isaac 147520cf1dd8SToby Isaac Input Parameters: 147620cf1dd8SToby Isaac + sp - The PetscDualSpace object 147720cf1dd8SToby Isaac . f - The basis functional index 147820cf1dd8SToby Isaac . time - The time 147920cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we currently just use the centroid 148020cf1dd8SToby Isaac . Nc - The number of components for the function 148120cf1dd8SToby Isaac . func - The input function 148220cf1dd8SToby Isaac - ctx - A context for the function 148320cf1dd8SToby Isaac 148420cf1dd8SToby Isaac Output Parameter: 148520cf1dd8SToby Isaac . value - The output value (scalar) 148620cf1dd8SToby Isaac 148720cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 148820cf1dd8SToby Isaac 148920cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 149020cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 149120cf1dd8SToby Isaac 149220cf1dd8SToby Isaac and the idea is to evaluate the functional as an integral 149320cf1dd8SToby Isaac 149420cf1dd8SToby Isaac $ n(f) = int dx n(x) . f(x) 149520cf1dd8SToby Isaac 149620cf1dd8SToby Isaac where both n and f have Nc components. 149720cf1dd8SToby Isaac 1498a4ce7ad1SMatthew G. Knepley Level: beginner 149920cf1dd8SToby Isaac 1500db781477SPatrick Sanan .seealso: `PetscDualSpaceCreate()` 150120cf1dd8SToby Isaac @*/ 1502*d71ae5a4SJacob Faibussowitsch 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) 1503*d71ae5a4SJacob Faibussowitsch { 150420cf1dd8SToby Isaac DM dm; 150520cf1dd8SToby Isaac PetscQuadrature n; 150620cf1dd8SToby Isaac const PetscReal *points, *weights; 150720cf1dd8SToby Isaac PetscScalar *val; 150820cf1dd8SToby Isaac PetscInt dimEmbed, qNc, c, Nq, q; 150920cf1dd8SToby Isaac 151020cf1dd8SToby Isaac PetscFunctionBegin; 151120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1512dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 15139566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 15149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 15159566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 15169566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, NULL, &qNc, &Nq, &points, &weights)); 151763a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 15189566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 151920cf1dd8SToby Isaac *value = 0.; 152020cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 15219566063dSJacob Faibussowitsch PetscCall((*func)(dimEmbed, time, cgeom->centroid, Nc, val, ctx)); 1522ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) *value += val[c] * weights[q * Nc + c]; 152320cf1dd8SToby Isaac } 15249566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 152520cf1dd8SToby Isaac PetscFunctionReturn(0); 152620cf1dd8SToby Isaac } 152720cf1dd8SToby Isaac 152820cf1dd8SToby Isaac /*@ 152920cf1dd8SToby Isaac PetscDualSpaceGetHeightSubspace - Get the subset of the dual space basis that is supported on a mesh point of a 153020cf1dd8SToby Isaac given height. This assumes that the reference cell is symmetric over points of this height. 153120cf1dd8SToby Isaac 153220cf1dd8SToby Isaac If the dual space is not defined on mesh points of the given height (e.g. if the space is discontinuous and 153320cf1dd8SToby Isaac pointwise values are not defined on the element boundaries), or if the implementation of PetscDualSpace does not 153420cf1dd8SToby Isaac support extracting subspaces, then NULL is returned. 153520cf1dd8SToby Isaac 153620cf1dd8SToby Isaac This does not increment the reference count on the returned dual space, and the user should not destroy it. 153720cf1dd8SToby Isaac 153820cf1dd8SToby Isaac Not collective 153920cf1dd8SToby Isaac 154020cf1dd8SToby Isaac Input Parameters: 154120cf1dd8SToby Isaac + sp - the PetscDualSpace object 154220cf1dd8SToby Isaac - height - the height of the mesh point for which the subspace is desired 154320cf1dd8SToby Isaac 154420cf1dd8SToby Isaac Output Parameter: 154520cf1dd8SToby Isaac . subsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 154620cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 154720cf1dd8SToby Isaac 154820cf1dd8SToby Isaac Level: advanced 154920cf1dd8SToby Isaac 1550db781477SPatrick Sanan .seealso: `PetscSpaceGetHeightSubspace()`, `PetscDualSpace` 155120cf1dd8SToby Isaac @*/ 1552*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetHeightSubspace(PetscDualSpace sp, PetscInt height, PetscDualSpace *subsp) 1553*d71ae5a4SJacob Faibussowitsch { 1554b4457527SToby Isaac PetscInt depth = -1, cStart, cEnd; 1555b4457527SToby Isaac DM dm; 155620cf1dd8SToby Isaac 155720cf1dd8SToby Isaac PetscFunctionBegin; 155820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1559064a246eSJacob Faibussowitsch PetscValidPointer(subsp, 3); 156008401ef6SPierre 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"); 156120cf1dd8SToby Isaac *subsp = NULL; 1562b4457527SToby Isaac dm = sp->dm; 15639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 15641dca8a05SBarry Smith PetscCheck(height >= 0 && height <= depth, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid height"); 15659566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1566b4457527SToby Isaac if (height == 0 && cEnd == cStart + 1) { 1567b4457527SToby Isaac *subsp = sp; 1568b4457527SToby Isaac PetscFunctionReturn(0); 1569b4457527SToby Isaac } 1570b4457527SToby Isaac if (!sp->heightSpaces) { 1571b4457527SToby Isaac PetscInt h; 15729566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth + 1, &(sp->heightSpaces))); 1573b4457527SToby Isaac 1574b4457527SToby Isaac for (h = 0; h <= depth; h++) { 1575b4457527SToby Isaac if (h == 0 && cEnd == cStart + 1) continue; 15769566063dSJacob Faibussowitsch if (sp->ops->createheightsubspace) PetscCall((*sp->ops->createheightsubspace)(sp, height, &(sp->heightSpaces[h]))); 1577b4457527SToby Isaac else if (sp->pointSpaces) { 1578b4457527SToby Isaac PetscInt hStart, hEnd; 1579b4457527SToby Isaac 15809566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &hStart, &hEnd)); 1581b4457527SToby Isaac if (hEnd > hStart) { 1582665f567fSMatthew G. Knepley const char *name; 1583665f567fSMatthew G. Knepley 15849566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(sp->pointSpaces[hStart]))); 1585665f567fSMatthew G. Knepley if (sp->pointSpaces[hStart]) { 15869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name)); 15879566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sp->pointSpaces[hStart], name)); 1588665f567fSMatthew G. Knepley } 1589b4457527SToby Isaac sp->heightSpaces[h] = sp->pointSpaces[hStart]; 1590b4457527SToby Isaac } 1591b4457527SToby Isaac } 1592b4457527SToby Isaac } 1593b4457527SToby Isaac } 1594b4457527SToby Isaac *subsp = sp->heightSpaces[height]; 159520cf1dd8SToby Isaac PetscFunctionReturn(0); 159620cf1dd8SToby Isaac } 159720cf1dd8SToby Isaac 159820cf1dd8SToby Isaac /*@ 159920cf1dd8SToby Isaac PetscDualSpaceGetPointSubspace - Get the subset of the dual space basis that is supported on a particular mesh point. 160020cf1dd8SToby Isaac 160120cf1dd8SToby Isaac If the dual space is not defined on the mesh point (e.g. if the space is discontinuous and pointwise values are not 160220cf1dd8SToby Isaac defined on the element boundaries), or if the implementation of PetscDualSpace does not support extracting 160320cf1dd8SToby Isaac subspaces, then NULL is returned. 160420cf1dd8SToby Isaac 160520cf1dd8SToby Isaac This does not increment the reference count on the returned dual space, and the user should not destroy it. 160620cf1dd8SToby Isaac 160720cf1dd8SToby Isaac Not collective 160820cf1dd8SToby Isaac 160920cf1dd8SToby Isaac Input Parameters: 161020cf1dd8SToby Isaac + sp - the PetscDualSpace object 161120cf1dd8SToby Isaac - point - the point (in the dual space's DM) for which the subspace is desired 161220cf1dd8SToby Isaac 161320cf1dd8SToby Isaac Output Parameters: 161420cf1dd8SToby Isaac bdsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 161520cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 161620cf1dd8SToby Isaac 161720cf1dd8SToby Isaac Level: advanced 161820cf1dd8SToby Isaac 1619db781477SPatrick Sanan .seealso: `PetscDualSpace` 162020cf1dd8SToby Isaac @*/ 1621*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetPointSubspace(PetscDualSpace sp, PetscInt point, PetscDualSpace *bdsp) 1622*d71ae5a4SJacob Faibussowitsch { 1623b4457527SToby Isaac PetscInt pStart = 0, pEnd = 0, cStart, cEnd; 1624b4457527SToby Isaac DM dm; 162520cf1dd8SToby Isaac 162620cf1dd8SToby Isaac PetscFunctionBegin; 162720cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1628064a246eSJacob Faibussowitsch PetscValidPointer(bdsp, 3); 162920cf1dd8SToby Isaac *bdsp = NULL; 1630b4457527SToby Isaac dm = sp->dm; 16319566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 16321dca8a05SBarry Smith PetscCheck(point >= pStart && point <= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid point"); 16339566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1634b4457527SToby 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 */ 1635b4457527SToby Isaac *bdsp = sp; 1636b4457527SToby Isaac PetscFunctionReturn(0); 1637b4457527SToby Isaac } 1638b4457527SToby Isaac if (!sp->pointSpaces) { 1639b4457527SToby Isaac PetscInt p; 16409566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &(sp->pointSpaces))); 164120cf1dd8SToby Isaac 1642b4457527SToby Isaac for (p = 0; p < pEnd - pStart; p++) { 1643b4457527SToby Isaac if (p + pStart == cStart && cEnd == cStart + 1) continue; 16449566063dSJacob Faibussowitsch if (sp->ops->createpointsubspace) PetscCall((*sp->ops->createpointsubspace)(sp, p + pStart, &(sp->pointSpaces[p]))); 1645b4457527SToby Isaac else if (sp->heightSpaces || sp->ops->createheightsubspace) { 1646b4457527SToby Isaac PetscInt dim, depth, height; 1647b4457527SToby Isaac DMLabel label; 1648b4457527SToby Isaac 16499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &dim)); 16509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 16519566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, p + pStart, &depth)); 165220cf1dd8SToby Isaac height = dim - depth; 16539566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(sp, height, &(sp->pointSpaces[p]))); 16549566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sp->pointSpaces[p])); 165520cf1dd8SToby Isaac } 1656b4457527SToby Isaac } 1657b4457527SToby Isaac } 1658b4457527SToby Isaac *bdsp = sp->pointSpaces[point - pStart]; 165920cf1dd8SToby Isaac PetscFunctionReturn(0); 166020cf1dd8SToby Isaac } 166120cf1dd8SToby Isaac 16626f905325SMatthew G. Knepley /*@C 16636f905325SMatthew G. Knepley PetscDualSpaceGetSymmetries - Returns a description of the symmetries of this basis 16646f905325SMatthew G. Knepley 16656f905325SMatthew G. Knepley Not collective 16666f905325SMatthew G. Knepley 16676f905325SMatthew G. Knepley Input Parameter: 16686f905325SMatthew G. Knepley . sp - the PetscDualSpace object 16696f905325SMatthew G. Knepley 16706f905325SMatthew G. Knepley Output Parameters: 1671b4457527SToby Isaac + perms - Permutations of the interior degrees of freedom, parameterized by the point orientation 1672b4457527SToby Isaac - flips - Sign reversal of the interior degrees of freedom, parameterized by the point orientation 16736f905325SMatthew G. Knepley 16746f905325SMatthew G. Knepley Note: The permutation and flip arrays are organized in the following way 16756f905325SMatthew G. Knepley $ perms[p][ornt][dof # on point] = new local dof # 16766f905325SMatthew G. Knepley $ flips[p][ornt][dof # on point] = reversal or not 16776f905325SMatthew G. Knepley 16786f905325SMatthew G. Knepley Level: developer 16796f905325SMatthew G. Knepley 16806f905325SMatthew G. Knepley @*/ 1681*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetSymmetries(PetscDualSpace sp, const PetscInt ****perms, const PetscScalar ****flips) 1682*d71ae5a4SJacob Faibussowitsch { 16836f905325SMatthew G. Knepley PetscFunctionBegin; 16846f905325SMatthew G. Knepley PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 16859371c9d4SSatish Balay if (perms) { 16869371c9d4SSatish Balay PetscValidPointer(perms, 2); 16879371c9d4SSatish Balay *perms = NULL; 16889371c9d4SSatish Balay } 16899371c9d4SSatish Balay if (flips) { 16909371c9d4SSatish Balay PetscValidPointer(flips, 3); 16919371c9d4SSatish Balay *flips = NULL; 16929371c9d4SSatish Balay } 16939566063dSJacob Faibussowitsch if (sp->ops->getsymmetries) PetscCall((sp->ops->getsymmetries)(sp, perms, flips)); 16946f905325SMatthew G. Knepley PetscFunctionReturn(0); 16956f905325SMatthew G. Knepley } 16964bee2e38SMatthew G. Knepley 16974bee2e38SMatthew G. Knepley /*@ 1698b4457527SToby Isaac PetscDualSpaceGetFormDegree - Get the form degree k for the k-form the describes the pushforwards/pullbacks of this 1699b4457527SToby Isaac dual space's functionals. 1700b4457527SToby Isaac 1701b4457527SToby Isaac Input Parameter: 1702b4457527SToby Isaac . dsp - The PetscDualSpace 1703b4457527SToby Isaac 1704b4457527SToby Isaac Output Parameter: 1705b4457527SToby 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 1706b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1707b4457527SToby 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). 1708b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1709b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1710b4457527SToby Isaac but are stored as 1-forms. 1711b4457527SToby Isaac 1712b4457527SToby Isaac Level: developer 1713b4457527SToby Isaac 1714db781477SPatrick Sanan .seealso: `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 1715b4457527SToby Isaac @*/ 1716*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetFormDegree(PetscDualSpace dsp, PetscInt *k) 1717*d71ae5a4SJacob Faibussowitsch { 1718b4457527SToby Isaac PetscFunctionBeginHot; 1719b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1720dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1721b4457527SToby Isaac *k = dsp->k; 1722b4457527SToby Isaac PetscFunctionReturn(0); 1723b4457527SToby Isaac } 1724b4457527SToby Isaac 1725b4457527SToby Isaac /*@ 1726b4457527SToby Isaac PetscDualSpaceSetFormDegree - Set the form degree k for the k-form the describes the pushforwards/pullbacks of this 1727b4457527SToby Isaac dual space's functionals. 1728b4457527SToby Isaac 1729d8d19677SJose E. Roman Input Parameters: 1730b4457527SToby Isaac + dsp - The PetscDualSpace 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 @*/ 1742*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetFormDegree(PetscDualSpace dsp, PetscInt k) 1743*d71ae5a4SJacob Faibussowitsch { 1744b4457527SToby Isaac PetscInt dim; 1745b4457527SToby Isaac 1746b4457527SToby Isaac PetscFunctionBeginHot; 1747b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 174828b400f6SJacob Faibussowitsch PetscCheck(!dsp->setupcalled, PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 1749b4457527SToby Isaac dim = dsp->dm->dim; 17501dca8a05SBarry 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); 1751b4457527SToby Isaac dsp->k = k; 1752b4457527SToby Isaac PetscFunctionReturn(0); 1753b4457527SToby Isaac } 1754b4457527SToby Isaac 1755b4457527SToby Isaac /*@ 17564bee2e38SMatthew G. Knepley PetscDualSpaceGetDeRahm - Get the k-simplex associated with the functionals in this dual space 17574bee2e38SMatthew G. Knepley 17584bee2e38SMatthew G. Knepley Input Parameter: 17594bee2e38SMatthew G. Knepley . dsp - The PetscDualSpace 17604bee2e38SMatthew G. Knepley 17614bee2e38SMatthew G. Knepley Output Parameter: 17624bee2e38SMatthew G. Knepley . k - The simplex dimension 17634bee2e38SMatthew G. Knepley 1764a4ce7ad1SMatthew G. Knepley Level: developer 17654bee2e38SMatthew G. Knepley 17664bee2e38SMatthew G. Knepley Note: Currently supported values are 17674bee2e38SMatthew G. Knepley $ 0: These are H_1 methods that only transform coordinates 17684bee2e38SMatthew G. Knepley $ 1: These are Hcurl methods that transform functions using the covariant Piola transform (COVARIANT_PIOLA_TRANSFORM) 17694bee2e38SMatthew G. Knepley $ 2: These are the same as 1 17704bee2e38SMatthew G. Knepley $ 3: These are Hdiv methods that transform functions using the contravariant Piola transform (CONTRAVARIANT_PIOLA_TRANSFORM) 17714bee2e38SMatthew G. Knepley 1772db781477SPatrick Sanan .seealso: `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 17734bee2e38SMatthew G. Knepley @*/ 1774*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDeRahm(PetscDualSpace dsp, PetscInt *k) 1775*d71ae5a4SJacob Faibussowitsch { 1776b4457527SToby Isaac PetscInt dim; 1777b4457527SToby Isaac 17784bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 17794bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1780dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1781b4457527SToby Isaac dim = dsp->dm->dim; 1782b4457527SToby Isaac if (!dsp->k) *k = IDENTITY_TRANSFORM; 1783b4457527SToby Isaac else if (dsp->k == 1) *k = COVARIANT_PIOLA_TRANSFORM; 1784b4457527SToby Isaac else if (dsp->k == -(dim - 1)) *k = CONTRAVARIANT_PIOLA_TRANSFORM; 1785b4457527SToby Isaac else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unsupported transformation"); 17864bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 17874bee2e38SMatthew G. Knepley } 17884bee2e38SMatthew G. Knepley 17894bee2e38SMatthew G. Knepley /*@C 17904bee2e38SMatthew G. Knepley PetscDualSpaceTransform - Transform the function values 17914bee2e38SMatthew G. Knepley 17924bee2e38SMatthew G. Knepley Input Parameters: 17934bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 17944bee2e38SMatthew G. Knepley . trans - The type of transform 17954bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 17964bee2e38SMatthew G. Knepley . fegeom - The cell geometry 17974bee2e38SMatthew G. Knepley . Nv - The number of function samples 17984bee2e38SMatthew G. Knepley . Nc - The number of function components 17994bee2e38SMatthew G. Knepley - vals - The function values 18004bee2e38SMatthew G. Knepley 18014bee2e38SMatthew G. Knepley Output Parameter: 18024bee2e38SMatthew G. Knepley . vals - The transformed function values 18034bee2e38SMatthew G. Knepley 1804a4ce7ad1SMatthew G. Knepley Level: intermediate 18054bee2e38SMatthew G. Knepley 1806f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18072edcad52SToby Isaac 1808db781477SPatrick Sanan .seealso: `PetscDualSpaceTransformGradient()`, `PetscDualSpaceTransformHessian()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 18094bee2e38SMatthew G. Knepley @*/ 1810*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransform(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 1811*d71ae5a4SJacob Faibussowitsch { 1812b4457527SToby Isaac PetscReal Jstar[9] = {0}; 1813b4457527SToby Isaac PetscInt dim, v, c, Nk; 18144bee2e38SMatthew G. Knepley 18154bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18164bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18174bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1818dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 1819b4457527SToby Isaac /* TODO: not handling dimEmbed != dim right now */ 18202ae266adSMatthew G. Knepley dim = dsp->dm->dim; 1821b4457527SToby Isaac /* No change needed for 0-forms */ 1822b4457527SToby Isaac if (!dsp->k) PetscFunctionReturn(0); 18239566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(dsp->k), &Nk)); 1824b4457527SToby Isaac /* TODO: use fegeom->isAffine */ 18259566063dSJacob Faibussowitsch PetscCall(PetscDTAltVPullbackMatrix(dim, dim, isInverse ? fegeom->J : fegeom->invJ, dsp->k, Jstar)); 18264bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1827b4457527SToby Isaac switch (Nk) { 1828b4457527SToby Isaac case 1: 1829b4457527SToby Isaac for (c = 0; c < Nc; c++) vals[v * Nc + c] *= Jstar[0]; 18304bee2e38SMatthew G. Knepley break; 1831b4457527SToby Isaac case 2: 1832b4457527SToby Isaac for (c = 0; c < Nc; c += 2) DMPlex_Mult2DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]); 18334bee2e38SMatthew G. Knepley break; 1834b4457527SToby Isaac case 3: 1835b4457527SToby Isaac for (c = 0; c < Nc; c += 3) DMPlex_Mult3DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]); 1836b4457527SToby Isaac break; 1837*d71ae5a4SJacob Faibussowitsch default: 1838*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported form size %" PetscInt_FMT " for transformation", Nk); 1839b4457527SToby Isaac } 18404bee2e38SMatthew G. Knepley } 18414bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 18424bee2e38SMatthew G. Knepley } 1843b4457527SToby Isaac 18444bee2e38SMatthew G. Knepley /*@C 18454bee2e38SMatthew G. Knepley PetscDualSpaceTransformGradient - Transform the function gradient values 18464bee2e38SMatthew G. Knepley 18474bee2e38SMatthew G. Knepley Input Parameters: 18484bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 18494bee2e38SMatthew G. Knepley . trans - The type of transform 18504bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18514bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18524bee2e38SMatthew G. Knepley . Nv - The number of function gradient samples 18534bee2e38SMatthew G. Knepley . Nc - The number of function components 18544bee2e38SMatthew G. Knepley - vals - The function gradient values 18554bee2e38SMatthew G. Knepley 18564bee2e38SMatthew G. Knepley Output Parameter: 1857f9244615SMatthew G. Knepley . vals - The transformed function gradient values 18584bee2e38SMatthew G. Knepley 1859a4ce7ad1SMatthew G. Knepley Level: intermediate 18604bee2e38SMatthew G. Knepley 1861f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18622edcad52SToby Isaac 1863db781477SPatrick Sanan .seealso: `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 18644bee2e38SMatthew G. Knepley @*/ 1865*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransformGradient(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 1866*d71ae5a4SJacob Faibussowitsch { 186727f02ce8SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 186827f02ce8SMatthew G. Knepley PetscInt v, c, d; 18694bee2e38SMatthew G. Knepley 18704bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18714bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18724bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1873dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 187427f02ce8SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 187563a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 187627f02ce8SMatthew G. Knepley #endif 18774bee2e38SMatthew G. Knepley /* Transform gradient */ 187827f02ce8SMatthew G. Knepley if (dim == dE) { 18794bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 18804bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 18819371c9d4SSatish Balay switch (dim) { 1882*d71ae5a4SJacob Faibussowitsch case 1: 1883*d71ae5a4SJacob Faibussowitsch vals[(v * Nc + c) * dim] *= fegeom->invJ[0]; 1884*d71ae5a4SJacob Faibussowitsch break; 1885*d71ae5a4SJacob Faibussowitsch case 2: 1886*d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]); 1887*d71ae5a4SJacob Faibussowitsch break; 1888*d71ae5a4SJacob Faibussowitsch case 3: 1889*d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]); 1890*d71ae5a4SJacob Faibussowitsch break; 1891*d71ae5a4SJacob Faibussowitsch default: 1892*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 18934bee2e38SMatthew G. Knepley } 18944bee2e38SMatthew G. Knepley } 18954bee2e38SMatthew G. Knepley } 189627f02ce8SMatthew G. Knepley } else { 189727f02ce8SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1898ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) DMPlex_MultTransposeReal_Internal(fegeom->invJ, dim, dE, 1, &vals[(v * Nc + c) * dE], &vals[(v * Nc + c) * dE]); 189927f02ce8SMatthew G. Knepley } 190027f02ce8SMatthew G. Knepley } 19014bee2e38SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 19024bee2e38SMatthew G. Knepley if (Nc == 1 || Nc != dim) PetscFunctionReturn(0); 19034bee2e38SMatthew G. Knepley switch (trans) { 1904*d71ae5a4SJacob Faibussowitsch case IDENTITY_TRANSFORM: 1905*d71ae5a4SJacob Faibussowitsch break; 19064bee2e38SMatthew G. Knepley case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 19074bee2e38SMatthew G. Knepley if (isInverse) { 19084bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19094bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19109371c9d4SSatish Balay switch (dim) { 1911*d71ae5a4SJacob Faibussowitsch case 2: 1912*d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1913*d71ae5a4SJacob Faibussowitsch break; 1914*d71ae5a4SJacob Faibussowitsch case 3: 1915*d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1916*d71ae5a4SJacob Faibussowitsch break; 1917*d71ae5a4SJacob Faibussowitsch default: 1918*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19194bee2e38SMatthew G. Knepley } 19204bee2e38SMatthew G. Knepley } 19214bee2e38SMatthew G. Knepley } 19224bee2e38SMatthew G. Knepley } else { 19234bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19244bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19259371c9d4SSatish Balay switch (dim) { 1926*d71ae5a4SJacob Faibussowitsch case 2: 1927*d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1928*d71ae5a4SJacob Faibussowitsch break; 1929*d71ae5a4SJacob Faibussowitsch case 3: 1930*d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1931*d71ae5a4SJacob Faibussowitsch break; 1932*d71ae5a4SJacob Faibussowitsch default: 1933*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19344bee2e38SMatthew G. Knepley } 19354bee2e38SMatthew G. Knepley } 19364bee2e38SMatthew G. Knepley } 19374bee2e38SMatthew G. Knepley } 19384bee2e38SMatthew G. Knepley break; 19394bee2e38SMatthew G. Knepley case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 19404bee2e38SMatthew G. Knepley if (isInverse) { 19414bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19424bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19439371c9d4SSatish Balay switch (dim) { 1944*d71ae5a4SJacob Faibussowitsch case 2: 1945*d71ae5a4SJacob Faibussowitsch DMPlex_Mult2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1946*d71ae5a4SJacob Faibussowitsch break; 1947*d71ae5a4SJacob Faibussowitsch case 3: 1948*d71ae5a4SJacob Faibussowitsch DMPlex_Mult3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1949*d71ae5a4SJacob Faibussowitsch break; 1950*d71ae5a4SJacob Faibussowitsch default: 1951*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19524bee2e38SMatthew G. Knepley } 19534bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] *= fegeom->detJ[0]; 19544bee2e38SMatthew G. Knepley } 19554bee2e38SMatthew G. Knepley } 19564bee2e38SMatthew G. Knepley } else { 19574bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19584bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19599371c9d4SSatish Balay switch (dim) { 1960*d71ae5a4SJacob Faibussowitsch case 2: 1961*d71ae5a4SJacob Faibussowitsch DMPlex_Mult2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1962*d71ae5a4SJacob Faibussowitsch break; 1963*d71ae5a4SJacob Faibussowitsch case 3: 1964*d71ae5a4SJacob Faibussowitsch DMPlex_Mult3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1965*d71ae5a4SJacob Faibussowitsch break; 1966*d71ae5a4SJacob Faibussowitsch default: 1967*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19684bee2e38SMatthew G. Knepley } 19694bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] /= fegeom->detJ[0]; 19704bee2e38SMatthew G. Knepley } 19714bee2e38SMatthew G. Knepley } 19724bee2e38SMatthew G. Knepley } 19734bee2e38SMatthew G. Knepley break; 19744bee2e38SMatthew G. Knepley } 19754bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 19764bee2e38SMatthew G. Knepley } 19774bee2e38SMatthew G. Knepley 19784bee2e38SMatthew G. Knepley /*@C 1979f9244615SMatthew G. Knepley PetscDualSpaceTransformHessian - Transform the function Hessian values 1980f9244615SMatthew G. Knepley 1981f9244615SMatthew G. Knepley Input Parameters: 1982f9244615SMatthew G. Knepley + dsp - The PetscDualSpace 1983f9244615SMatthew G. Knepley . trans - The type of transform 1984f9244615SMatthew G. Knepley . isInverse - Flag to invert the transform 1985f9244615SMatthew G. Knepley . fegeom - The cell geometry 1986f9244615SMatthew G. Knepley . Nv - The number of function Hessian samples 1987f9244615SMatthew G. Knepley . Nc - The number of function components 1988f9244615SMatthew G. Knepley - vals - The function gradient values 1989f9244615SMatthew G. Knepley 1990f9244615SMatthew G. Knepley Output Parameter: 1991f9244615SMatthew G. Knepley . vals - The transformed function Hessian values 1992f9244615SMatthew G. Knepley 1993f9244615SMatthew G. Knepley Level: intermediate 1994f9244615SMatthew G. Knepley 1995f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 1996f9244615SMatthew G. Knepley 1997db781477SPatrick Sanan .seealso: `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 1998f9244615SMatthew G. Knepley @*/ 1999*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransformHessian(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 2000*d71ae5a4SJacob Faibussowitsch { 2001f9244615SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 2002f9244615SMatthew G. Knepley PetscInt v, c; 2003f9244615SMatthew G. Knepley 2004f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2005f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2006f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 4); 2007dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 2008f9244615SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 200963a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 2010f9244615SMatthew G. Knepley #endif 2011f9244615SMatthew G. Knepley /* Transform Hessian: J^{-T}_{ik} J^{-T}_{jl} H(f)_{kl} = J^{-T}_{ik} H(f)_{kl} J^{-1}_{lj} */ 2012f9244615SMatthew G. Knepley if (dim == dE) { 2013f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2014f9244615SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 20159371c9d4SSatish Balay switch (dim) { 2016*d71ae5a4SJacob Faibussowitsch case 1: 2017*d71ae5a4SJacob Faibussowitsch vals[(v * Nc + c) * dim * dim] *= PetscSqr(fegeom->invJ[0]); 2018*d71ae5a4SJacob Faibussowitsch break; 2019*d71ae5a4SJacob Faibussowitsch case 2: 2020*d71ae5a4SJacob Faibussowitsch DMPlex_PTAP2DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]); 2021*d71ae5a4SJacob Faibussowitsch break; 2022*d71ae5a4SJacob Faibussowitsch case 3: 2023*d71ae5a4SJacob Faibussowitsch DMPlex_PTAP3DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]); 2024*d71ae5a4SJacob Faibussowitsch break; 2025*d71ae5a4SJacob Faibussowitsch default: 2026*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 2027f9244615SMatthew G. Knepley } 2028f9244615SMatthew G. Knepley } 2029f9244615SMatthew G. Knepley } 2030f9244615SMatthew G. Knepley } else { 2031f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2032ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) DMPlex_PTAPReal_Internal(fegeom->invJ, dim, dE, &vals[(v * Nc + c) * dE * dE], &vals[(v * Nc + c) * dE * dE]); 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) { 2038*d71ae5a4SJacob Faibussowitsch case IDENTITY_TRANSFORM: 2039*d71ae5a4SJacob Faibussowitsch break; 2040*d71ae5a4SJacob Faibussowitsch case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 2041*d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2042*d71ae5a4SJacob Faibussowitsch case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 2043*d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2044f9244615SMatthew G. Knepley } 2045f9244615SMatthew G. Knepley PetscFunctionReturn(0); 2046f9244615SMatthew G. Knepley } 2047f9244615SMatthew G. Knepley 2048f9244615SMatthew G. Knepley /*@C 20494bee2e38SMatthew 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. 20504bee2e38SMatthew G. Knepley 20514bee2e38SMatthew G. Knepley Input Parameters: 20524bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 20534bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 20544bee2e38SMatthew G. Knepley . Nq - The number of function samples 20554bee2e38SMatthew G. Knepley . Nc - The number of function components 20564bee2e38SMatthew G. Knepley - pointEval - The function values 20574bee2e38SMatthew G. Knepley 20584bee2e38SMatthew G. Knepley Output Parameter: 20594bee2e38SMatthew G. Knepley . pointEval - The transformed function values 20604bee2e38SMatthew G. Knepley 20614bee2e38SMatthew G. Knepley Level: advanced 20624bee2e38SMatthew G. Knepley 20634bee2e38SMatthew 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. 20644bee2e38SMatthew G. Knepley 20652edcad52SToby Isaac Note: This only handles tranformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 20662edcad52SToby Isaac 2067db781477SPatrick Sanan .seealso: `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 20684bee2e38SMatthew G. Knepley @*/ 2069*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePullback(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2070*d71ae5a4SJacob Faibussowitsch { 20714bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2072b4457527SToby Isaac PetscInt k; 20734bee2e38SMatthew G. Knepley 20744bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 20754bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 20764bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2077dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 20784bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 20794bee2e38SMatthew G. Knepley This determines their transformation properties. */ 20809566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 20819371c9d4SSatish Balay switch (k) { 2082*d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2083*d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2084*d71ae5a4SJacob Faibussowitsch break; 2085*d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2086*d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2087*d71ae5a4SJacob Faibussowitsch break; 2088b4457527SToby Isaac case 2: 2089*d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2090*d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2091*d71ae5a4SJacob Faibussowitsch break; 2092*d71ae5a4SJacob Faibussowitsch default: 2093*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 20944bee2e38SMatthew G. Knepley } 20959566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_TRUE, fegeom, Nq, Nc, pointEval)); 20964bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 20974bee2e38SMatthew G. Knepley } 20984bee2e38SMatthew G. Knepley 20994bee2e38SMatthew G. Knepley /*@C 21004bee2e38SMatthew 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. 21014bee2e38SMatthew G. Knepley 21024bee2e38SMatthew G. Knepley Input Parameters: 21034bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 21044bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21054bee2e38SMatthew G. Knepley . Nq - The number of function samples 21064bee2e38SMatthew G. Knepley . Nc - The number of function components 21074bee2e38SMatthew G. Knepley - pointEval - The function values 21084bee2e38SMatthew G. Knepley 21094bee2e38SMatthew G. Knepley Output Parameter: 21104bee2e38SMatthew G. Knepley . pointEval - The transformed function values 21114bee2e38SMatthew G. Knepley 21124bee2e38SMatthew G. Knepley Level: advanced 21134bee2e38SMatthew G. Knepley 21144bee2e38SMatthew 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. 21154bee2e38SMatthew G. Knepley 2116f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21172edcad52SToby Isaac 2118db781477SPatrick Sanan .seealso: `PetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 21194bee2e38SMatthew G. Knepley @*/ 2120*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforward(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2121*d71ae5a4SJacob Faibussowitsch { 21224bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2123b4457527SToby Isaac PetscInt k; 21244bee2e38SMatthew G. Knepley 21254bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21264bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 21274bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2128dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 21294bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 21304bee2e38SMatthew G. Knepley This determines their transformation properties. */ 21319566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 21329371c9d4SSatish Balay switch (k) { 2133*d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2134*d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2135*d71ae5a4SJacob Faibussowitsch break; 2136*d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2137*d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2138*d71ae5a4SJacob Faibussowitsch break; 2139b4457527SToby Isaac case 2: 2140*d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2141*d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2142*d71ae5a4SJacob Faibussowitsch break; 2143*d71ae5a4SJacob Faibussowitsch default: 2144*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 21454bee2e38SMatthew G. Knepley } 21469566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 21474bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 21484bee2e38SMatthew G. Knepley } 21494bee2e38SMatthew G. Knepley 21504bee2e38SMatthew G. Knepley /*@C 21514bee2e38SMatthew 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. 21524bee2e38SMatthew G. Knepley 21534bee2e38SMatthew G. Knepley Input Parameters: 21544bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 21554bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21564bee2e38SMatthew G. Knepley . Nq - The number of function gradient samples 21574bee2e38SMatthew G. Knepley . Nc - The number of function components 21584bee2e38SMatthew G. Knepley - pointEval - The function gradient values 21594bee2e38SMatthew G. Knepley 21604bee2e38SMatthew G. Knepley Output Parameter: 21614bee2e38SMatthew G. Knepley . pointEval - The transformed function gradient values 21624bee2e38SMatthew G. Knepley 21634bee2e38SMatthew G. Knepley Level: advanced 21644bee2e38SMatthew G. Knepley 21654bee2e38SMatthew 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. 21664bee2e38SMatthew G. Knepley 2167f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21682edcad52SToby Isaac 2169db781477SPatrick Sanan .seealso: `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2170dc0529c6SBarry Smith @*/ 2171*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforwardGradient(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2172*d71ae5a4SJacob Faibussowitsch { 21734bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2174b4457527SToby Isaac PetscInt k; 21754bee2e38SMatthew G. Knepley 21764bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21774bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 21784bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2179dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 21804bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 21814bee2e38SMatthew G. Knepley This determines their transformation properties. */ 21829566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 21839371c9d4SSatish Balay switch (k) { 2184*d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2185*d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2186*d71ae5a4SJacob Faibussowitsch break; 2187*d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2188*d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2189*d71ae5a4SJacob Faibussowitsch break; 2190b4457527SToby Isaac case 2: 2191*d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2192*d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2193*d71ae5a4SJacob Faibussowitsch break; 2194*d71ae5a4SJacob Faibussowitsch default: 2195*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 21964bee2e38SMatthew G. Knepley } 21979566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformGradient(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 21984bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 21994bee2e38SMatthew G. Knepley } 2200f9244615SMatthew G. Knepley 2201f9244615SMatthew G. Knepley /*@C 2202f9244615SMatthew 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. 2203f9244615SMatthew G. Knepley 2204f9244615SMatthew G. Knepley Input Parameters: 2205f9244615SMatthew G. Knepley + dsp - The PetscDualSpace 2206f9244615SMatthew G. Knepley . fegeom - The geometry for this cell 2207f9244615SMatthew G. Knepley . Nq - The number of function Hessian samples 2208f9244615SMatthew G. Knepley . Nc - The number of function components 2209f9244615SMatthew G. Knepley - pointEval - The function gradient values 2210f9244615SMatthew G. Knepley 2211f9244615SMatthew G. Knepley Output Parameter: 2212f9244615SMatthew G. Knepley . pointEval - The transformed function Hessian values 2213f9244615SMatthew G. Knepley 2214f9244615SMatthew G. Knepley Level: advanced 2215f9244615SMatthew G. Knepley 2216f9244615SMatthew 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. 2217f9244615SMatthew G. Knepley 2218f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2219f9244615SMatthew G. Knepley 2220db781477SPatrick Sanan .seealso: `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2221f9244615SMatthew G. Knepley @*/ 2222*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforwardHessian(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2223*d71ae5a4SJacob Faibussowitsch { 2224f9244615SMatthew G. Knepley PetscDualSpaceTransformType trans; 2225f9244615SMatthew G. Knepley PetscInt k; 2226f9244615SMatthew G. Knepley 2227f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2228f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2229f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2230dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 2231f9244615SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 2232f9244615SMatthew G. Knepley This determines their transformation properties. */ 22339566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 22349371c9d4SSatish Balay switch (k) { 2235*d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2236*d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2237*d71ae5a4SJacob Faibussowitsch break; 2238*d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2239*d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2240*d71ae5a4SJacob Faibussowitsch break; 2241f9244615SMatthew G. Knepley case 2: 2242*d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2243*d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2244*d71ae5a4SJacob Faibussowitsch break; 2245*d71ae5a4SJacob Faibussowitsch default: 2246*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 2247f9244615SMatthew G. Knepley } 22489566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformHessian(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 2249f9244615SMatthew G. Knepley PetscFunctionReturn(0); 2250f9244615SMatthew G. Knepley } 2251