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 26*dce8aebaSBarry Smith .seealso: `PetscDualSpaceType`, `PetscDualSpaceTensorPointLexicographic_Internal()` 276f905325SMatthew G. Knepley */ 28d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceLatticePointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) 29d71ae5a4SJacob Faibussowitsch { 306f905325SMatthew G. Knepley PetscFunctionBegin; 316f905325SMatthew G. Knepley while (len--) { 326f905325SMatthew G. Knepley max -= tup[len]; 336f905325SMatthew G. Knepley if (!max) { 346f905325SMatthew G. Knepley tup[len] = 0; 356f905325SMatthew G. Knepley break; 366f905325SMatthew G. Knepley } 376f905325SMatthew G. Knepley } 386f905325SMatthew G. Knepley tup[++len]++; 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 57*dce8aebaSBarry Smith .seealso: `PetscDualSpaceType`, `PetscDualSpaceLatticePointLexicographic_Internal()` 586f905325SMatthew G. Knepley */ 59d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTensorPointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) 60d71ae5a4SJacob Faibussowitsch { 616f905325SMatthew G. Knepley PetscInt i; 626f905325SMatthew G. Knepley 636f905325SMatthew G. Knepley PetscFunctionBegin; 646f905325SMatthew G. Knepley for (i = 0; i < len; i++) { 656f905325SMatthew G. Knepley if (tup[i] < max) { 666f905325SMatthew G. Knepley break; 676f905325SMatthew G. Knepley } else { 686f905325SMatthew G. Knepley tup[i] = 0; 696f905325SMatthew G. Knepley } 706f905325SMatthew G. Knepley } 716f905325SMatthew G. Knepley tup[i]++; 726f905325SMatthew G. Knepley PetscFunctionReturn(0); 736f905325SMatthew G. Knepley } 746f905325SMatthew G. Knepley 7520cf1dd8SToby Isaac /*@C 76*dce8aebaSBarry Smith PetscDualSpaceRegister - Adds a new `PetscDualSpaceType` 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 Sample usage: 8520cf1dd8SToby Isaac .vb 8620cf1dd8SToby Isaac PetscDualSpaceRegister("my_space", MyPetscDualSpaceCreate); 8720cf1dd8SToby Isaac .ve 8820cf1dd8SToby Isaac 8920cf1dd8SToby Isaac Then, your PetscDualSpace type can be chosen with the procedural interface via 9020cf1dd8SToby Isaac .vb 9120cf1dd8SToby Isaac PetscDualSpaceCreate(MPI_Comm, PetscDualSpace *); 9220cf1dd8SToby Isaac PetscDualSpaceSetType(PetscDualSpace, "my_dual_space"); 9320cf1dd8SToby Isaac .ve 9420cf1dd8SToby Isaac or at runtime via the option 9520cf1dd8SToby Isaac .vb 9620cf1dd8SToby Isaac -petscdualspace_type my_dual_space 9720cf1dd8SToby Isaac .ve 9820cf1dd8SToby Isaac 9920cf1dd8SToby Isaac Level: advanced 10020cf1dd8SToby Isaac 101*dce8aebaSBarry Smith Note: 102*dce8aebaSBarry Smith `PetscDualSpaceRegister()` may be called multiple times to add several user-defined `PetscDualSpace` 10320cf1dd8SToby Isaac 104*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceType`, `PetscDualSpaceRegisterAll()`, `PetscDualSpaceRegisterDestroy()` 10520cf1dd8SToby Isaac @*/ 106d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceRegister(const char sname[], PetscErrorCode (*function)(PetscDualSpace)) 107d71ae5a4SJacob Faibussowitsch { 10820cf1dd8SToby Isaac PetscFunctionBegin; 1099566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&PetscDualSpaceList, sname, function)); 11020cf1dd8SToby Isaac PetscFunctionReturn(0); 11120cf1dd8SToby Isaac } 11220cf1dd8SToby Isaac 11320cf1dd8SToby Isaac /*@C 114*dce8aebaSBarry Smith PetscDualSpaceSetType - Builds a particular `PetscDualSpace` based on its `PetscDualSpaceType` 11520cf1dd8SToby Isaac 116d083f849SBarry Smith Collective on sp 11720cf1dd8SToby Isaac 11820cf1dd8SToby Isaac Input Parameters: 119*dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 12020cf1dd8SToby Isaac - name - The kind of space 12120cf1dd8SToby Isaac 12220cf1dd8SToby Isaac Options Database Key: 12320cf1dd8SToby Isaac . -petscdualspace_type <type> - Sets the PetscDualSpace type; use -help for a list of available types 12420cf1dd8SToby Isaac 12520cf1dd8SToby Isaac Level: intermediate 12620cf1dd8SToby Isaac 127*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceType`, `PetscDualSpaceGetType()`, `PetscDualSpaceCreate()` 12820cf1dd8SToby Isaac @*/ 129d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetType(PetscDualSpace sp, PetscDualSpaceType name) 130d71ae5a4SJacob Faibussowitsch { 13120cf1dd8SToby Isaac PetscErrorCode (*r)(PetscDualSpace); 13220cf1dd8SToby Isaac PetscBool match; 13320cf1dd8SToby Isaac 13420cf1dd8SToby Isaac PetscFunctionBegin; 13520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)sp, name, &match)); 13720cf1dd8SToby Isaac if (match) PetscFunctionReturn(0); 13820cf1dd8SToby Isaac 1399566063dSJacob Faibussowitsch if (!PetscDualSpaceRegisterAllCalled) PetscCall(PetscDualSpaceRegisterAll()); 1409566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(PetscDualSpaceList, name, &r)); 14128b400f6SJacob Faibussowitsch PetscCheck(r, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDualSpace type: %s", name); 14220cf1dd8SToby Isaac 143dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, destroy); 14420cf1dd8SToby Isaac sp->ops->destroy = NULL; 145dbbe0bcdSBarry Smith 1469566063dSJacob Faibussowitsch PetscCall((*r)(sp)); 1479566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)sp, name)); 14820cf1dd8SToby Isaac PetscFunctionReturn(0); 14920cf1dd8SToby Isaac } 15020cf1dd8SToby Isaac 15120cf1dd8SToby Isaac /*@C 152*dce8aebaSBarry Smith PetscDualSpaceGetType - Gets the `PetscDualSpaceType` name (as a string) from the object. 15320cf1dd8SToby Isaac 15420cf1dd8SToby Isaac Not Collective 15520cf1dd8SToby Isaac 15620cf1dd8SToby Isaac Input Parameter: 157*dce8aebaSBarry Smith . sp - The `PetscDualSpace` 15820cf1dd8SToby Isaac 15920cf1dd8SToby Isaac Output Parameter: 160*dce8aebaSBarry Smith . name - The `PetscDualSpaceType` name 16120cf1dd8SToby Isaac 16220cf1dd8SToby Isaac Level: intermediate 16320cf1dd8SToby Isaac 164*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceType`, `PetscDualSpaceSetType()`, `PetscDualSpaceCreate()` 16520cf1dd8SToby Isaac @*/ 166d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetType(PetscDualSpace sp, PetscDualSpaceType *name) 167d71ae5a4SJacob Faibussowitsch { 16820cf1dd8SToby Isaac PetscFunctionBegin; 16920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 17020cf1dd8SToby Isaac PetscValidPointer(name, 2); 17148a46eb9SPierre Jolivet if (!PetscDualSpaceRegisterAllCalled) PetscCall(PetscDualSpaceRegisterAll()); 17220cf1dd8SToby Isaac *name = ((PetscObject)sp)->type_name; 17320cf1dd8SToby Isaac PetscFunctionReturn(0); 17420cf1dd8SToby Isaac } 17520cf1dd8SToby Isaac 176d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDualSpaceView_ASCII(PetscDualSpace sp, PetscViewer v) 177d71ae5a4SJacob Faibussowitsch { 178221d6281SMatthew G. Knepley PetscViewerFormat format; 179221d6281SMatthew G. Knepley PetscInt pdim, f; 180221d6281SMatthew G. Knepley 181221d6281SMatthew G. Knepley PetscFunctionBegin; 1829566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &pdim)); 1839566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)sp, v)); 1849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 185b4457527SToby Isaac if (sp->k) { 18663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual space for %" PetscInt_FMT "-forms %swith %" PetscInt_FMT " components, size %" PetscInt_FMT "\n", PetscAbsInt(sp->k), sp->k < 0 ? "(stored in dual form) " : "", sp->Nc, pdim)); 187b4457527SToby Isaac } else { 18863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual space with %" PetscInt_FMT " components, size %" PetscInt_FMT "\n", sp->Nc, pdim)); 189b4457527SToby Isaac } 190dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, view, v); 1919566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(v, &format)); 192221d6281SMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 194221d6281SMatthew G. Knepley for (f = 0; f < pdim; ++f) { 19563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Dual basis vector %" PetscInt_FMT "\n", f)); 1969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 1979566063dSJacob Faibussowitsch PetscCall(PetscQuadratureView(sp->functional[f], v)); 1989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 199221d6281SMatthew G. Knepley } 2009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 201221d6281SMatthew G. Knepley } 2029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 203221d6281SMatthew G. Knepley PetscFunctionReturn(0); 204221d6281SMatthew G. Knepley } 205221d6281SMatthew G. Knepley 206fe2efc57SMark /*@C 207*dce8aebaSBarry Smith PetscDualSpaceViewFromOptions - View a `PetscDualSpace` based on values in the options database 208fe2efc57SMark 209*dce8aebaSBarry Smith Collective on A 210fe2efc57SMark 211fe2efc57SMark Input Parameters: 212*dce8aebaSBarry Smith + A - the `PetscDualSpace` object 213*dce8aebaSBarry Smith . obj - Optional object, provides the options prefix 214*dce8aebaSBarry Smith - name - command line option name 215fe2efc57SMark 216fe2efc57SMark Level: intermediate 217*dce8aebaSBarry Smith 218db781477SPatrick Sanan .seealso: `PetscDualSpace`, `PetscDualSpaceView()`, `PetscObjectViewFromOptions()`, `PetscDualSpaceCreate()` 219fe2efc57SMark @*/ 220d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceViewFromOptions(PetscDualSpace A, PetscObject obj, const char name[]) 221d71ae5a4SJacob Faibussowitsch { 222fe2efc57SMark PetscFunctionBegin; 223fe2efc57SMark PetscValidHeaderSpecific(A, PETSCDUALSPACE_CLASSID, 1); 2249566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 225fe2efc57SMark PetscFunctionReturn(0); 226fe2efc57SMark } 227fe2efc57SMark 22820cf1dd8SToby Isaac /*@ 229*dce8aebaSBarry Smith PetscDualSpaceView - Views a `PetscDualSpace` 23020cf1dd8SToby Isaac 231d083f849SBarry Smith Collective on sp 23220cf1dd8SToby Isaac 233d8d19677SJose E. Roman Input Parameters: 234*dce8aebaSBarry Smith + sp - the `PetscDualSpace` object to view 23520cf1dd8SToby Isaac - v - the viewer 23620cf1dd8SToby Isaac 237a4ce7ad1SMatthew G. Knepley Level: beginner 23820cf1dd8SToby Isaac 239*dce8aebaSBarry Smith .seealso: `PetscViewer`, `PetscDualSpaceDestroy()`, `PetscDualSpace` 24020cf1dd8SToby Isaac @*/ 241d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceView(PetscDualSpace sp, PetscViewer v) 242d71ae5a4SJacob 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 /*@ 255*dce8aebaSBarry Smith PetscDualSpaceSetFromOptions - sets parameters in a `PetscDualSpace` from the options database 25620cf1dd8SToby Isaac 257d083f849SBarry Smith Collective on sp 25820cf1dd8SToby Isaac 25920cf1dd8SToby Isaac Input Parameter: 260*dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to set options for 26120cf1dd8SToby Isaac 262*dce8aebaSBarry Smith Options Database Keys: 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 270*dce8aebaSBarry Smith .seealso: `PetscDualSpaceView()`, `PetscDualSpace`, `PetscObjectSetFromOptions()` 27120cf1dd8SToby Isaac @*/ 272d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetFromOptions(PetscDualSpace sp) 273d71ae5a4SJacob 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 /*@ 316*dce8aebaSBarry Smith PetscDualSpaceSetUp - Construct a basis for a `PetscDualSpace` 31720cf1dd8SToby Isaac 318d083f849SBarry Smith Collective on sp 31920cf1dd8SToby Isaac 32020cf1dd8SToby Isaac Input Parameter: 321*dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to setup 32220cf1dd8SToby Isaac 323a4ce7ad1SMatthew G. Knepley Level: intermediate 32420cf1dd8SToby Isaac 325*dce8aebaSBarry Smith .seealso: `PetscDualSpaceView()`, `PetscDualSpaceDestroy()`, `PetscDualSpace` 32620cf1dd8SToby Isaac @*/ 327d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetUp(PetscDualSpace sp) 328d71ae5a4SJacob 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 340d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDualSpaceClearDMData_Internal(PetscDualSpace sp, DM dm) 341d71ae5a4SJacob 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 /*@ 377*dce8aebaSBarry Smith PetscDualSpaceDestroy - Destroys a `PetscDualSpace` object 37820cf1dd8SToby Isaac 379d083f849SBarry Smith Collective on sp 38020cf1dd8SToby Isaac 38120cf1dd8SToby Isaac Input Parameter: 382*dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to destroy 38320cf1dd8SToby Isaac 384a4ce7ad1SMatthew G. Knepley Level: beginner 38520cf1dd8SToby Isaac 386*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceView()`, `PetscDualSpace()`, `PetscDualSpaceCreate()` 38720cf1dd8SToby Isaac @*/ 388d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceDestroy(PetscDualSpace *sp) 389d71ae5a4SJacob 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 /*@ 417*dce8aebaSBarry Smith 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: 422*dce8aebaSBarry Smith . comm - The communicator for the `PetscDualSpace` object 42320cf1dd8SToby Isaac 42420cf1dd8SToby Isaac Output Parameter: 425*dce8aebaSBarry Smith . sp - The `PetscDualSpace` object 42620cf1dd8SToby Isaac 42720cf1dd8SToby Isaac Level: beginner 42820cf1dd8SToby Isaac 429*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetType()`, `PETSCDUALSPACELAGRANGE` 43020cf1dd8SToby Isaac @*/ 431d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreate(MPI_Comm comm, PetscDualSpace *sp) 432d71ae5a4SJacob 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 /*@ 456*dce8aebaSBarry Smith PetscDualSpaceDuplicate - Creates a duplicate `PetscDualSpace` object that is not setup. 45720cf1dd8SToby Isaac 458d083f849SBarry Smith Collective on sp 45920cf1dd8SToby Isaac 46020cf1dd8SToby Isaac Input Parameter: 461*dce8aebaSBarry Smith . sp - The original `PetscDualSpace` 46220cf1dd8SToby Isaac 46320cf1dd8SToby Isaac Output Parameter: 464*dce8aebaSBarry Smith . spNew - The duplicate `PetscDualSpace` 46520cf1dd8SToby Isaac 46620cf1dd8SToby Isaac Level: beginner 46720cf1dd8SToby Isaac 468*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`, `PetscDualSpaceSetType()` 46920cf1dd8SToby Isaac @*/ 470d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceDuplicate(PetscDualSpace sp, PetscDualSpace *spNew) 471d71ae5a4SJacob 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 /*@ 496*dce8aebaSBarry Smith PetscDualSpaceGetDM - Get the `DM` representing the reference cell of a `PetscDualSpace` 49720cf1dd8SToby Isaac 49820cf1dd8SToby Isaac Not collective 49920cf1dd8SToby Isaac 50020cf1dd8SToby Isaac Input Parameter: 501*dce8aebaSBarry Smith . sp - The `PetscDualSpace` 50220cf1dd8SToby Isaac 50320cf1dd8SToby Isaac Output Parameter: 504*dce8aebaSBarry Smith . dm - The reference cell, that is a `DM` that consists of a single cell 50520cf1dd8SToby Isaac 50620cf1dd8SToby Isaac Level: intermediate 50720cf1dd8SToby Isaac 508*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetDM()`, `PetscDualSpaceCreate()` 50920cf1dd8SToby Isaac @*/ 510d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDM(PetscDualSpace sp, DM *dm) 511d71ae5a4SJacob 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 /*@ 520*dce8aebaSBarry Smith PetscDualSpaceSetDM - Get the `DM` representing the reference cell 52120cf1dd8SToby Isaac 52220cf1dd8SToby Isaac Not collective 52320cf1dd8SToby Isaac 52420cf1dd8SToby Isaac Input Parameters: 525*dce8aebaSBarry Smith + sp - The `PetscDual`Space 52620cf1dd8SToby Isaac - dm - The reference cell 52720cf1dd8SToby Isaac 52820cf1dd8SToby Isaac Level: intermediate 52920cf1dd8SToby Isaac 530*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `DM`, `PetscDualSpaceGetDM()`, `PetscDualSpaceCreate()` 53120cf1dd8SToby Isaac @*/ 532d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetDM(PetscDualSpace sp, DM dm) 533d71ae5a4SJacob 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: 551*dce8aebaSBarry Smith . sp - The `PetscDualSpace` 55220cf1dd8SToby Isaac 55320cf1dd8SToby Isaac Output Parameter: 55420cf1dd8SToby Isaac . order - The order 55520cf1dd8SToby Isaac 55620cf1dd8SToby Isaac Level: intermediate 55720cf1dd8SToby Isaac 558*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetOrder()`, `PetscDualSpaceCreate()` 55920cf1dd8SToby Isaac @*/ 560d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetOrder(PetscDualSpace sp, PetscInt *order) 561d71ae5a4SJacob 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: 575*dce8aebaSBarry Smith + sp - The `PetscDualSpace` 57620cf1dd8SToby Isaac - order - The order 57720cf1dd8SToby Isaac 57820cf1dd8SToby Isaac Level: intermediate 57920cf1dd8SToby Isaac 580*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetOrder()`, `PetscDualSpaceCreate()` 58120cf1dd8SToby Isaac @*/ 582d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetOrder(PetscDualSpace sp, PetscInt order) 583d71ae5a4SJacob 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: 595*dce8aebaSBarry Smith . sp - The `PetscDualSpace` 59620cf1dd8SToby Isaac 59720cf1dd8SToby Isaac Output Parameter: 59820cf1dd8SToby Isaac . Nc - The number of components 59920cf1dd8SToby Isaac 60020cf1dd8SToby Isaac Level: intermediate 60120cf1dd8SToby Isaac 602*dce8aebaSBarry Smith Note: 603*dce8aebaSBarry Smith A vector space, for example, will have d components, where d is the spatial dimension 604*dce8aebaSBarry Smith 605db781477SPatrick Sanan .seealso: `PetscDualSpaceSetNumComponents()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 60620cf1dd8SToby Isaac @*/ 607d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetNumComponents(PetscDualSpace sp, PetscInt *Nc) 608d71ae5a4SJacob Faibussowitsch { 60920cf1dd8SToby Isaac PetscFunctionBegin; 61020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 611dadcf809SJacob Faibussowitsch PetscValidIntPointer(Nc, 2); 61220cf1dd8SToby Isaac *Nc = sp->Nc; 61320cf1dd8SToby Isaac PetscFunctionReturn(0); 61420cf1dd8SToby Isaac } 61520cf1dd8SToby Isaac 61620cf1dd8SToby Isaac /*@ 61720cf1dd8SToby Isaac PetscDualSpaceSetNumComponents - Set the number of components for this space 61820cf1dd8SToby Isaac 61920cf1dd8SToby Isaac Input Parameters: 620*dce8aebaSBarry Smith + sp - The `PetscDualSpace` 62120cf1dd8SToby Isaac - order - The number of components 62220cf1dd8SToby Isaac 62320cf1dd8SToby Isaac Level: intermediate 62420cf1dd8SToby Isaac 625db781477SPatrick Sanan .seealso: `PetscDualSpaceGetNumComponents()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 62620cf1dd8SToby Isaac @*/ 627d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetNumComponents(PetscDualSpace sp, PetscInt Nc) 628d71ae5a4SJacob Faibussowitsch { 62920cf1dd8SToby Isaac PetscFunctionBegin; 63020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 63128b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 63220cf1dd8SToby Isaac sp->Nc = Nc; 63320cf1dd8SToby Isaac PetscFunctionReturn(0); 63420cf1dd8SToby Isaac } 63520cf1dd8SToby Isaac 63620cf1dd8SToby Isaac /*@ 63720cf1dd8SToby Isaac PetscDualSpaceGetFunctional - Get the i-th basis functional in the dual space 63820cf1dd8SToby Isaac 63920cf1dd8SToby Isaac Not collective 64020cf1dd8SToby Isaac 64120cf1dd8SToby Isaac Input Parameters: 642*dce8aebaSBarry Smith + sp - The `PetscDualSpace` 64320cf1dd8SToby Isaac - i - The basis number 64420cf1dd8SToby Isaac 64520cf1dd8SToby Isaac Output Parameter: 64620cf1dd8SToby Isaac . functional - The basis functional 64720cf1dd8SToby Isaac 64820cf1dd8SToby Isaac Level: intermediate 64920cf1dd8SToby Isaac 650*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()` 65120cf1dd8SToby Isaac @*/ 652d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetFunctional(PetscDualSpace sp, PetscInt i, PetscQuadrature *functional) 653d71ae5a4SJacob Faibussowitsch { 65420cf1dd8SToby Isaac PetscInt dim; 65520cf1dd8SToby Isaac 65620cf1dd8SToby Isaac PetscFunctionBegin; 65720cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 65820cf1dd8SToby Isaac PetscValidPointer(functional, 3); 6599566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &dim)); 66063a3b9bcSJacob 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); 66120cf1dd8SToby Isaac *functional = sp->functional[i]; 66220cf1dd8SToby Isaac PetscFunctionReturn(0); 66320cf1dd8SToby Isaac } 66420cf1dd8SToby Isaac 66520cf1dd8SToby Isaac /*@ 66620cf1dd8SToby Isaac PetscDualSpaceGetDimension - Get the dimension of the dual space, i.e. the number of basis functionals 66720cf1dd8SToby Isaac 66820cf1dd8SToby Isaac Not collective 66920cf1dd8SToby Isaac 67020cf1dd8SToby Isaac Input Parameter: 671*dce8aebaSBarry Smith . sp - The `PetscDualSpace` 67220cf1dd8SToby Isaac 67320cf1dd8SToby Isaac Output Parameter: 67420cf1dd8SToby Isaac . dim - The dimension 67520cf1dd8SToby Isaac 67620cf1dd8SToby Isaac Level: intermediate 67720cf1dd8SToby Isaac 678*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 67920cf1dd8SToby Isaac @*/ 680d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDimension(PetscDualSpace sp, PetscInt *dim) 681d71ae5a4SJacob Faibussowitsch { 68220cf1dd8SToby Isaac PetscFunctionBegin; 68320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 684dadcf809SJacob Faibussowitsch PetscValidIntPointer(dim, 2); 685b4457527SToby Isaac if (sp->spdim < 0) { 686b4457527SToby Isaac PetscSection section; 687b4457527SToby Isaac 6889566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 689b4457527SToby Isaac if (section) { 6909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &(sp->spdim))); 691b4457527SToby Isaac } else sp->spdim = 0; 692b4457527SToby Isaac } 693b4457527SToby Isaac *dim = sp->spdim; 69420cf1dd8SToby Isaac PetscFunctionReturn(0); 69520cf1dd8SToby Isaac } 69620cf1dd8SToby Isaac 697b4457527SToby Isaac /*@ 698b4457527SToby 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 699b4457527SToby Isaac 700b4457527SToby Isaac Not collective 701b4457527SToby Isaac 702b4457527SToby Isaac Input Parameter: 703*dce8aebaSBarry Smith . sp - The `PetscDualSpace` 704b4457527SToby Isaac 705b4457527SToby Isaac Output Parameter: 706b4457527SToby Isaac . dim - The dimension 707b4457527SToby Isaac 708b4457527SToby Isaac Level: intermediate 709b4457527SToby Isaac 710*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 711b4457527SToby Isaac @*/ 712d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetInteriorDimension(PetscDualSpace sp, PetscInt *intdim) 713d71ae5a4SJacob Faibussowitsch { 714b4457527SToby Isaac PetscFunctionBegin; 715b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 716dadcf809SJacob Faibussowitsch PetscValidIntPointer(intdim, 2); 717b4457527SToby Isaac if (sp->spintdim < 0) { 718b4457527SToby Isaac PetscSection section; 719b4457527SToby Isaac 7209566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 721b4457527SToby Isaac if (section) { 7229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &(sp->spintdim))); 723b4457527SToby Isaac } else sp->spintdim = 0; 724b4457527SToby Isaac } 725b4457527SToby Isaac *intdim = sp->spintdim; 726b4457527SToby Isaac PetscFunctionReturn(0); 727b4457527SToby Isaac } 728b4457527SToby Isaac 729b4457527SToby Isaac /*@ 730b4457527SToby Isaac PetscDualSpaceGetUniform - Whether this dual space is uniform 731b4457527SToby Isaac 732b4457527SToby Isaac Not collective 733b4457527SToby Isaac 734b4457527SToby Isaac Input Parameters: 735b4457527SToby Isaac . sp - A dual space 736b4457527SToby Isaac 737b4457527SToby Isaac Output Parameters: 738*dce8aebaSBarry Smith . uniform - `PETSC_TRUE` if (a) the dual space is the same for each point in a stratum of the reference `DMPLEX`, and 739*dce8aebaSBarry Smith (b) every symmetry of each point in the reference `DMPLEX` is also a symmetry of the point's dual space. 740b4457527SToby Isaac 741b4457527SToby Isaac Level: advanced 742b4457527SToby Isaac 743*dce8aebaSBarry Smith Note: 744*dce8aebaSBarry Smith All of the usual spaces on simplex or tensor-product elements will be uniform, only reference cells 745b4457527SToby Isaac with non-uniform strata (like trianguar-prisms) or anisotropic hp dual spaces will not be uniform. 746b4457527SToby Isaac 747*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetPointSubspace()`, `PetscDualSpaceGetSymmetries()` 748b4457527SToby Isaac @*/ 749d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetUniform(PetscDualSpace sp, PetscBool *uniform) 750d71ae5a4SJacob Faibussowitsch { 751b4457527SToby Isaac PetscFunctionBegin; 752b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 753dadcf809SJacob Faibussowitsch PetscValidBoolPointer(uniform, 2); 754b4457527SToby Isaac *uniform = sp->uniform; 755b4457527SToby Isaac PetscFunctionReturn(0); 756b4457527SToby Isaac } 757b4457527SToby Isaac 75820cf1dd8SToby Isaac /*@C 75920cf1dd8SToby Isaac PetscDualSpaceGetNumDof - Get the number of degrees of freedom for each spatial (topological) dimension 76020cf1dd8SToby Isaac 76120cf1dd8SToby Isaac Not collective 76220cf1dd8SToby Isaac 76320cf1dd8SToby Isaac Input Parameter: 764*dce8aebaSBarry Smith . sp - The `PetscDualSpace` 76520cf1dd8SToby Isaac 76620cf1dd8SToby Isaac Output Parameter: 76720cf1dd8SToby Isaac . numDof - An array of length dim+1 which holds the number of dofs for each dimension 76820cf1dd8SToby Isaac 76920cf1dd8SToby Isaac Level: intermediate 77020cf1dd8SToby Isaac 771*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 77220cf1dd8SToby Isaac @*/ 773d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetNumDof(PetscDualSpace sp, const PetscInt **numDof) 774d71ae5a4SJacob Faibussowitsch { 77520cf1dd8SToby Isaac PetscFunctionBegin; 77620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 77720cf1dd8SToby Isaac PetscValidPointer(numDof, 2); 77828b400f6SJacob 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"); 779b4457527SToby Isaac if (!sp->numDof) { 780b4457527SToby Isaac DM dm; 781b4457527SToby Isaac PetscInt depth, d; 782b4457527SToby Isaac PetscSection section; 783b4457527SToby Isaac 7849566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 7859566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 7869566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth + 1, &(sp->numDof))); 7879566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 788b4457527SToby Isaac for (d = 0; d <= depth; d++) { 789b4457527SToby Isaac PetscInt dStart, dEnd; 790b4457527SToby Isaac 7919566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 792b4457527SToby Isaac if (dEnd <= dStart) continue; 7939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, dStart, &(sp->numDof[d]))); 794b4457527SToby Isaac } 795b4457527SToby Isaac } 796b4457527SToby Isaac *numDof = sp->numDof; 79708401ef6SPierre Jolivet PetscCheck(*numDof, PetscObjectComm((PetscObject)sp), PETSC_ERR_LIB, "Empty numDof[] returned from dual space implementation"); 79820cf1dd8SToby Isaac PetscFunctionReturn(0); 79920cf1dd8SToby Isaac } 80020cf1dd8SToby Isaac 801b4457527SToby Isaac /* create the section of the right size and set a permutation for topological ordering */ 802d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSectionCreate_Internal(PetscDualSpace sp, PetscSection *topSection) 803d71ae5a4SJacob Faibussowitsch { 804b4457527SToby Isaac DM dm; 805b4457527SToby Isaac PetscInt pStart, pEnd, cStart, cEnd, c, depth, count, i; 806b4457527SToby Isaac PetscInt *seen, *perm; 807b4457527SToby Isaac PetscSection section; 808b4457527SToby Isaac 809b4457527SToby Isaac PetscFunctionBegin; 810b4457527SToby Isaac dm = sp->dm; 8119566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion)); 8129566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 8149566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &seen)); 8159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &perm)); 8169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8179566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 818b4457527SToby Isaac for (c = cStart, count = 0; c < cEnd; c++) { 819b4457527SToby Isaac PetscInt closureSize = -1, e; 820b4457527SToby Isaac PetscInt *closure = NULL; 821b4457527SToby Isaac 822b4457527SToby Isaac perm[count++] = c; 823b4457527SToby Isaac seen[c - pStart] = 1; 8249566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 825b4457527SToby Isaac for (e = 0; e < closureSize; e++) { 826b4457527SToby Isaac PetscInt point = closure[2 * e]; 827b4457527SToby Isaac 828b4457527SToby Isaac if (seen[point - pStart]) continue; 829b4457527SToby Isaac perm[count++] = point; 830b4457527SToby Isaac seen[point - pStart] = 1; 831b4457527SToby Isaac } 8329566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 833b4457527SToby Isaac } 8341dca8a05SBarry Smith PetscCheck(count == pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad topological ordering"); 8359371c9d4SSatish Balay for (i = 0; i < pEnd - pStart; i++) 8369371c9d4SSatish Balay if (perm[i] != i) break; 837b4457527SToby Isaac if (i < pEnd - pStart) { 838b4457527SToby Isaac IS permIS; 839b4457527SToby Isaac 8409566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pEnd - pStart, perm, PETSC_OWN_POINTER, &permIS)); 8419566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(permIS)); 8429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(section, permIS)); 8439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS)); 844b4457527SToby Isaac } else { 8459566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 846b4457527SToby Isaac } 8479566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 848b4457527SToby Isaac *topSection = section; 849b4457527SToby Isaac PetscFunctionReturn(0); 850b4457527SToby Isaac } 851b4457527SToby Isaac 852b4457527SToby Isaac /* mark boundary points and set up */ 853d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSectionSetUp_Internal(PetscDualSpace sp, PetscSection section) 854d71ae5a4SJacob Faibussowitsch { 855b4457527SToby Isaac DM dm; 856b4457527SToby Isaac DMLabel boundary; 857b4457527SToby Isaac PetscInt pStart, pEnd, p; 858b4457527SToby Isaac 859b4457527SToby Isaac PetscFunctionBegin; 860b4457527SToby Isaac dm = sp->dm; 8619566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "boundary", &boundary)); 8629566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 8639566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, 1, boundary)); 8649566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, boundary)); 8659566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 866b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 867b4457527SToby Isaac PetscInt bval; 868b4457527SToby Isaac 8699566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(boundary, p, &bval)); 870b4457527SToby Isaac if (bval == 1) { 871b4457527SToby Isaac PetscInt dof; 872b4457527SToby Isaac 8739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 8749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetConstraintDof(section, p, dof)); 875b4457527SToby Isaac } 876b4457527SToby Isaac } 8779566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&boundary)); 8789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 879b4457527SToby Isaac PetscFunctionReturn(0); 880b4457527SToby Isaac } 881b4457527SToby Isaac 882a4ce7ad1SMatthew G. Knepley /*@ 883*dce8aebaSBarry Smith PetscDualSpaceGetSection - Create a `PetscSection` over the reference cell with the layout from this space 884a4ce7ad1SMatthew G. Knepley 885a4ce7ad1SMatthew G. Knepley Collective on sp 886a4ce7ad1SMatthew G. Knepley 887a4ce7ad1SMatthew G. Knepley Input Parameters: 888*dce8aebaSBarry Smith . sp - The `PetscDualSpace` 889a4ce7ad1SMatthew G. Knepley 890a4ce7ad1SMatthew G. Knepley Output Parameter: 891a4ce7ad1SMatthew G. Knepley . section - The section 892a4ce7ad1SMatthew G. Knepley 893a4ce7ad1SMatthew G. Knepley Level: advanced 894a4ce7ad1SMatthew G. Knepley 895*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscSection`, `PetscDualSpaceCreate()`, `DMPLEX` 896a4ce7ad1SMatthew G. Knepley @*/ 897d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetSection(PetscDualSpace sp, PetscSection *section) 898d71ae5a4SJacob Faibussowitsch { 899b4457527SToby Isaac PetscInt pStart, pEnd, p; 900b4457527SToby Isaac 901b4457527SToby Isaac PetscFunctionBegin; 90278f1d139SRomain Beucher if (!sp->dm) { 90378f1d139SRomain Beucher *section = NULL; 90478f1d139SRomain Beucher PetscFunctionReturn(0); 90578f1d139SRomain Beucher } 906b4457527SToby Isaac if (!sp->pointSection) { 907b4457527SToby Isaac /* mark the boundary */ 9089566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionCreate_Internal(sp, &(sp->pointSection))); 9099566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(sp->dm, &pStart, &pEnd)); 910b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 911b4457527SToby Isaac PetscDualSpace psp; 912b4457527SToby Isaac 9139566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, p, &psp)); 914b4457527SToby Isaac if (psp) { 915b4457527SToby Isaac PetscInt dof; 916b4457527SToby Isaac 9179566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorDimension(psp, &dof)); 9189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sp->pointSection, p, dof)); 919b4457527SToby Isaac } 920b4457527SToby Isaac } 9219566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionSetUp_Internal(sp, sp->pointSection)); 922b4457527SToby Isaac } 923b4457527SToby Isaac *section = sp->pointSection; 924b4457527SToby Isaac PetscFunctionReturn(0); 925b4457527SToby Isaac } 926b4457527SToby Isaac 927b4457527SToby Isaac /* this assumes that all of the point dual spaces store their interior dofs first, which is true when the point DMs 928b4457527SToby Isaac * have one cell */ 929d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushForwardSubspaces_Internal(PetscDualSpace sp, PetscInt sStart, PetscInt sEnd) 930d71ae5a4SJacob Faibussowitsch { 931b4457527SToby Isaac PetscReal *sv0, *v0, *J; 932b4457527SToby Isaac PetscSection section; 933b4457527SToby Isaac PetscInt dim, s, k; 93420cf1dd8SToby Isaac DM dm; 93520cf1dd8SToby Isaac 93620cf1dd8SToby Isaac PetscFunctionBegin; 9379566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 9389566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9399566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 9409566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim, &sv0, dim * dim, &J)); 9419566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFormDegree(sp, &k)); 942b4457527SToby Isaac for (s = sStart; s < sEnd; s++) { 943b4457527SToby Isaac PetscReal detJ, hdetJ; 944b4457527SToby Isaac PetscDualSpace ssp; 945b4457527SToby Isaac PetscInt dof, off, f, sdim; 946b4457527SToby Isaac PetscInt i, j; 947b4457527SToby Isaac DM sdm; 94820cf1dd8SToby Isaac 9499566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, s, &ssp)); 950b4457527SToby Isaac if (!ssp) continue; 9519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, s, &dof)); 9529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, s, &off)); 953b4457527SToby Isaac /* get the first vertex of the reference cell */ 9549566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(ssp, &sdm)); 9559566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sdm, &sdim)); 9569566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(sdm, 0, sv0, NULL, NULL, &hdetJ)); 9579566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, s, v0, J, NULL, &detJ)); 958b4457527SToby Isaac /* compactify Jacobian */ 9599371c9d4SSatish Balay for (i = 0; i < dim; i++) 9609371c9d4SSatish Balay for (j = 0; j < sdim; j++) J[i * sdim + j] = J[i * dim + j]; 961b4457527SToby Isaac for (f = 0; f < dof; f++) { 962b4457527SToby Isaac PetscQuadrature fn; 96320cf1dd8SToby Isaac 9649566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(ssp, f, &fn)); 9659566063dSJacob Faibussowitsch PetscCall(PetscQuadraturePushForward(fn, dim, sv0, v0, J, k, &(sp->functional[off + f]))); 96620cf1dd8SToby Isaac } 96720cf1dd8SToby Isaac } 9689566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, sv0, J)); 96920cf1dd8SToby Isaac PetscFunctionReturn(0); 97020cf1dd8SToby Isaac } 97120cf1dd8SToby Isaac 97220cf1dd8SToby Isaac /*@C 97320cf1dd8SToby Isaac PetscDualSpaceApply - Apply a functional from the dual space basis to an input function 97420cf1dd8SToby Isaac 97520cf1dd8SToby Isaac Input Parameters: 976*dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 97720cf1dd8SToby Isaac . f - The basis functional index 97820cf1dd8SToby Isaac . time - The time 97920cf1dd8SToby 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) 98020cf1dd8SToby Isaac . numComp - The number of components for the function 98120cf1dd8SToby Isaac . func - The input function 98220cf1dd8SToby Isaac - ctx - A context for the function 98320cf1dd8SToby Isaac 98420cf1dd8SToby Isaac Output Parameter: 98520cf1dd8SToby Isaac . value - numComp output values 98620cf1dd8SToby Isaac 987*dce8aebaSBarry Smith Calling Sequence of func: 988*dce8aebaSBarry Smith .vb 989*dce8aebaSBarry Smith func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt numComponents, PetscScalar values[], void *ctx) 990*dce8aebaSBarry Smith .ve 99120cf1dd8SToby Isaac 992a4ce7ad1SMatthew G. Knepley Level: beginner 99320cf1dd8SToby Isaac 994*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 99520cf1dd8SToby Isaac @*/ 996d71ae5a4SJacob 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) 997d71ae5a4SJacob Faibussowitsch { 99820cf1dd8SToby Isaac PetscFunctionBegin; 99920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 100020cf1dd8SToby Isaac PetscValidPointer(cgeom, 4); 1001dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 1002dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, apply, f, time, cgeom, numComp, func, ctx, value); 100320cf1dd8SToby Isaac PetscFunctionReturn(0); 100420cf1dd8SToby Isaac } 100520cf1dd8SToby Isaac 100620cf1dd8SToby Isaac /*@C 1007*dce8aebaSBarry Smith PetscDualSpaceApplyAll - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetAllData()` 100820cf1dd8SToby Isaac 100920cf1dd8SToby Isaac Input Parameters: 1010*dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1011*dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetAllData()` 101220cf1dd8SToby Isaac 101320cf1dd8SToby Isaac Output Parameter: 101420cf1dd8SToby Isaac . spValue - The values of all dual space functionals 101520cf1dd8SToby Isaac 1016*dce8aebaSBarry Smith Level: advanced 101720cf1dd8SToby Isaac 1018*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 101920cf1dd8SToby Isaac @*/ 1020d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyAll(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1021d71ae5a4SJacob Faibussowitsch { 102220cf1dd8SToby Isaac PetscFunctionBegin; 102320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1024dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyall, pointEval, spValue); 102520cf1dd8SToby Isaac PetscFunctionReturn(0); 102620cf1dd8SToby Isaac } 102720cf1dd8SToby Isaac 102820cf1dd8SToby Isaac /*@C 1029*dce8aebaSBarry Smith PetscDualSpaceApplyInterior - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1030b4457527SToby Isaac 1031b4457527SToby Isaac Input Parameters: 1032*dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1033*dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1034b4457527SToby Isaac 1035b4457527SToby Isaac Output Parameter: 1036b4457527SToby Isaac . spValue - The values of interior dual space functionals 1037b4457527SToby Isaac 1038*dce8aebaSBarry Smith Level: advanced 1039b4457527SToby Isaac 1040*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 1041b4457527SToby Isaac @*/ 1042d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyInterior(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1043d71ae5a4SJacob Faibussowitsch { 1044b4457527SToby Isaac PetscFunctionBegin; 1045b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1046dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyint, pointEval, spValue); 1047b4457527SToby Isaac PetscFunctionReturn(0); 1048b4457527SToby Isaac } 1049b4457527SToby Isaac 1050b4457527SToby Isaac /*@C 105120cf1dd8SToby Isaac PetscDualSpaceApplyDefault - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional. 105220cf1dd8SToby Isaac 105320cf1dd8SToby Isaac Input Parameters: 1054*dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 105520cf1dd8SToby Isaac . f - The basis functional index 105620cf1dd8SToby Isaac . time - The time 105720cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian) 105820cf1dd8SToby Isaac . Nc - The number of components for the function 105920cf1dd8SToby Isaac . func - The input function 106020cf1dd8SToby Isaac - ctx - A context for the function 106120cf1dd8SToby Isaac 106220cf1dd8SToby Isaac Output Parameter: 106320cf1dd8SToby Isaac . value - The output value 106420cf1dd8SToby Isaac 1065*dce8aebaSBarry Smith Calling Sequence of func: 1066*dce8aebaSBarry Smith .vb 1067*dce8aebaSBarry Smith func(PetscInt dim, PetscReal time, const PetscReal x[],PetscInt numComponents, PetscScalar values[], void *ctx) 1068*dce8aebaSBarry Smith .ve 106920cf1dd8SToby Isaac 1070*dce8aebaSBarry Smith Level: advanced 107120cf1dd8SToby Isaac 1072*dce8aebaSBarry Smith Note: 1073*dce8aebaSBarry Smith The idea is to evaluate the functional as an integral $ n(f) = \int dx n(x) . f(x) $ where both n and f have Nc components. 107420cf1dd8SToby Isaac 1075*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 107620cf1dd8SToby Isaac @*/ 1077d71ae5a4SJacob 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) 1078d71ae5a4SJacob Faibussowitsch { 107920cf1dd8SToby Isaac DM dm; 108020cf1dd8SToby Isaac PetscQuadrature n; 108120cf1dd8SToby Isaac const PetscReal *points, *weights; 108220cf1dd8SToby Isaac PetscReal x[3]; 108320cf1dd8SToby Isaac PetscScalar *val; 108420cf1dd8SToby Isaac PetscInt dim, dE, qNc, c, Nq, q; 108520cf1dd8SToby Isaac PetscBool isAffine; 108620cf1dd8SToby Isaac 108720cf1dd8SToby Isaac PetscFunctionBegin; 108820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1089dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 10909566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 10919566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 10929566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, &dim, &qNc, &Nq, &points, &weights)); 109363a3b9bcSJacob 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); 109463a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 10959566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 109620cf1dd8SToby Isaac *value = 0.0; 109720cf1dd8SToby Isaac isAffine = cgeom->isAffine; 109820cf1dd8SToby Isaac dE = cgeom->dimEmbed; 109920cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 110020cf1dd8SToby Isaac if (isAffine) { 110120cf1dd8SToby Isaac CoordinatesRefToReal(dE, cgeom->dim, cgeom->xi, cgeom->v, cgeom->J, &points[q * dim], x); 11029566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, x, Nc, val, ctx)); 110320cf1dd8SToby Isaac } else { 11049566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, &cgeom->v[dE * q], Nc, val, ctx)); 110520cf1dd8SToby Isaac } 1106ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) *value += val[c] * weights[q * Nc + c]; 110720cf1dd8SToby Isaac } 11089566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 110920cf1dd8SToby Isaac PetscFunctionReturn(0); 111020cf1dd8SToby Isaac } 111120cf1dd8SToby Isaac 111220cf1dd8SToby Isaac /*@C 1113*dce8aebaSBarry Smith PetscDualSpaceApplyAllDefault - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetAllData()` 111420cf1dd8SToby Isaac 111520cf1dd8SToby Isaac Input Parameters: 1116*dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1117*dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetAllData()` 111820cf1dd8SToby Isaac 111920cf1dd8SToby Isaac Output Parameter: 112020cf1dd8SToby Isaac . spValue - The values of all dual space functionals 112120cf1dd8SToby Isaac 1122*dce8aebaSBarry Smith Level: advanced 112320cf1dd8SToby Isaac 1124*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 112520cf1dd8SToby Isaac @*/ 1126d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyAllDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1127d71ae5a4SJacob Faibussowitsch { 1128b4457527SToby Isaac Vec pointValues, dofValues; 1129b4457527SToby Isaac Mat allMat; 113020cf1dd8SToby Isaac 113120cf1dd8SToby Isaac PetscFunctionBegin; 113220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 113320cf1dd8SToby Isaac PetscValidScalarPointer(pointEval, 2); 1134064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11359566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetAllData(sp, NULL, &allMat)); 113648a46eb9SPierre Jolivet if (!(sp->allNodeValues)) PetscCall(MatCreateVecs(allMat, &(sp->allNodeValues), NULL)); 1137b4457527SToby Isaac pointValues = sp->allNodeValues; 113848a46eb9SPierre Jolivet if (!(sp->allDofValues)) PetscCall(MatCreateVecs(allMat, NULL, &(sp->allDofValues))); 1139b4457527SToby Isaac dofValues = sp->allDofValues; 11409566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11419566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11429566063dSJacob Faibussowitsch PetscCall(MatMult(allMat, pointValues, dofValues)); 11439566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11449566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 1145b4457527SToby Isaac PetscFunctionReturn(0); 114620cf1dd8SToby Isaac } 1147b4457527SToby Isaac 1148b4457527SToby Isaac /*@C 1149*dce8aebaSBarry Smith PetscDualSpaceApplyInteriorDefault - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1150b4457527SToby Isaac 1151b4457527SToby Isaac Input Parameters: 1152*dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1153*dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1154b4457527SToby Isaac 1155b4457527SToby Isaac Output Parameter: 1156b4457527SToby Isaac . spValue - The values of interior dual space functionals 1157b4457527SToby Isaac 1158*dce8aebaSBarry Smith Level: advanced 1159b4457527SToby Isaac 1160*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 1161b4457527SToby Isaac @*/ 1162d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyInteriorDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1163d71ae5a4SJacob Faibussowitsch { 1164b4457527SToby Isaac Vec pointValues, dofValues; 1165b4457527SToby Isaac Mat intMat; 1166b4457527SToby Isaac 1167b4457527SToby Isaac PetscFunctionBegin; 1168b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1169b4457527SToby Isaac PetscValidScalarPointer(pointEval, 2); 1170064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11719566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(sp, NULL, &intMat)); 117248a46eb9SPierre Jolivet if (!(sp->intNodeValues)) PetscCall(MatCreateVecs(intMat, &(sp->intNodeValues), NULL)); 1173b4457527SToby Isaac pointValues = sp->intNodeValues; 117448a46eb9SPierre Jolivet if (!(sp->intDofValues)) PetscCall(MatCreateVecs(intMat, NULL, &(sp->intDofValues))); 1175b4457527SToby Isaac dofValues = sp->intDofValues; 11769566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11779566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11789566063dSJacob Faibussowitsch PetscCall(MatMult(intMat, pointValues, dofValues)); 11799566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11809566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 118120cf1dd8SToby Isaac PetscFunctionReturn(0); 118220cf1dd8SToby Isaac } 118320cf1dd8SToby Isaac 1184a4ce7ad1SMatthew G. Knepley /*@ 1185b4457527SToby Isaac PetscDualSpaceGetAllData - Get all quadrature nodes from this space, and the matrix that sends quadrature node values to degree-of-freedom values 1186a4ce7ad1SMatthew G. Knepley 1187a4ce7ad1SMatthew G. Knepley Input Parameter: 1188a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1189a4ce7ad1SMatthew G. Knepley 1190d8d19677SJose E. Roman Output Parameters: 1191*dce8aebaSBarry Smith + allNodes - A `PetscQuadrature` object containing all evaluation nodes 1192*dce8aebaSBarry Smith - allMat - A `Mat` for the node-to-dof transformation 1193a4ce7ad1SMatthew G. Knepley 1194a4ce7ad1SMatthew G. Knepley Level: advanced 1195a4ce7ad1SMatthew G. Knepley 1196*dce8aebaSBarry Smith .seealso: `PetscQuadrature`, `PetscDualSpace`, `PetscDualSpaceCreate()`, `Mat` 1197a4ce7ad1SMatthew G. Knepley @*/ 1198d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetAllData(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 1199d71ae5a4SJacob Faibussowitsch { 120020cf1dd8SToby Isaac PetscFunctionBegin; 120120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1202b4457527SToby Isaac if (allNodes) PetscValidPointer(allNodes, 2); 1203b4457527SToby Isaac if (allMat) PetscValidPointer(allMat, 3); 1204b4457527SToby Isaac if ((!sp->allNodes || !sp->allMat) && sp->ops->createalldata) { 1205b4457527SToby Isaac PetscQuadrature qpoints; 1206b4457527SToby Isaac Mat amat; 1207b4457527SToby Isaac 1208dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createalldata, &qpoints, &amat); 12099566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->allNodes))); 12109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->allMat))); 1211b4457527SToby Isaac sp->allNodes = qpoints; 1212b4457527SToby Isaac sp->allMat = amat; 121320cf1dd8SToby Isaac } 1214b4457527SToby Isaac if (allNodes) *allNodes = sp->allNodes; 1215b4457527SToby Isaac if (allMat) *allMat = sp->allMat; 121620cf1dd8SToby Isaac PetscFunctionReturn(0); 121720cf1dd8SToby Isaac } 121820cf1dd8SToby Isaac 1219a4ce7ad1SMatthew G. Knepley /*@ 1220b4457527SToby Isaac PetscDualSpaceCreateAllDataDefault - Create all evaluation nodes and the node-to-dof matrix by examining functionals 1221a4ce7ad1SMatthew G. Knepley 1222a4ce7ad1SMatthew G. Knepley Input Parameter: 1223a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1224a4ce7ad1SMatthew G. Knepley 1225d8d19677SJose E. Roman Output Parameters: 1226*dce8aebaSBarry Smith + allNodes - A `PetscQuadrature` object containing all evaluation nodes 1227*dce8aebaSBarry Smith - allMat - A `Mat` for the node-to-dof transformation 1228a4ce7ad1SMatthew G. Knepley 1229a4ce7ad1SMatthew G. Knepley Level: advanced 1230a4ce7ad1SMatthew G. Knepley 1231*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`, `Mat`, `PetscQuadrature` 1232a4ce7ad1SMatthew G. Knepley @*/ 1233d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreateAllDataDefault(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 1234d71ae5a4SJacob Faibussowitsch { 123520cf1dd8SToby Isaac PetscInt spdim; 123620cf1dd8SToby Isaac PetscInt numPoints, offset; 123720cf1dd8SToby Isaac PetscReal *points; 123820cf1dd8SToby Isaac PetscInt f, dim; 1239b4457527SToby Isaac PetscInt Nc, nrows, ncols; 1240b4457527SToby Isaac PetscInt maxNumPoints; 124120cf1dd8SToby Isaac PetscQuadrature q; 1242b4457527SToby Isaac Mat A; 124320cf1dd8SToby Isaac 124420cf1dd8SToby Isaac PetscFunctionBegin; 12459566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 12469566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &spdim)); 124720cf1dd8SToby Isaac if (!spdim) { 12489566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes)); 12499566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, 0, 0, 0, NULL, NULL)); 125020cf1dd8SToby Isaac } 1251b4457527SToby Isaac nrows = spdim; 12529566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, 0, &q)); 12539566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, NULL, &numPoints, NULL, NULL)); 1254b4457527SToby Isaac maxNumPoints = numPoints; 125520cf1dd8SToby Isaac for (f = 1; f < spdim; f++) { 125620cf1dd8SToby Isaac PetscInt Np; 125720cf1dd8SToby Isaac 12589566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q)); 12599566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL)); 126020cf1dd8SToby Isaac numPoints += Np; 1261b4457527SToby Isaac maxNumPoints = PetscMax(maxNumPoints, Np); 126220cf1dd8SToby Isaac } 1263b4457527SToby Isaac ncols = numPoints * Nc; 12649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points)); 12659566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, nrows, ncols, maxNumPoints * Nc, NULL, &A)); 126620cf1dd8SToby Isaac for (f = 0, offset = 0; f < spdim; f++) { 1267b4457527SToby Isaac const PetscReal *p, *w; 126820cf1dd8SToby Isaac PetscInt Np, i; 1269b4457527SToby Isaac PetscInt fnc; 127020cf1dd8SToby Isaac 12719566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q)); 12729566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, &fnc, &Np, &p, &w)); 127308401ef6SPierre Jolivet PetscCheck(fnc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "functional component mismatch"); 1274ad540459SPierre Jolivet for (i = 0; i < Np * dim; i++) points[offset * dim + i] = p[i]; 127548a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(A, f, offset * Nc, w[i], INSERT_VALUES)); 1276b4457527SToby Isaac offset += Np; 1277b4457527SToby Isaac } 12789566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 12799566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 12809566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes)); 12819566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, dim, 0, numPoints, points, NULL)); 1282b4457527SToby Isaac *allMat = A; 1283b4457527SToby Isaac PetscFunctionReturn(0); 1284b4457527SToby Isaac } 1285b4457527SToby Isaac 1286b4457527SToby Isaac /*@ 1287b4457527SToby Isaac PetscDualSpaceGetInteriorData - Get all quadrature points necessary to compute the interior degrees of freedom from 1288b4457527SToby Isaac this space, as well as the matrix that computes the degrees of freedom from the quadrature values. Degrees of 1289*dce8aebaSBarry Smith freedom are interior degrees of freedom if they belong (by `PetscDualSpaceGetSection()`) to interior points in the 1290*dce8aebaSBarry Smith reference `DMPLEX`: complementary boundary degrees of freedom are marked as constrained in the section returned by 1291*dce8aebaSBarry Smith `PetscDualSpaceGetSection()`). 1292b4457527SToby Isaac 1293b4457527SToby Isaac Input Parameter: 1294b4457527SToby Isaac . sp - The dualspace 1295b4457527SToby Isaac 1296d8d19677SJose E. Roman Output Parameters: 1297*dce8aebaSBarry Smith + intNodes - A `PetscQuadrature` object containing all evaluation points needed to evaluate interior degrees of freedom 1298b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1299*dce8aebaSBarry Smith the size of the constrained layout (`PetscSectionGetConstrainStorageSize()`) of the dual space section, 1300*dce8aebaSBarry Smith npoints is the number of points in intNodes and nc is `PetscDualSpaceGetNumComponents()`. 1301b4457527SToby Isaac 1302b4457527SToby Isaac Level: advanced 1303b4457527SToby Isaac 1304*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `Mat`, `PetscDualSpaceCreate()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceGetNumComponents()`, `PetscQuadratureGetData()` 1305b4457527SToby Isaac @*/ 1306d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetInteriorData(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1307d71ae5a4SJacob Faibussowitsch { 1308b4457527SToby Isaac PetscFunctionBegin; 1309b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1310b4457527SToby Isaac if (intNodes) PetscValidPointer(intNodes, 2); 1311b4457527SToby Isaac if (intMat) PetscValidPointer(intMat, 3); 1312b4457527SToby Isaac if ((!sp->intNodes || !sp->intMat) && sp->ops->createintdata) { 1313b4457527SToby Isaac PetscQuadrature qpoints; 1314b4457527SToby Isaac Mat imat; 1315b4457527SToby Isaac 1316dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createintdata, &qpoints, &imat); 13179566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->intNodes))); 13189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->intMat))); 1319b4457527SToby Isaac sp->intNodes = qpoints; 1320b4457527SToby Isaac sp->intMat = imat; 1321b4457527SToby Isaac } 1322b4457527SToby Isaac if (intNodes) *intNodes = sp->intNodes; 1323b4457527SToby Isaac if (intMat) *intMat = sp->intMat; 1324b4457527SToby Isaac PetscFunctionReturn(0); 1325b4457527SToby Isaac } 1326b4457527SToby Isaac 1327b4457527SToby Isaac /*@ 1328b4457527SToby Isaac PetscDualSpaceCreateInteriorDataDefault - Create quadrature points by examining interior functionals and create the matrix mapping quadrature point values to interior dual space values 1329b4457527SToby Isaac 1330b4457527SToby Isaac Input Parameter: 1331b4457527SToby Isaac . sp - The dualspace 1332b4457527SToby Isaac 1333d8d19677SJose E. Roman Output Parameters: 1334*dce8aebaSBarry Smith + intNodes - A `PetscQuadrature` object containing all evaluation points needed to evaluate interior degrees of freedom 1335b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1336*dce8aebaSBarry Smith the size of the constrained layout (`PetscSectionGetConstrainStorageSize()`) of the dual space section, 1337*dce8aebaSBarry Smith npoints is the number of points in allNodes and nc is `PetscDualSpaceGetNumComponents()`. 1338b4457527SToby Isaac 1339b4457527SToby Isaac Level: advanced 1340b4457527SToby Isaac 1341*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `Mat`, `PetscDualSpaceCreate()`, `PetscDualSpaceGetInteriorData()` 1342b4457527SToby Isaac @*/ 1343d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreateInteriorDataDefault(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1344d71ae5a4SJacob Faibussowitsch { 1345b4457527SToby Isaac DM dm; 1346b4457527SToby Isaac PetscInt spdim0; 1347b4457527SToby Isaac PetscInt Nc; 1348b4457527SToby Isaac PetscInt pStart, pEnd, p, f; 1349b4457527SToby Isaac PetscSection section; 1350b4457527SToby Isaac PetscInt numPoints, offset, matoffset; 1351b4457527SToby Isaac PetscReal *points; 1352b4457527SToby Isaac PetscInt dim; 1353b4457527SToby Isaac PetscInt *nnz; 1354b4457527SToby Isaac PetscQuadrature q; 1355b4457527SToby Isaac Mat imat; 1356b4457527SToby Isaac 1357b4457527SToby Isaac PetscFunctionBegin; 1358b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 13599566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 13609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &spdim0)); 1361b4457527SToby Isaac if (!spdim0) { 1362b4457527SToby Isaac *intNodes = NULL; 1363b4457527SToby Isaac *intMat = NULL; 1364b4457527SToby Isaac PetscFunctionReturn(0); 1365b4457527SToby Isaac } 13669566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 13679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 13689566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 13699566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 13709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(spdim0, &nnz)); 1371b4457527SToby Isaac for (p = pStart, f = 0, numPoints = 0; p < pEnd; p++) { 1372b4457527SToby Isaac PetscInt dof, cdof, off, d; 1373b4457527SToby Isaac 13749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 13759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1376b4457527SToby Isaac if (!(dof - cdof)) continue; 13779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1378b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1379b4457527SToby Isaac PetscInt Np; 1380b4457527SToby Isaac 13819566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q)); 13829566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL)); 1383b4457527SToby Isaac nnz[f] = Np * Nc; 1384b4457527SToby Isaac numPoints += Np; 1385b4457527SToby Isaac } 1386b4457527SToby Isaac } 13879566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, spdim0, numPoints * Nc, 0, nnz, &imat)); 13889566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 13899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points)); 1390b4457527SToby Isaac for (p = pStart, f = 0, offset = 0, matoffset = 0; p < pEnd; p++) { 1391b4457527SToby Isaac PetscInt dof, cdof, off, d; 1392b4457527SToby Isaac 13939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 13949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1395b4457527SToby Isaac if (!(dof - cdof)) continue; 13969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1397b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1398b4457527SToby Isaac const PetscReal *p; 1399b4457527SToby Isaac const PetscReal *w; 1400b4457527SToby Isaac PetscInt Np, i; 1401b4457527SToby Isaac 14029566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q)); 14039566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, &p, &w)); 1404ad540459SPierre Jolivet for (i = 0; i < Np * dim; i++) points[offset + i] = p[i]; 140548a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(imat, f, matoffset + i, w[i], INSERT_VALUES)); 1406b4457527SToby Isaac offset += Np * dim; 1407b4457527SToby Isaac matoffset += Np * Nc; 1408b4457527SToby Isaac } 1409b4457527SToby Isaac } 14109566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, intNodes)); 14119566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*intNodes, dim, 0, numPoints, points, NULL)); 14129566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(imat, MAT_FINAL_ASSEMBLY)); 14139566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(imat, MAT_FINAL_ASSEMBLY)); 1414b4457527SToby Isaac *intMat = imat; 141520cf1dd8SToby Isaac PetscFunctionReturn(0); 141620cf1dd8SToby Isaac } 141720cf1dd8SToby Isaac 14184f9ab2b4SJed Brown /*@ 1419*dce8aebaSBarry Smith PetscDualSpaceEqual - Determine if two dual spaces are equivalent 14204f9ab2b4SJed Brown 14214f9ab2b4SJed Brown Input Parameters: 1422*dce8aebaSBarry Smith + A - A `PetscDualSpace` object 1423*dce8aebaSBarry Smith - B - Another `PetscDualSpace` object 14244f9ab2b4SJed Brown 14254f9ab2b4SJed Brown Output Parameter: 1426*dce8aebaSBarry Smith . equal - `PETSC_TRUE` if the dual spaces are equivalent 14274f9ab2b4SJed Brown 14284f9ab2b4SJed Brown Level: advanced 14294f9ab2b4SJed Brown 1430*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 14314f9ab2b4SJed Brown @*/ 1432d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceEqual(PetscDualSpace A, PetscDualSpace B, PetscBool *equal) 1433d71ae5a4SJacob Faibussowitsch { 14344f9ab2b4SJed Brown PetscInt sizeA, sizeB, dimA, dimB; 14354f9ab2b4SJed Brown const PetscInt *dofA, *dofB; 14364f9ab2b4SJed Brown PetscQuadrature quadA, quadB; 14374f9ab2b4SJed Brown Mat matA, matB; 14384f9ab2b4SJed Brown 14394f9ab2b4SJed Brown PetscFunctionBegin; 14404f9ab2b4SJed Brown PetscValidHeaderSpecific(A, PETSCDUALSPACE_CLASSID, 1); 14414f9ab2b4SJed Brown PetscValidHeaderSpecific(B, PETSCDUALSPACE_CLASSID, 2); 14424f9ab2b4SJed Brown PetscValidBoolPointer(equal, 3); 14434f9ab2b4SJed Brown *equal = PETSC_FALSE; 14449566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(A, &sizeA)); 14459566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(B, &sizeB)); 1446ad540459SPierre Jolivet if (sizeB != sizeA) PetscFunctionReturn(0); 14479566063dSJacob Faibussowitsch PetscCall(DMGetDimension(A->dm, &dimA)); 14489566063dSJacob Faibussowitsch PetscCall(DMGetDimension(B->dm, &dimB)); 1449ad540459SPierre Jolivet if (dimA != dimB) PetscFunctionReturn(0); 14504f9ab2b4SJed Brown 14519566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(A, &dofA)); 14529566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(B, &dofB)); 14534f9ab2b4SJed Brown for (PetscInt d = 0; d < dimA; d++) { 1454ad540459SPierre Jolivet if (dofA[d] != dofB[d]) PetscFunctionReturn(0); 14554f9ab2b4SJed Brown } 14564f9ab2b4SJed Brown 14579566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(A, &quadA, &matA)); 14589566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(B, &quadB, &matB)); 14594f9ab2b4SJed Brown if (!quadA && !quadB) { 14604f9ab2b4SJed Brown *equal = PETSC_TRUE; 14614f9ab2b4SJed Brown } else if (quadA && quadB) { 14629566063dSJacob Faibussowitsch PetscCall(PetscQuadratureEqual(quadA, quadB, equal)); 14634f9ab2b4SJed Brown if (*equal == PETSC_FALSE) PetscFunctionReturn(0); 14644f9ab2b4SJed Brown if (!matA && !matB) PetscFunctionReturn(0); 14659566063dSJacob Faibussowitsch if (matA && matB) PetscCall(MatEqual(matA, matB, equal)); 14664f9ab2b4SJed Brown else *equal = PETSC_FALSE; 14674f9ab2b4SJed Brown } 14684f9ab2b4SJed Brown PetscFunctionReturn(0); 14694f9ab2b4SJed Brown } 14704f9ab2b4SJed Brown 147120cf1dd8SToby Isaac /*@C 147220cf1dd8SToby Isaac PetscDualSpaceApplyFVM - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional at the cell centroid. 147320cf1dd8SToby Isaac 147420cf1dd8SToby Isaac Input Parameters: 1475*dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 147620cf1dd8SToby Isaac . f - The basis functional index 147720cf1dd8SToby Isaac . time - The time 147820cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we currently just use the centroid 147920cf1dd8SToby Isaac . Nc - The number of components for the function 148020cf1dd8SToby Isaac . func - The input function 148120cf1dd8SToby Isaac - ctx - A context for the function 148220cf1dd8SToby Isaac 148320cf1dd8SToby Isaac Output Parameter: 148420cf1dd8SToby Isaac . value - The output value (scalar) 148520cf1dd8SToby Isaac 1486*dce8aebaSBarry Smith Calling Sequence of func: 1487*dce8aebaSBarry Smith .vb 1488*dce8aebaSBarry Smith func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt numComponents, PetscScalar values[], void *ctx) 1489*dce8aebaSBarry Smith .ve 1490*dce8aebaSBarry Smith Level: advanced 149120cf1dd8SToby Isaac 1492*dce8aebaSBarry Smith Note: 1493*dce8aebaSBarry Smith The idea is to evaluate the functional as an integral $ n(f) = \int dx n(x) . f(x)$ where both n and f have Nc components. 149420cf1dd8SToby Isaac 1495*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 149620cf1dd8SToby Isaac @*/ 1497d71ae5a4SJacob 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) 1498d71ae5a4SJacob Faibussowitsch { 149920cf1dd8SToby Isaac DM dm; 150020cf1dd8SToby Isaac PetscQuadrature n; 150120cf1dd8SToby Isaac const PetscReal *points, *weights; 150220cf1dd8SToby Isaac PetscScalar *val; 150320cf1dd8SToby Isaac PetscInt dimEmbed, qNc, c, Nq, q; 150420cf1dd8SToby Isaac 150520cf1dd8SToby Isaac PetscFunctionBegin; 150620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1507dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 15089566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 15099566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 15109566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 15119566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, NULL, &qNc, &Nq, &points, &weights)); 151263a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 15139566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 151420cf1dd8SToby Isaac *value = 0.; 151520cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 15169566063dSJacob Faibussowitsch PetscCall((*func)(dimEmbed, time, cgeom->centroid, Nc, val, ctx)); 1517ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) *value += val[c] * weights[q * Nc + c]; 151820cf1dd8SToby Isaac } 15199566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 152020cf1dd8SToby Isaac PetscFunctionReturn(0); 152120cf1dd8SToby Isaac } 152220cf1dd8SToby Isaac 152320cf1dd8SToby Isaac /*@ 152420cf1dd8SToby Isaac PetscDualSpaceGetHeightSubspace - Get the subset of the dual space basis that is supported on a mesh point of a 152520cf1dd8SToby Isaac given height. This assumes that the reference cell is symmetric over points of this height. 152620cf1dd8SToby Isaac 152720cf1dd8SToby Isaac Not collective 152820cf1dd8SToby Isaac 152920cf1dd8SToby Isaac Input Parameters: 1530*dce8aebaSBarry Smith + sp - the `PetscDualSpace` object 153120cf1dd8SToby Isaac - height - the height of the mesh point for which the subspace is desired 153220cf1dd8SToby Isaac 153320cf1dd8SToby Isaac Output Parameter: 153420cf1dd8SToby Isaac . subsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 153520cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 153620cf1dd8SToby Isaac 153720cf1dd8SToby Isaac Level: advanced 153820cf1dd8SToby Isaac 1539*dce8aebaSBarry Smith Notes: 1540*dce8aebaSBarry Smith If the dual space is not defined on mesh points of the given height (e.g. if the space is discontinuous and 1541*dce8aebaSBarry Smith pointwise values are not defined on the element boundaries), or if the implementation of `PetscDualSpace` does not 1542*dce8aebaSBarry Smith support extracting subspaces, then NULL is returned. 1543*dce8aebaSBarry Smith 1544*dce8aebaSBarry Smith This does not increment the reference count on the returned dual space, and the user should not destroy it. 1545*dce8aebaSBarry Smith 1546*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscSpaceGetHeightSubspace()`, `PetscDualSpace`, `PetscDualSpaceGetPointSubspace()` 154720cf1dd8SToby Isaac @*/ 1548d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetHeightSubspace(PetscDualSpace sp, PetscInt height, PetscDualSpace *subsp) 1549d71ae5a4SJacob Faibussowitsch { 1550b4457527SToby Isaac PetscInt depth = -1, cStart, cEnd; 1551b4457527SToby Isaac DM dm; 155220cf1dd8SToby Isaac 155320cf1dd8SToby Isaac PetscFunctionBegin; 155420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1555064a246eSJacob Faibussowitsch PetscValidPointer(subsp, 3); 155608401ef6SPierre 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"); 155720cf1dd8SToby Isaac *subsp = NULL; 1558b4457527SToby Isaac dm = sp->dm; 15599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 15601dca8a05SBarry Smith PetscCheck(height >= 0 && height <= depth, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid height"); 15619566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1562b4457527SToby Isaac if (height == 0 && cEnd == cStart + 1) { 1563b4457527SToby Isaac *subsp = sp; 1564b4457527SToby Isaac PetscFunctionReturn(0); 1565b4457527SToby Isaac } 1566b4457527SToby Isaac if (!sp->heightSpaces) { 1567b4457527SToby Isaac PetscInt h; 15689566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth + 1, &(sp->heightSpaces))); 1569b4457527SToby Isaac 1570b4457527SToby Isaac for (h = 0; h <= depth; h++) { 1571b4457527SToby Isaac if (h == 0 && cEnd == cStart + 1) continue; 15729566063dSJacob Faibussowitsch if (sp->ops->createheightsubspace) PetscCall((*sp->ops->createheightsubspace)(sp, height, &(sp->heightSpaces[h]))); 1573b4457527SToby Isaac else if (sp->pointSpaces) { 1574b4457527SToby Isaac PetscInt hStart, hEnd; 1575b4457527SToby Isaac 15769566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &hStart, &hEnd)); 1577b4457527SToby Isaac if (hEnd > hStart) { 1578665f567fSMatthew G. Knepley const char *name; 1579665f567fSMatthew G. Knepley 15809566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(sp->pointSpaces[hStart]))); 1581665f567fSMatthew G. Knepley if (sp->pointSpaces[hStart]) { 15829566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name)); 15839566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sp->pointSpaces[hStart], name)); 1584665f567fSMatthew G. Knepley } 1585b4457527SToby Isaac sp->heightSpaces[h] = sp->pointSpaces[hStart]; 1586b4457527SToby Isaac } 1587b4457527SToby Isaac } 1588b4457527SToby Isaac } 1589b4457527SToby Isaac } 1590b4457527SToby Isaac *subsp = sp->heightSpaces[height]; 159120cf1dd8SToby Isaac PetscFunctionReturn(0); 159220cf1dd8SToby Isaac } 159320cf1dd8SToby Isaac 159420cf1dd8SToby Isaac /*@ 159520cf1dd8SToby Isaac PetscDualSpaceGetPointSubspace - Get the subset of the dual space basis that is supported on a particular mesh point. 159620cf1dd8SToby Isaac 159720cf1dd8SToby Isaac Not collective 159820cf1dd8SToby Isaac 159920cf1dd8SToby Isaac Input Parameters: 1600*dce8aebaSBarry Smith + sp - the `PetscDualSpace` object 160120cf1dd8SToby Isaac - point - the point (in the dual space's DM) for which the subspace is desired 160220cf1dd8SToby Isaac 160320cf1dd8SToby Isaac Output Parameters: 1604*dce8aebaSBarry Smith bdsp - the subspace. The functionals in the subspace are with respect to the intrinsic geometry of the 160520cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 160620cf1dd8SToby Isaac 160720cf1dd8SToby Isaac Level: advanced 160820cf1dd8SToby Isaac 1609*dce8aebaSBarry Smith Notes: 1610*dce8aebaSBarry Smith If the dual space is not defined on the mesh point (e.g. if the space is discontinuous and pointwise values are not 1611*dce8aebaSBarry Smith defined on the element boundaries), or if the implementation of `PetscDualSpace` does not support extracting 1612*dce8aebaSBarry Smith subspaces, then NULL is returned. 1613*dce8aebaSBarry Smith 1614*dce8aebaSBarry Smith This does not increment the reference count on the returned dual space, and the user should not destroy it. 1615*dce8aebaSBarry Smith 1616*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetHeightSubspace()` 161720cf1dd8SToby Isaac @*/ 1618d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetPointSubspace(PetscDualSpace sp, PetscInt point, PetscDualSpace *bdsp) 1619d71ae5a4SJacob Faibussowitsch { 1620b4457527SToby Isaac PetscInt pStart = 0, pEnd = 0, cStart, cEnd; 1621b4457527SToby Isaac DM dm; 162220cf1dd8SToby Isaac 162320cf1dd8SToby Isaac PetscFunctionBegin; 162420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1625064a246eSJacob Faibussowitsch PetscValidPointer(bdsp, 3); 162620cf1dd8SToby Isaac *bdsp = NULL; 1627b4457527SToby Isaac dm = sp->dm; 16289566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 16291dca8a05SBarry Smith PetscCheck(point >= pStart && point <= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid point"); 16309566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1631b4457527SToby 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 */ 1632b4457527SToby Isaac *bdsp = sp; 1633b4457527SToby Isaac PetscFunctionReturn(0); 1634b4457527SToby Isaac } 1635b4457527SToby Isaac if (!sp->pointSpaces) { 1636b4457527SToby Isaac PetscInt p; 16379566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &(sp->pointSpaces))); 163820cf1dd8SToby Isaac 1639b4457527SToby Isaac for (p = 0; p < pEnd - pStart; p++) { 1640b4457527SToby Isaac if (p + pStart == cStart && cEnd == cStart + 1) continue; 16419566063dSJacob Faibussowitsch if (sp->ops->createpointsubspace) PetscCall((*sp->ops->createpointsubspace)(sp, p + pStart, &(sp->pointSpaces[p]))); 1642b4457527SToby Isaac else if (sp->heightSpaces || sp->ops->createheightsubspace) { 1643b4457527SToby Isaac PetscInt dim, depth, height; 1644b4457527SToby Isaac DMLabel label; 1645b4457527SToby Isaac 16469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &dim)); 16479566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 16489566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, p + pStart, &depth)); 164920cf1dd8SToby Isaac height = dim - depth; 16509566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(sp, height, &(sp->pointSpaces[p]))); 16519566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sp->pointSpaces[p])); 165220cf1dd8SToby Isaac } 1653b4457527SToby Isaac } 1654b4457527SToby Isaac } 1655b4457527SToby Isaac *bdsp = sp->pointSpaces[point - pStart]; 165620cf1dd8SToby Isaac PetscFunctionReturn(0); 165720cf1dd8SToby Isaac } 165820cf1dd8SToby Isaac 16596f905325SMatthew G. Knepley /*@C 16606f905325SMatthew G. Knepley PetscDualSpaceGetSymmetries - Returns a description of the symmetries of this basis 16616f905325SMatthew G. Knepley 16626f905325SMatthew G. Knepley Not collective 16636f905325SMatthew G. Knepley 16646f905325SMatthew G. Knepley Input Parameter: 1665*dce8aebaSBarry Smith . sp - the `PetscDualSpace` object 16666f905325SMatthew G. Knepley 16676f905325SMatthew G. Knepley Output Parameters: 1668b4457527SToby Isaac + perms - Permutations of the interior degrees of freedom, parameterized by the point orientation 1669b4457527SToby Isaac - flips - Sign reversal of the interior degrees of freedom, parameterized by the point orientation 16706f905325SMatthew G. Knepley 16716f905325SMatthew G. Knepley Level: developer 16726f905325SMatthew G. Knepley 1673*dce8aebaSBarry Smith Note: 1674*dce8aebaSBarry Smith The permutation and flip arrays are organized in the following way 1675*dce8aebaSBarry Smith .vb 1676*dce8aebaSBarry Smith perms[p][ornt][dof # on point] = new local dof # 1677*dce8aebaSBarry Smith flips[p][ornt][dof # on point] = reversal or not 1678*dce8aebaSBarry Smith .ve 1679*dce8aebaSBarry Smith 1680*dce8aebaSBarry Smith .seealso: `PetscDualSpace` 16816f905325SMatthew G. Knepley @*/ 1682d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetSymmetries(PetscDualSpace sp, const PetscInt ****perms, const PetscScalar ****flips) 1683d71ae5a4SJacob Faibussowitsch { 16846f905325SMatthew G. Knepley PetscFunctionBegin; 16856f905325SMatthew G. Knepley PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 16869371c9d4SSatish Balay if (perms) { 16879371c9d4SSatish Balay PetscValidPointer(perms, 2); 16889371c9d4SSatish Balay *perms = NULL; 16899371c9d4SSatish Balay } 16909371c9d4SSatish Balay if (flips) { 16919371c9d4SSatish Balay PetscValidPointer(flips, 3); 16929371c9d4SSatish Balay *flips = NULL; 16939371c9d4SSatish Balay } 16949566063dSJacob Faibussowitsch if (sp->ops->getsymmetries) PetscCall((sp->ops->getsymmetries)(sp, perms, flips)); 16956f905325SMatthew G. Knepley PetscFunctionReturn(0); 16966f905325SMatthew G. Knepley } 16974bee2e38SMatthew G. Knepley 16984bee2e38SMatthew G. Knepley /*@ 1699b4457527SToby Isaac PetscDualSpaceGetFormDegree - Get the form degree k for the k-form the describes the pushforwards/pullbacks of this 1700b4457527SToby Isaac dual space's functionals. 1701b4457527SToby Isaac 1702b4457527SToby Isaac Input Parameter: 1703*dce8aebaSBarry Smith . dsp - The `PetscDualSpace` 1704b4457527SToby Isaac 1705b4457527SToby Isaac Output Parameter: 1706b4457527SToby 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 1707b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1708b4457527SToby 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). 1709b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1710b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1711b4457527SToby Isaac but are stored as 1-forms. 1712b4457527SToby Isaac 1713b4457527SToby Isaac Level: developer 1714b4457527SToby Isaac 1715*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 1716b4457527SToby Isaac @*/ 1717d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetFormDegree(PetscDualSpace dsp, PetscInt *k) 1718d71ae5a4SJacob Faibussowitsch { 1719b4457527SToby Isaac PetscFunctionBeginHot; 1720b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1721dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1722b4457527SToby Isaac *k = dsp->k; 1723b4457527SToby Isaac PetscFunctionReturn(0); 1724b4457527SToby Isaac } 1725b4457527SToby Isaac 1726b4457527SToby Isaac /*@ 1727b4457527SToby Isaac PetscDualSpaceSetFormDegree - Set the form degree k for the k-form the describes the pushforwards/pullbacks of this 1728b4457527SToby Isaac dual space's functionals. 1729b4457527SToby Isaac 1730d8d19677SJose E. Roman Input Parameters: 1731*dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 1732b4457527SToby 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 1733b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1734b4457527SToby 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). 1735b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1736b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1737b4457527SToby Isaac but are stored as 1-forms. 1738b4457527SToby Isaac 1739b4457527SToby Isaac Level: developer 1740b4457527SToby Isaac 1741*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 1742b4457527SToby Isaac @*/ 1743d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetFormDegree(PetscDualSpace dsp, PetscInt k) 1744d71ae5a4SJacob Faibussowitsch { 1745b4457527SToby Isaac PetscInt dim; 1746b4457527SToby Isaac 1747b4457527SToby Isaac PetscFunctionBeginHot; 1748b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 174928b400f6SJacob Faibussowitsch PetscCheck(!dsp->setupcalled, PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 1750b4457527SToby Isaac dim = dsp->dm->dim; 17511dca8a05SBarry 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); 1752b4457527SToby Isaac dsp->k = k; 1753b4457527SToby Isaac PetscFunctionReturn(0); 1754b4457527SToby Isaac } 1755b4457527SToby Isaac 1756b4457527SToby Isaac /*@ 17574bee2e38SMatthew G. Knepley PetscDualSpaceGetDeRahm - Get the k-simplex associated with the functionals in this dual space 17584bee2e38SMatthew G. Knepley 17594bee2e38SMatthew G. Knepley Input Parameter: 1760*dce8aebaSBarry Smith . dsp - The `PetscDualSpace` 17614bee2e38SMatthew G. Knepley 17624bee2e38SMatthew G. Knepley Output Parameter: 17634bee2e38SMatthew G. Knepley . k - The simplex dimension 17644bee2e38SMatthew G. Knepley 1765a4ce7ad1SMatthew G. Knepley Level: developer 17664bee2e38SMatthew G. Knepley 1767*dce8aebaSBarry Smith Note: 1768*dce8aebaSBarry Smith Currently supported values are 1769*dce8aebaSBarry Smith .vb 1770*dce8aebaSBarry Smith 0: These are H_1 methods that only transform coordinates 1771*dce8aebaSBarry Smith 1: These are Hcurl methods that transform functions using the covariant Piola transform (COVARIANT_PIOLA_TRANSFORM) 1772*dce8aebaSBarry Smith 2: These are the same as 1 1773*dce8aebaSBarry Smith 3: These are Hdiv methods that transform functions using the contravariant Piola transform (CONTRAVARIANT_PIOLA_TRANSFORM) 1774*dce8aebaSBarry Smith .ve 17754bee2e38SMatthew G. Knepley 1776*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 17774bee2e38SMatthew G. Knepley @*/ 1778d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDeRahm(PetscDualSpace dsp, PetscInt *k) 1779d71ae5a4SJacob Faibussowitsch { 1780b4457527SToby Isaac PetscInt dim; 1781b4457527SToby Isaac 17824bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 17834bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1784dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1785b4457527SToby Isaac dim = dsp->dm->dim; 1786b4457527SToby Isaac if (!dsp->k) *k = IDENTITY_TRANSFORM; 1787b4457527SToby Isaac else if (dsp->k == 1) *k = COVARIANT_PIOLA_TRANSFORM; 1788b4457527SToby Isaac else if (dsp->k == -(dim - 1)) *k = CONTRAVARIANT_PIOLA_TRANSFORM; 1789b4457527SToby Isaac else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unsupported transformation"); 17904bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 17914bee2e38SMatthew G. Knepley } 17924bee2e38SMatthew G. Knepley 17934bee2e38SMatthew G. Knepley /*@C 17944bee2e38SMatthew G. Knepley PetscDualSpaceTransform - Transform the function values 17954bee2e38SMatthew G. Knepley 17964bee2e38SMatthew G. Knepley Input Parameters: 1797*dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 17984bee2e38SMatthew G. Knepley . trans - The type of transform 17994bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18004bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18014bee2e38SMatthew G. Knepley . Nv - The number of function samples 18024bee2e38SMatthew G. Knepley . Nc - The number of function components 18034bee2e38SMatthew G. Knepley - vals - The function values 18044bee2e38SMatthew G. Knepley 18054bee2e38SMatthew G. Knepley Output Parameter: 18064bee2e38SMatthew G. Knepley . vals - The transformed function values 18074bee2e38SMatthew G. Knepley 1808a4ce7ad1SMatthew G. Knepley Level: intermediate 18094bee2e38SMatthew G. Knepley 1810*dce8aebaSBarry Smith Note: 1811*dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18122edcad52SToby Isaac 1813*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransformGradient()`, `PetscDualSpaceTransformHessian()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 18144bee2e38SMatthew G. Knepley @*/ 1815d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransform(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 1816d71ae5a4SJacob Faibussowitsch { 1817b4457527SToby Isaac PetscReal Jstar[9] = {0}; 1818b4457527SToby Isaac PetscInt dim, v, c, Nk; 18194bee2e38SMatthew G. Knepley 18204bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18214bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18224bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1823dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 1824b4457527SToby Isaac /* TODO: not handling dimEmbed != dim right now */ 18252ae266adSMatthew G. Knepley dim = dsp->dm->dim; 1826b4457527SToby Isaac /* No change needed for 0-forms */ 1827b4457527SToby Isaac if (!dsp->k) PetscFunctionReturn(0); 18289566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(dsp->k), &Nk)); 1829b4457527SToby Isaac /* TODO: use fegeom->isAffine */ 18309566063dSJacob Faibussowitsch PetscCall(PetscDTAltVPullbackMatrix(dim, dim, isInverse ? fegeom->J : fegeom->invJ, dsp->k, Jstar)); 18314bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1832b4457527SToby Isaac switch (Nk) { 1833b4457527SToby Isaac case 1: 1834b4457527SToby Isaac for (c = 0; c < Nc; c++) vals[v * Nc + c] *= Jstar[0]; 18354bee2e38SMatthew G. Knepley break; 1836b4457527SToby Isaac case 2: 1837b4457527SToby Isaac for (c = 0; c < Nc; c += 2) DMPlex_Mult2DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]); 18384bee2e38SMatthew G. Knepley break; 1839b4457527SToby Isaac case 3: 1840b4457527SToby Isaac for (c = 0; c < Nc; c += 3) DMPlex_Mult3DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]); 1841b4457527SToby Isaac break; 1842d71ae5a4SJacob Faibussowitsch default: 1843d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported form size %" PetscInt_FMT " for transformation", Nk); 1844b4457527SToby Isaac } 18454bee2e38SMatthew G. Knepley } 18464bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 18474bee2e38SMatthew G. Knepley } 1848b4457527SToby Isaac 18494bee2e38SMatthew G. Knepley /*@C 18504bee2e38SMatthew G. Knepley PetscDualSpaceTransformGradient - Transform the function gradient values 18514bee2e38SMatthew G. Knepley 18524bee2e38SMatthew G. Knepley Input Parameters: 1853*dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 18544bee2e38SMatthew G. Knepley . trans - The type of transform 18554bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18564bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18574bee2e38SMatthew G. Knepley . Nv - The number of function gradient samples 18584bee2e38SMatthew G. Knepley . Nc - The number of function components 18594bee2e38SMatthew G. Knepley - vals - The function gradient values 18604bee2e38SMatthew G. Knepley 18614bee2e38SMatthew G. Knepley Output Parameter: 1862f9244615SMatthew G. Knepley . vals - The transformed function gradient values 18634bee2e38SMatthew G. Knepley 1864a4ce7ad1SMatthew G. Knepley Level: intermediate 18654bee2e38SMatthew G. Knepley 1866*dce8aebaSBarry Smith Note: 1867*dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18682edcad52SToby Isaac 1869*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 18704bee2e38SMatthew G. Knepley @*/ 1871d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransformGradient(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 1872d71ae5a4SJacob Faibussowitsch { 187327f02ce8SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 187427f02ce8SMatthew G. Knepley PetscInt v, c, d; 18754bee2e38SMatthew G. Knepley 18764bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18774bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18784bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1879dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 188027f02ce8SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 188163a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 188227f02ce8SMatthew G. Knepley #endif 18834bee2e38SMatthew G. Knepley /* Transform gradient */ 188427f02ce8SMatthew G. Knepley if (dim == dE) { 18854bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 18864bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 18879371c9d4SSatish Balay switch (dim) { 1888d71ae5a4SJacob Faibussowitsch case 1: 1889d71ae5a4SJacob Faibussowitsch vals[(v * Nc + c) * dim] *= fegeom->invJ[0]; 1890d71ae5a4SJacob Faibussowitsch break; 1891d71ae5a4SJacob Faibussowitsch case 2: 1892d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]); 1893d71ae5a4SJacob Faibussowitsch break; 1894d71ae5a4SJacob Faibussowitsch case 3: 1895d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]); 1896d71ae5a4SJacob Faibussowitsch break; 1897d71ae5a4SJacob Faibussowitsch default: 1898d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 18994bee2e38SMatthew G. Knepley } 19004bee2e38SMatthew G. Knepley } 19014bee2e38SMatthew G. Knepley } 190227f02ce8SMatthew G. Knepley } else { 190327f02ce8SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1904ad540459SPierre 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]); 190527f02ce8SMatthew G. Knepley } 190627f02ce8SMatthew G. Knepley } 19074bee2e38SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 19084bee2e38SMatthew G. Knepley if (Nc == 1 || Nc != dim) PetscFunctionReturn(0); 19094bee2e38SMatthew G. Knepley switch (trans) { 1910d71ae5a4SJacob Faibussowitsch case IDENTITY_TRANSFORM: 1911d71ae5a4SJacob Faibussowitsch break; 19124bee2e38SMatthew G. Knepley case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 19134bee2e38SMatthew G. Knepley if (isInverse) { 19144bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19154bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19169371c9d4SSatish Balay switch (dim) { 1917d71ae5a4SJacob Faibussowitsch case 2: 1918d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1919d71ae5a4SJacob Faibussowitsch break; 1920d71ae5a4SJacob Faibussowitsch case 3: 1921d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1922d71ae5a4SJacob Faibussowitsch break; 1923d71ae5a4SJacob Faibussowitsch default: 1924d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19254bee2e38SMatthew G. Knepley } 19264bee2e38SMatthew G. Knepley } 19274bee2e38SMatthew G. Knepley } 19284bee2e38SMatthew G. Knepley } else { 19294bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19304bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19319371c9d4SSatish Balay switch (dim) { 1932d71ae5a4SJacob Faibussowitsch case 2: 1933d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1934d71ae5a4SJacob Faibussowitsch break; 1935d71ae5a4SJacob Faibussowitsch case 3: 1936d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1937d71ae5a4SJacob Faibussowitsch break; 1938d71ae5a4SJacob Faibussowitsch default: 1939d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19404bee2e38SMatthew G. Knepley } 19414bee2e38SMatthew G. Knepley } 19424bee2e38SMatthew G. Knepley } 19434bee2e38SMatthew G. Knepley } 19444bee2e38SMatthew G. Knepley break; 19454bee2e38SMatthew G. Knepley case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 19464bee2e38SMatthew G. Knepley if (isInverse) { 19474bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19484bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19499371c9d4SSatish Balay switch (dim) { 1950d71ae5a4SJacob Faibussowitsch case 2: 1951d71ae5a4SJacob Faibussowitsch DMPlex_Mult2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1952d71ae5a4SJacob Faibussowitsch break; 1953d71ae5a4SJacob Faibussowitsch case 3: 1954d71ae5a4SJacob Faibussowitsch DMPlex_Mult3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1955d71ae5a4SJacob Faibussowitsch break; 1956d71ae5a4SJacob Faibussowitsch default: 1957d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19584bee2e38SMatthew G. Knepley } 19594bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] *= fegeom->detJ[0]; 19604bee2e38SMatthew G. Knepley } 19614bee2e38SMatthew G. Knepley } 19624bee2e38SMatthew G. Knepley } else { 19634bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19644bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19659371c9d4SSatish Balay switch (dim) { 1966d71ae5a4SJacob Faibussowitsch case 2: 1967d71ae5a4SJacob Faibussowitsch DMPlex_Mult2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1968d71ae5a4SJacob Faibussowitsch break; 1969d71ae5a4SJacob Faibussowitsch case 3: 1970d71ae5a4SJacob Faibussowitsch DMPlex_Mult3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1971d71ae5a4SJacob Faibussowitsch break; 1972d71ae5a4SJacob Faibussowitsch default: 1973d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19744bee2e38SMatthew G. Knepley } 19754bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] /= fegeom->detJ[0]; 19764bee2e38SMatthew G. Knepley } 19774bee2e38SMatthew G. Knepley } 19784bee2e38SMatthew G. Knepley } 19794bee2e38SMatthew G. Knepley break; 19804bee2e38SMatthew G. Knepley } 19814bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 19824bee2e38SMatthew G. Knepley } 19834bee2e38SMatthew G. Knepley 19844bee2e38SMatthew G. Knepley /*@C 1985f9244615SMatthew G. Knepley PetscDualSpaceTransformHessian - Transform the function Hessian values 1986f9244615SMatthew G. Knepley 1987f9244615SMatthew G. Knepley Input Parameters: 1988*dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 1989f9244615SMatthew G. Knepley . trans - The type of transform 1990f9244615SMatthew G. Knepley . isInverse - Flag to invert the transform 1991f9244615SMatthew G. Knepley . fegeom - The cell geometry 1992f9244615SMatthew G. Knepley . Nv - The number of function Hessian samples 1993f9244615SMatthew G. Knepley . Nc - The number of function components 1994f9244615SMatthew G. Knepley - vals - The function gradient values 1995f9244615SMatthew G. Knepley 1996f9244615SMatthew G. Knepley Output Parameter: 1997f9244615SMatthew G. Knepley . vals - The transformed function Hessian values 1998f9244615SMatthew G. Knepley 1999f9244615SMatthew G. Knepley Level: intermediate 2000f9244615SMatthew G. Knepley 2001*dce8aebaSBarry Smith Note: 2002*dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2003f9244615SMatthew G. Knepley 2004*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 2005f9244615SMatthew G. Knepley @*/ 2006d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransformHessian(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 2007d71ae5a4SJacob Faibussowitsch { 2008f9244615SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 2009f9244615SMatthew G. Knepley PetscInt v, c; 2010f9244615SMatthew G. Knepley 2011f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2012f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2013f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 4); 2014dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 2015f9244615SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 201663a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 2017f9244615SMatthew G. Knepley #endif 2018f9244615SMatthew G. Knepley /* Transform Hessian: J^{-T}_{ik} J^{-T}_{jl} H(f)_{kl} = J^{-T}_{ik} H(f)_{kl} J^{-1}_{lj} */ 2019f9244615SMatthew G. Knepley if (dim == dE) { 2020f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2021f9244615SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 20229371c9d4SSatish Balay switch (dim) { 2023d71ae5a4SJacob Faibussowitsch case 1: 2024d71ae5a4SJacob Faibussowitsch vals[(v * Nc + c) * dim * dim] *= PetscSqr(fegeom->invJ[0]); 2025d71ae5a4SJacob Faibussowitsch break; 2026d71ae5a4SJacob Faibussowitsch case 2: 2027d71ae5a4SJacob Faibussowitsch DMPlex_PTAP2DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]); 2028d71ae5a4SJacob Faibussowitsch break; 2029d71ae5a4SJacob Faibussowitsch case 3: 2030d71ae5a4SJacob Faibussowitsch DMPlex_PTAP3DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]); 2031d71ae5a4SJacob Faibussowitsch break; 2032d71ae5a4SJacob Faibussowitsch default: 2033d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 2034f9244615SMatthew G. Knepley } 2035f9244615SMatthew G. Knepley } 2036f9244615SMatthew G. Knepley } 2037f9244615SMatthew G. Knepley } else { 2038f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2039ad540459SPierre 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]); 2040f9244615SMatthew G. Knepley } 2041f9244615SMatthew G. Knepley } 2042f9244615SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 2043f9244615SMatthew G. Knepley if (Nc == 1 || Nc != dim) PetscFunctionReturn(0); 2044f9244615SMatthew G. Knepley switch (trans) { 2045d71ae5a4SJacob Faibussowitsch case IDENTITY_TRANSFORM: 2046d71ae5a4SJacob Faibussowitsch break; 2047d71ae5a4SJacob Faibussowitsch case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 2048d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2049d71ae5a4SJacob Faibussowitsch case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 2050d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2051f9244615SMatthew G. Knepley } 2052f9244615SMatthew G. Knepley PetscFunctionReturn(0); 2053f9244615SMatthew G. Knepley } 2054f9244615SMatthew G. Knepley 2055f9244615SMatthew G. Knepley /*@C 20564bee2e38SMatthew 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. 20574bee2e38SMatthew G. Knepley 20584bee2e38SMatthew G. Knepley Input Parameters: 2059*dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 20604bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 20614bee2e38SMatthew G. Knepley . Nq - The number of function samples 20624bee2e38SMatthew G. Knepley . Nc - The number of function components 20634bee2e38SMatthew G. Knepley - pointEval - The function values 20644bee2e38SMatthew G. Knepley 20654bee2e38SMatthew G. Knepley Output Parameter: 20664bee2e38SMatthew G. Knepley . pointEval - The transformed function values 20674bee2e38SMatthew G. Knepley 20684bee2e38SMatthew G. Knepley Level: advanced 20694bee2e38SMatthew G. Knepley 2070*dce8aebaSBarry Smith Notes: 2071*dce8aebaSBarry Smith Functions transform in a complementary way (pushforward) to functionals, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex. 20724bee2e38SMatthew G. Knepley 2073*dce8aebaSBarry Smith This only handles tranformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 20742edcad52SToby Isaac 2075*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 20764bee2e38SMatthew G. Knepley @*/ 2077d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePullback(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2078d71ae5a4SJacob Faibussowitsch { 20794bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2080b4457527SToby Isaac PetscInt k; 20814bee2e38SMatthew G. Knepley 20824bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 20834bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 20844bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2085dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 20864bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 20874bee2e38SMatthew G. Knepley This determines their transformation properties. */ 20889566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 20899371c9d4SSatish Balay switch (k) { 2090d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2091d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2092d71ae5a4SJacob Faibussowitsch break; 2093d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2094d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2095d71ae5a4SJacob Faibussowitsch break; 2096b4457527SToby Isaac case 2: 2097d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2098d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2099d71ae5a4SJacob Faibussowitsch break; 2100d71ae5a4SJacob Faibussowitsch default: 2101d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 21024bee2e38SMatthew G. Knepley } 21039566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_TRUE, fegeom, Nq, Nc, pointEval)); 21044bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 21054bee2e38SMatthew G. Knepley } 21064bee2e38SMatthew G. Knepley 21074bee2e38SMatthew G. Knepley /*@C 21084bee2e38SMatthew 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. 21094bee2e38SMatthew G. Knepley 21104bee2e38SMatthew G. Knepley Input Parameters: 2111*dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 21124bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21134bee2e38SMatthew G. Knepley . Nq - The number of function samples 21144bee2e38SMatthew G. Knepley . Nc - The number of function components 21154bee2e38SMatthew G. Knepley - pointEval - The function values 21164bee2e38SMatthew G. Knepley 21174bee2e38SMatthew G. Knepley Output Parameter: 21184bee2e38SMatthew G. Knepley . pointEval - The transformed function values 21194bee2e38SMatthew G. Knepley 21204bee2e38SMatthew G. Knepley Level: advanced 21214bee2e38SMatthew G. Knepley 2122*dce8aebaSBarry Smith Notes: 2123*dce8aebaSBarry Smith Functionals transform in a complementary way (pullback) to functions, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex. 21244bee2e38SMatthew G. Knepley 2125*dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21262edcad52SToby Isaac 2127*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 21284bee2e38SMatthew G. Knepley @*/ 2129d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforward(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2130d71ae5a4SJacob Faibussowitsch { 21314bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2132b4457527SToby Isaac PetscInt k; 21334bee2e38SMatthew G. Knepley 21344bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21354bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 21364bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2137dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 21384bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 21394bee2e38SMatthew G. Knepley This determines their transformation properties. */ 21409566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 21419371c9d4SSatish Balay switch (k) { 2142d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2143d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2144d71ae5a4SJacob Faibussowitsch break; 2145d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2146d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2147d71ae5a4SJacob Faibussowitsch break; 2148b4457527SToby Isaac case 2: 2149d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2150d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2151d71ae5a4SJacob Faibussowitsch break; 2152d71ae5a4SJacob Faibussowitsch default: 2153d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 21544bee2e38SMatthew G. Knepley } 21559566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 21564bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 21574bee2e38SMatthew G. Knepley } 21584bee2e38SMatthew G. Knepley 21594bee2e38SMatthew G. Knepley /*@C 21604bee2e38SMatthew 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. 21614bee2e38SMatthew G. Knepley 21624bee2e38SMatthew G. Knepley Input Parameters: 2163*dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 21644bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21654bee2e38SMatthew G. Knepley . Nq - The number of function gradient samples 21664bee2e38SMatthew G. Knepley . Nc - The number of function components 21674bee2e38SMatthew G. Knepley - pointEval - The function gradient values 21684bee2e38SMatthew G. Knepley 21694bee2e38SMatthew G. Knepley Output Parameter: 21704bee2e38SMatthew G. Knepley . pointEval - The transformed function gradient values 21714bee2e38SMatthew G. Knepley 21724bee2e38SMatthew G. Knepley Level: advanced 21734bee2e38SMatthew G. Knepley 2174*dce8aebaSBarry Smith Notes: 2175*dce8aebaSBarry Smith Functionals transform in a complementary way (pullback) to functions, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex. 21764bee2e38SMatthew G. Knepley 2177*dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21782edcad52SToby Isaac 2179*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2180dc0529c6SBarry Smith @*/ 2181d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforwardGradient(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2182d71ae5a4SJacob Faibussowitsch { 21834bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2184b4457527SToby Isaac PetscInt k; 21854bee2e38SMatthew G. Knepley 21864bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21874bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 21884bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2189dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 21904bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 21914bee2e38SMatthew G. Knepley This determines their transformation properties. */ 21929566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 21939371c9d4SSatish Balay switch (k) { 2194d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2195d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2196d71ae5a4SJacob Faibussowitsch break; 2197d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2198d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2199d71ae5a4SJacob Faibussowitsch break; 2200b4457527SToby Isaac case 2: 2201d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2202d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2203d71ae5a4SJacob Faibussowitsch break; 2204d71ae5a4SJacob Faibussowitsch default: 2205d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 22064bee2e38SMatthew G. Knepley } 22079566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformGradient(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 22084bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 22094bee2e38SMatthew G. Knepley } 2210f9244615SMatthew G. Knepley 2211f9244615SMatthew G. Knepley /*@C 2212f9244615SMatthew 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. 2213f9244615SMatthew G. Knepley 2214f9244615SMatthew G. Knepley Input Parameters: 2215*dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 2216f9244615SMatthew G. Knepley . fegeom - The geometry for this cell 2217f9244615SMatthew G. Knepley . Nq - The number of function Hessian samples 2218f9244615SMatthew G. Knepley . Nc - The number of function components 2219f9244615SMatthew G. Knepley - pointEval - The function gradient values 2220f9244615SMatthew G. Knepley 2221f9244615SMatthew G. Knepley Output Parameter: 2222f9244615SMatthew G. Knepley . pointEval - The transformed function Hessian values 2223f9244615SMatthew G. Knepley 2224f9244615SMatthew G. Knepley Level: advanced 2225f9244615SMatthew G. Knepley 2226*dce8aebaSBarry Smith Notes: 2227*dce8aebaSBarry Smith Functionals transform in a complementary way (pullback) to functions, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex. 2228f9244615SMatthew G. Knepley 2229*dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2230f9244615SMatthew G. Knepley 2231*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2232f9244615SMatthew G. Knepley @*/ 2233d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforwardHessian(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2234d71ae5a4SJacob Faibussowitsch { 2235f9244615SMatthew G. Knepley PetscDualSpaceTransformType trans; 2236f9244615SMatthew G. Knepley PetscInt k; 2237f9244615SMatthew G. Knepley 2238f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2239f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2240f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2241dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 2242f9244615SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 2243f9244615SMatthew G. Knepley This determines their transformation properties. */ 22449566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 22459371c9d4SSatish Balay switch (k) { 2246d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2247d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2248d71ae5a4SJacob Faibussowitsch break; 2249d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2250d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2251d71ae5a4SJacob Faibussowitsch break; 2252f9244615SMatthew G. Knepley case 2: 2253d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2254d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2255d71ae5a4SJacob Faibussowitsch break; 2256d71ae5a4SJacob Faibussowitsch default: 2257d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 2258f9244615SMatthew G. Knepley } 22599566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformHessian(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 2260f9244615SMatthew G. Knepley PetscFunctionReturn(0); 2261f9244615SMatthew G. Knepley } 2262