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: 22cfb853baSMatthew G. Knepley . tup - A tuple of len integers whose sum is at most 'max' 236f905325SMatthew G. Knepley 246f905325SMatthew G. Knepley Level: developer 256f905325SMatthew G. Knepley 26dce8aebaSBarry Smith .seealso: `PetscDualSpaceType`, `PetscDualSpaceTensorPointLexicographic_Internal()` 276f905325SMatthew G. Knepley */ 28d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceLatticePointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) 29d71ae5a4SJacob Faibussowitsch { 306f905325SMatthew G. Knepley PetscFunctionBegin; 316f905325SMatthew G. Knepley while (len--) { 326f905325SMatthew G. Knepley max -= tup[len]; 336f905325SMatthew G. Knepley if (!max) { 346f905325SMatthew G. Knepley tup[len] = 0; 356f905325SMatthew G. Knepley break; 366f905325SMatthew G. Knepley } 376f905325SMatthew G. Knepley } 386f905325SMatthew G. Knepley tup[++len]++; 393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 406f905325SMatthew G. Knepley } 416f905325SMatthew G. Knepley 426f905325SMatthew G. Knepley /* 436f905325SMatthew G. Knepley PetscDualSpaceTensorPointLexicographic_Internal - Returns all tuples of size 'len' with nonnegative integers that are all less than or equal to 'max'. 446f905325SMatthew G. Knepley Ordering is lexicographic with lowest index as least significant in ordering. 456f905325SMatthew G. Knepley e.g. for len == 2 and max == 2, this will return, in order, {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0,2}, {1,2}, {2,2}. 466f905325SMatthew G. Knepley 476f905325SMatthew G. Knepley Input Parameters: 486f905325SMatthew G. Knepley + len - The length of the tuple 496f905325SMatthew G. Knepley . max - The maximum value 506f905325SMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 516f905325SMatthew G. Knepley 526f905325SMatthew G. Knepley Output Parameter: 53cfb853baSMatthew G. Knepley . tup - A tuple of len integers whose entries are at most 'max' 546f905325SMatthew G. Knepley 556f905325SMatthew G. Knepley Level: developer 566f905325SMatthew G. Knepley 57dce8aebaSBarry Smith .seealso: `PetscDualSpaceType`, `PetscDualSpaceLatticePointLexicographic_Internal()` 586f905325SMatthew G. Knepley */ 59d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTensorPointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) 60d71ae5a4SJacob Faibussowitsch { 616f905325SMatthew G. Knepley PetscInt i; 626f905325SMatthew G. Knepley 636f905325SMatthew G. Knepley PetscFunctionBegin; 646f905325SMatthew G. Knepley for (i = 0; i < len; i++) { 656f905325SMatthew G. Knepley if (tup[i] < max) { 666f905325SMatthew G. Knepley break; 676f905325SMatthew G. Knepley } else { 686f905325SMatthew G. Knepley tup[i] = 0; 696f905325SMatthew G. Knepley } 706f905325SMatthew G. Knepley } 716f905325SMatthew G. Knepley tup[i]++; 723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 736f905325SMatthew G. Knepley } 746f905325SMatthew G. Knepley 7520cf1dd8SToby Isaac /*@C 76dce8aebaSBarry Smith PetscDualSpaceRegister - Adds a new `PetscDualSpaceType` 7720cf1dd8SToby Isaac 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 101dce8aebaSBarry Smith Note: 102dce8aebaSBarry Smith `PetscDualSpaceRegister()` may be called multiple times to add several user-defined `PetscDualSpace` 10320cf1dd8SToby Isaac 104dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceType`, `PetscDualSpaceRegisterAll()`, `PetscDualSpaceRegisterDestroy()` 10520cf1dd8SToby Isaac @*/ 106d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceRegister(const char sname[], PetscErrorCode (*function)(PetscDualSpace)) 107d71ae5a4SJacob Faibussowitsch { 10820cf1dd8SToby Isaac PetscFunctionBegin; 1099566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&PetscDualSpaceList, sname, function)); 1103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11120cf1dd8SToby Isaac } 11220cf1dd8SToby Isaac 11320cf1dd8SToby Isaac /*@C 114dce8aebaSBarry Smith PetscDualSpaceSetType - Builds a particular `PetscDualSpace` based on its `PetscDualSpaceType` 11520cf1dd8SToby Isaac 116d083f849SBarry Smith Collective on sp 11720cf1dd8SToby Isaac 11820cf1dd8SToby Isaac Input Parameters: 119dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 12020cf1dd8SToby Isaac - name - The kind of space 12120cf1dd8SToby Isaac 12220cf1dd8SToby Isaac Options Database Key: 12320cf1dd8SToby Isaac . -petscdualspace_type <type> - Sets the PetscDualSpace type; use -help for a list of available types 12420cf1dd8SToby Isaac 12520cf1dd8SToby Isaac Level: intermediate 12620cf1dd8SToby Isaac 127dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceType`, `PetscDualSpaceGetType()`, `PetscDualSpaceCreate()` 12820cf1dd8SToby Isaac @*/ 129d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetType(PetscDualSpace sp, PetscDualSpaceType name) 130d71ae5a4SJacob Faibussowitsch { 13120cf1dd8SToby Isaac PetscErrorCode (*r)(PetscDualSpace); 13220cf1dd8SToby Isaac PetscBool match; 13320cf1dd8SToby Isaac 13420cf1dd8SToby Isaac PetscFunctionBegin; 13520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)sp, name, &match)); 1373ba16761SJacob Faibussowitsch if (match) PetscFunctionReturn(PETSC_SUCCESS); 13820cf1dd8SToby Isaac 1399566063dSJacob Faibussowitsch if (!PetscDualSpaceRegisterAllCalled) PetscCall(PetscDualSpaceRegisterAll()); 1409566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(PetscDualSpaceList, name, &r)); 14128b400f6SJacob Faibussowitsch PetscCheck(r, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDualSpace type: %s", name); 14220cf1dd8SToby Isaac 143dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, destroy); 14420cf1dd8SToby Isaac sp->ops->destroy = NULL; 145dbbe0bcdSBarry Smith 1469566063dSJacob Faibussowitsch PetscCall((*r)(sp)); 1479566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)sp, name)); 1483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14920cf1dd8SToby Isaac } 15020cf1dd8SToby Isaac 15120cf1dd8SToby Isaac /*@C 152dce8aebaSBarry Smith PetscDualSpaceGetType - Gets the `PetscDualSpaceType` name (as a string) from the object. 15320cf1dd8SToby Isaac 15420cf1dd8SToby Isaac Not Collective 15520cf1dd8SToby Isaac 15620cf1dd8SToby Isaac Input Parameter: 157dce8aebaSBarry Smith . sp - The `PetscDualSpace` 15820cf1dd8SToby Isaac 15920cf1dd8SToby Isaac Output Parameter: 160dce8aebaSBarry Smith . name - The `PetscDualSpaceType` name 16120cf1dd8SToby Isaac 16220cf1dd8SToby Isaac Level: intermediate 16320cf1dd8SToby Isaac 164dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceType`, `PetscDualSpaceSetType()`, `PetscDualSpaceCreate()` 16520cf1dd8SToby Isaac @*/ 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; 1733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 2033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 204221d6281SMatthew G. Knepley } 205221d6281SMatthew G. Knepley 206fe2efc57SMark /*@C 207dce8aebaSBarry Smith PetscDualSpaceViewFromOptions - View a `PetscDualSpace` based on values in the options database 208fe2efc57SMark 209dce8aebaSBarry Smith Collective on A 210fe2efc57SMark 211fe2efc57SMark Input Parameters: 212dce8aebaSBarry Smith + A - the `PetscDualSpace` object 213dce8aebaSBarry Smith . obj - Optional object, provides the options prefix 214dce8aebaSBarry Smith - name - command line option name 215fe2efc57SMark 216fe2efc57SMark Level: intermediate 217dce8aebaSBarry Smith 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)); 2253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 226fe2efc57SMark } 227fe2efc57SMark 22820cf1dd8SToby Isaac /*@ 229dce8aebaSBarry Smith PetscDualSpaceView - Views a `PetscDualSpace` 23020cf1dd8SToby Isaac 231d083f849SBarry Smith Collective on sp 23220cf1dd8SToby Isaac 233d8d19677SJose E. Roman Input Parameters: 234dce8aebaSBarry Smith + sp - the `PetscDualSpace` object to view 23520cf1dd8SToby Isaac - v - the viewer 23620cf1dd8SToby Isaac 237a4ce7ad1SMatthew G. Knepley Level: beginner 23820cf1dd8SToby Isaac 239dce8aebaSBarry 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)); 2513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25220cf1dd8SToby Isaac } 25320cf1dd8SToby Isaac 25420cf1dd8SToby Isaac /*@ 255dce8aebaSBarry Smith PetscDualSpaceSetFromOptions - sets parameters in a `PetscDualSpace` from the options database 25620cf1dd8SToby Isaac 257d083f849SBarry Smith Collective on sp 25820cf1dd8SToby Isaac 25920cf1dd8SToby Isaac Input Parameter: 260dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to set options for 26120cf1dd8SToby Isaac 262dce8aebaSBarry 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 266*a9c5e6deSMatthew G. Knepley . -petscdualspace_refcell <celltype> - Reference cell type name 267*a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_continuity - Flag for continuous element 268*a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_tensor - Flag for tensor dual space 269*a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_trimmed - Flag for trimmed dual space 270*a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_node_type <nodetype> - Lagrange node location type 271*a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_node_endpoints - Flag for nodes that include endpoints 272*a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_node_exponent - Gauss-Jacobi weight function exponent 273*a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_use_moments - Use moments (where appropriate) for functionals 274*a9c5e6deSMatthew G. Knepley - -petscdualspace_lagrange_moment_order <order> - Quadrature order for moment functionals 27520cf1dd8SToby Isaac 276a4ce7ad1SMatthew G. Knepley Level: intermediate 27720cf1dd8SToby Isaac 278dce8aebaSBarry Smith .seealso: `PetscDualSpaceView()`, `PetscDualSpace`, `PetscObjectSetFromOptions()` 27920cf1dd8SToby Isaac @*/ 280d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetFromOptions(PetscDualSpace sp) 281d71ae5a4SJacob Faibussowitsch { 2822df84da0SMatthew G. Knepley DMPolytopeType refCell = DM_POLYTOPE_TRIANGLE; 28320cf1dd8SToby Isaac const char *defaultType; 28420cf1dd8SToby Isaac char name[256]; 285f783ec47SMatthew G. Knepley PetscBool flg; 28620cf1dd8SToby Isaac 28720cf1dd8SToby Isaac PetscFunctionBegin; 28820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 28920cf1dd8SToby Isaac if (!((PetscObject)sp)->type_name) { 29020cf1dd8SToby Isaac defaultType = PETSCDUALSPACELAGRANGE; 29120cf1dd8SToby Isaac } else { 29220cf1dd8SToby Isaac defaultType = ((PetscObject)sp)->type_name; 29320cf1dd8SToby Isaac } 2949566063dSJacob Faibussowitsch if (!PetscSpaceRegisterAllCalled) PetscCall(PetscSpaceRegisterAll()); 29520cf1dd8SToby Isaac 296d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)sp); 2979566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-petscdualspace_type", "Dual space", "PetscDualSpaceSetType", PetscDualSpaceList, defaultType, name, 256, &flg)); 29820cf1dd8SToby Isaac if (flg) { 2999566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, name)); 30020cf1dd8SToby Isaac } else if (!((PetscObject)sp)->type_name) { 3019566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, defaultType)); 30220cf1dd8SToby Isaac } 3039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_order", "The approximation order", "PetscDualSpaceSetOrder", sp->order, &sp->order, NULL, 0)); 3049566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-petscdualspace_form_degree", "The form degree of the dofs", "PetscDualSpaceSetFormDegree", sp->k, &sp->k, NULL)); 3059566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_components", "The number of components", "PetscDualSpaceSetNumComponents", sp->Nc, &sp->Nc, NULL, 1)); 306dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, setfromoptions, PetscOptionsObject); 3079566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-petscdualspace_refcell", "Reference cell shape", "PetscDualSpaceSetReferenceCell", DMPolytopeTypes, (PetscEnum)refCell, (PetscEnum *)&refCell, &flg)); 308063ee4adSMatthew G. Knepley if (flg) { 309063ee4adSMatthew G. Knepley DM K; 310063ee4adSMatthew G. Knepley 3119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, refCell, &K)); 3129566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(sp, K)); 3139566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 314063ee4adSMatthew G. Knepley } 315063ee4adSMatthew G. Knepley 31620cf1dd8SToby Isaac /* process any options handlers added with PetscObjectAddOptionsHandler() */ 317dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)sp, PetscOptionsObject)); 318d0609cedSBarry Smith PetscOptionsEnd(); 319063ee4adSMatthew G. Knepley sp->setfromoptionscalled = PETSC_TRUE; 3203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32120cf1dd8SToby Isaac } 32220cf1dd8SToby Isaac 32320cf1dd8SToby Isaac /*@ 324dce8aebaSBarry Smith PetscDualSpaceSetUp - Construct a basis for a `PetscDualSpace` 32520cf1dd8SToby Isaac 326d083f849SBarry Smith Collective on sp 32720cf1dd8SToby Isaac 32820cf1dd8SToby Isaac Input Parameter: 329dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to setup 33020cf1dd8SToby Isaac 331a4ce7ad1SMatthew G. Knepley Level: intermediate 33220cf1dd8SToby Isaac 333dce8aebaSBarry Smith .seealso: `PetscDualSpaceView()`, `PetscDualSpaceDestroy()`, `PetscDualSpace` 33420cf1dd8SToby Isaac @*/ 335d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetUp(PetscDualSpace sp) 336d71ae5a4SJacob Faibussowitsch { 33720cf1dd8SToby Isaac PetscFunctionBegin; 33820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 3393ba16761SJacob Faibussowitsch if (sp->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3409566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 34120cf1dd8SToby Isaac sp->setupcalled = PETSC_TRUE; 342dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, setup); 3439566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 3449566063dSJacob Faibussowitsch if (sp->setfromoptionscalled) PetscCall(PetscDualSpaceViewFromOptions(sp, NULL, "-petscdualspace_view")); 3453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34620cf1dd8SToby Isaac } 34720cf1dd8SToby Isaac 348d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDualSpaceClearDMData_Internal(PetscDualSpace sp, DM dm) 349d71ae5a4SJacob Faibussowitsch { 350b4457527SToby Isaac PetscInt pStart = -1, pEnd = -1, depth = -1; 351b4457527SToby Isaac 352b4457527SToby Isaac PetscFunctionBegin; 3533ba16761SJacob Faibussowitsch if (!dm) PetscFunctionReturn(PETSC_SUCCESS); 3549566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3559566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 356b4457527SToby Isaac 357b4457527SToby Isaac if (sp->pointSpaces) { 358b4457527SToby Isaac PetscInt i; 359b4457527SToby Isaac 36048a46eb9SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) PetscCall(PetscDualSpaceDestroy(&(sp->pointSpaces[i]))); 361b4457527SToby Isaac } 3629566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->pointSpaces)); 363b4457527SToby Isaac 364b4457527SToby Isaac if (sp->heightSpaces) { 365b4457527SToby Isaac PetscInt i; 366b4457527SToby Isaac 36748a46eb9SPierre Jolivet for (i = 0; i <= depth; i++) PetscCall(PetscDualSpaceDestroy(&(sp->heightSpaces[i]))); 368b4457527SToby Isaac } 3699566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->heightSpaces)); 370b4457527SToby Isaac 3719566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(sp->pointSection))); 3729566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->intNodes))); 3739566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->intDofValues))); 3749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->intNodeValues))); 3759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->intMat))); 3769566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->allNodes))); 3779566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->allDofValues))); 3789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->allNodeValues))); 3799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->allMat))); 3809566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->numDof)); 3813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 382b4457527SToby Isaac } 383b4457527SToby Isaac 38420cf1dd8SToby Isaac /*@ 385dce8aebaSBarry Smith PetscDualSpaceDestroy - Destroys a `PetscDualSpace` object 38620cf1dd8SToby Isaac 387d083f849SBarry Smith Collective on sp 38820cf1dd8SToby Isaac 38920cf1dd8SToby Isaac Input Parameter: 390dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to destroy 39120cf1dd8SToby Isaac 392a4ce7ad1SMatthew G. Knepley Level: beginner 39320cf1dd8SToby Isaac 394dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceView()`, `PetscDualSpace()`, `PetscDualSpaceCreate()` 39520cf1dd8SToby Isaac @*/ 396d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceDestroy(PetscDualSpace *sp) 397d71ae5a4SJacob Faibussowitsch { 39820cf1dd8SToby Isaac PetscInt dim, f; 399b4457527SToby Isaac DM dm; 40020cf1dd8SToby Isaac 40120cf1dd8SToby Isaac PetscFunctionBegin; 4023ba16761SJacob Faibussowitsch if (!*sp) PetscFunctionReturn(PETSC_SUCCESS); 40320cf1dd8SToby Isaac PetscValidHeaderSpecific((*sp), PETSCDUALSPACE_CLASSID, 1); 40420cf1dd8SToby Isaac 4059371c9d4SSatish Balay if (--((PetscObject)(*sp))->refct > 0) { 4069371c9d4SSatish Balay *sp = NULL; 4073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4089371c9d4SSatish Balay } 40920cf1dd8SToby Isaac ((PetscObject)(*sp))->refct = 0; 41020cf1dd8SToby Isaac 4119566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(*sp, &dim)); 412b4457527SToby Isaac dm = (*sp)->dm; 413b4457527SToby Isaac 414dbbe0bcdSBarry Smith PetscTryTypeMethod((*sp), destroy); 4159566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceClearDMData_Internal(*sp, dm)); 416b4457527SToby Isaac 41748a46eb9SPierre Jolivet for (f = 0; f < dim; ++f) PetscCall(PetscQuadratureDestroy(&(*sp)->functional[f])); 4189566063dSJacob Faibussowitsch PetscCall(PetscFree((*sp)->functional)); 4199566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*sp)->dm)); 4209566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(sp)); 4213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42220cf1dd8SToby Isaac } 42320cf1dd8SToby Isaac 42420cf1dd8SToby Isaac /*@ 425dce8aebaSBarry Smith PetscDualSpaceCreate - Creates an empty `PetscDualSpace` object. The type can then be set with `PetscDualSpaceSetType()`. 42620cf1dd8SToby Isaac 427d083f849SBarry Smith Collective 42820cf1dd8SToby Isaac 42920cf1dd8SToby Isaac Input Parameter: 430dce8aebaSBarry Smith . comm - The communicator for the `PetscDualSpace` object 43120cf1dd8SToby Isaac 43220cf1dd8SToby Isaac Output Parameter: 433dce8aebaSBarry Smith . sp - The `PetscDualSpace` object 43420cf1dd8SToby Isaac 43520cf1dd8SToby Isaac Level: beginner 43620cf1dd8SToby Isaac 437dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetType()`, `PETSCDUALSPACELAGRANGE` 43820cf1dd8SToby Isaac @*/ 439d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreate(MPI_Comm comm, PetscDualSpace *sp) 440d71ae5a4SJacob Faibussowitsch { 44120cf1dd8SToby Isaac PetscDualSpace s; 44220cf1dd8SToby Isaac 44320cf1dd8SToby Isaac PetscFunctionBegin; 44420cf1dd8SToby Isaac PetscValidPointer(sp, 2); 4459566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(FECitation, &FEcite)); 44620cf1dd8SToby Isaac *sp = NULL; 4479566063dSJacob Faibussowitsch PetscCall(PetscFEInitializePackage()); 44820cf1dd8SToby Isaac 4499566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(s, PETSCDUALSPACE_CLASSID, "PetscDualSpace", "Dual Space", "PetscDualSpace", comm, PetscDualSpaceDestroy, PetscDualSpaceView)); 45020cf1dd8SToby Isaac 45120cf1dd8SToby Isaac s->order = 0; 45220cf1dd8SToby Isaac s->Nc = 1; 4534bee2e38SMatthew G. Knepley s->k = 0; 454b4457527SToby Isaac s->spdim = -1; 455b4457527SToby Isaac s->spintdim = -1; 456b4457527SToby Isaac s->uniform = PETSC_TRUE; 45720cf1dd8SToby Isaac s->setupcalled = PETSC_FALSE; 45820cf1dd8SToby Isaac 45920cf1dd8SToby Isaac *sp = s; 4603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46120cf1dd8SToby Isaac } 46220cf1dd8SToby Isaac 46320cf1dd8SToby Isaac /*@ 464dce8aebaSBarry Smith PetscDualSpaceDuplicate - Creates a duplicate `PetscDualSpace` object that is not setup. 46520cf1dd8SToby Isaac 466d083f849SBarry Smith Collective on sp 46720cf1dd8SToby Isaac 46820cf1dd8SToby Isaac Input Parameter: 469dce8aebaSBarry Smith . sp - The original `PetscDualSpace` 47020cf1dd8SToby Isaac 47120cf1dd8SToby Isaac Output Parameter: 472dce8aebaSBarry Smith . spNew - The duplicate `PetscDualSpace` 47320cf1dd8SToby Isaac 47420cf1dd8SToby Isaac Level: beginner 47520cf1dd8SToby Isaac 476dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`, `PetscDualSpaceSetType()` 47720cf1dd8SToby Isaac @*/ 478d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceDuplicate(PetscDualSpace sp, PetscDualSpace *spNew) 479d71ae5a4SJacob Faibussowitsch { 480b4457527SToby Isaac DM dm; 481b4457527SToby Isaac PetscDualSpaceType type; 482b4457527SToby Isaac const char *name; 48320cf1dd8SToby Isaac 48420cf1dd8SToby Isaac PetscFunctionBegin; 48520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 48620cf1dd8SToby Isaac PetscValidPointer(spNew, 2); 4879566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(PetscObjectComm((PetscObject)sp), spNew)); 4889566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name)); 4899566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*spNew, name)); 4909566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetType(sp, &type)); 4919566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(*spNew, type)); 4929566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 4939566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(*spNew, dm)); 494b4457527SToby Isaac 495b4457527SToby Isaac (*spNew)->order = sp->order; 496b4457527SToby Isaac (*spNew)->k = sp->k; 497b4457527SToby Isaac (*spNew)->Nc = sp->Nc; 498b4457527SToby Isaac (*spNew)->uniform = sp->uniform; 499dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, duplicate, *spNew); 5003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50120cf1dd8SToby Isaac } 50220cf1dd8SToby Isaac 50320cf1dd8SToby Isaac /*@ 504dce8aebaSBarry Smith PetscDualSpaceGetDM - Get the `DM` representing the reference cell of a `PetscDualSpace` 50520cf1dd8SToby Isaac 50620cf1dd8SToby Isaac Not collective 50720cf1dd8SToby Isaac 50820cf1dd8SToby Isaac Input Parameter: 509dce8aebaSBarry Smith . sp - The `PetscDualSpace` 51020cf1dd8SToby Isaac 51120cf1dd8SToby Isaac Output Parameter: 512dce8aebaSBarry Smith . dm - The reference cell, that is a `DM` that consists of a single cell 51320cf1dd8SToby Isaac 51420cf1dd8SToby Isaac Level: intermediate 51520cf1dd8SToby Isaac 516dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetDM()`, `PetscDualSpaceCreate()` 51720cf1dd8SToby Isaac @*/ 518d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDM(PetscDualSpace sp, DM *dm) 519d71ae5a4SJacob Faibussowitsch { 52020cf1dd8SToby Isaac PetscFunctionBegin; 52120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 52220cf1dd8SToby Isaac PetscValidPointer(dm, 2); 52320cf1dd8SToby Isaac *dm = sp->dm; 5243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52520cf1dd8SToby Isaac } 52620cf1dd8SToby Isaac 52720cf1dd8SToby Isaac /*@ 528dce8aebaSBarry Smith PetscDualSpaceSetDM - Get the `DM` representing the reference cell 52920cf1dd8SToby Isaac 53020cf1dd8SToby Isaac Not collective 53120cf1dd8SToby Isaac 53220cf1dd8SToby Isaac Input Parameters: 533dce8aebaSBarry Smith + sp - The `PetscDual`Space 53420cf1dd8SToby Isaac - dm - The reference cell 53520cf1dd8SToby Isaac 53620cf1dd8SToby Isaac Level: intermediate 53720cf1dd8SToby Isaac 538dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `DM`, `PetscDualSpaceGetDM()`, `PetscDualSpaceCreate()` 53920cf1dd8SToby Isaac @*/ 540d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetDM(PetscDualSpace sp, DM dm) 541d71ae5a4SJacob Faibussowitsch { 54220cf1dd8SToby Isaac PetscFunctionBegin; 54320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 54420cf1dd8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 54528b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change DM after dualspace is set up"); 5469566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 54748a46eb9SPierre Jolivet if (sp->dm && sp->dm != dm) PetscCall(PetscDualSpaceClearDMData_Internal(sp, sp->dm)); 5489566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sp->dm)); 54920cf1dd8SToby Isaac sp->dm = dm; 5503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55120cf1dd8SToby Isaac } 55220cf1dd8SToby Isaac 55320cf1dd8SToby Isaac /*@ 55420cf1dd8SToby Isaac PetscDualSpaceGetOrder - Get the order of the dual space 55520cf1dd8SToby Isaac 55620cf1dd8SToby Isaac Not collective 55720cf1dd8SToby Isaac 55820cf1dd8SToby Isaac Input Parameter: 559dce8aebaSBarry Smith . sp - The `PetscDualSpace` 56020cf1dd8SToby Isaac 56120cf1dd8SToby Isaac Output Parameter: 56220cf1dd8SToby Isaac . order - The order 56320cf1dd8SToby Isaac 56420cf1dd8SToby Isaac Level: intermediate 56520cf1dd8SToby Isaac 566dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetOrder()`, `PetscDualSpaceCreate()` 56720cf1dd8SToby Isaac @*/ 568d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetOrder(PetscDualSpace sp, PetscInt *order) 569d71ae5a4SJacob Faibussowitsch { 57020cf1dd8SToby Isaac PetscFunctionBegin; 57120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 572dadcf809SJacob Faibussowitsch PetscValidIntPointer(order, 2); 57320cf1dd8SToby Isaac *order = sp->order; 5743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57520cf1dd8SToby Isaac } 57620cf1dd8SToby Isaac 57720cf1dd8SToby Isaac /*@ 57820cf1dd8SToby Isaac PetscDualSpaceSetOrder - Set the order of the dual space 57920cf1dd8SToby Isaac 58020cf1dd8SToby Isaac Not collective 58120cf1dd8SToby Isaac 58220cf1dd8SToby Isaac Input Parameters: 583dce8aebaSBarry Smith + sp - The `PetscDualSpace` 58420cf1dd8SToby Isaac - order - The order 58520cf1dd8SToby Isaac 58620cf1dd8SToby Isaac Level: intermediate 58720cf1dd8SToby Isaac 588dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetOrder()`, `PetscDualSpaceCreate()` 58920cf1dd8SToby Isaac @*/ 590d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetOrder(PetscDualSpace sp, PetscInt order) 591d71ae5a4SJacob Faibussowitsch { 59220cf1dd8SToby Isaac PetscFunctionBegin; 59320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 59428b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change order after dualspace is set up"); 59520cf1dd8SToby Isaac sp->order = order; 5963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59720cf1dd8SToby Isaac } 59820cf1dd8SToby Isaac 59920cf1dd8SToby Isaac /*@ 60020cf1dd8SToby Isaac PetscDualSpaceGetNumComponents - Return the number of components for this space 60120cf1dd8SToby Isaac 60220cf1dd8SToby Isaac Input Parameter: 603dce8aebaSBarry Smith . sp - The `PetscDualSpace` 60420cf1dd8SToby Isaac 60520cf1dd8SToby Isaac Output Parameter: 60620cf1dd8SToby Isaac . Nc - The number of components 60720cf1dd8SToby Isaac 60820cf1dd8SToby Isaac Level: intermediate 60920cf1dd8SToby Isaac 610dce8aebaSBarry Smith Note: 611dce8aebaSBarry Smith A vector space, for example, will have d components, where d is the spatial dimension 612dce8aebaSBarry Smith 613db781477SPatrick Sanan .seealso: `PetscDualSpaceSetNumComponents()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 61420cf1dd8SToby Isaac @*/ 615d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetNumComponents(PetscDualSpace sp, PetscInt *Nc) 616d71ae5a4SJacob Faibussowitsch { 61720cf1dd8SToby Isaac PetscFunctionBegin; 61820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 619dadcf809SJacob Faibussowitsch PetscValidIntPointer(Nc, 2); 62020cf1dd8SToby Isaac *Nc = sp->Nc; 6213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 62220cf1dd8SToby Isaac } 62320cf1dd8SToby Isaac 62420cf1dd8SToby Isaac /*@ 62520cf1dd8SToby Isaac PetscDualSpaceSetNumComponents - Set the number of components for this space 62620cf1dd8SToby Isaac 62720cf1dd8SToby Isaac Input Parameters: 628dce8aebaSBarry Smith + sp - The `PetscDualSpace` 62920cf1dd8SToby Isaac - order - The number of components 63020cf1dd8SToby Isaac 63120cf1dd8SToby Isaac Level: intermediate 63220cf1dd8SToby Isaac 633db781477SPatrick Sanan .seealso: `PetscDualSpaceGetNumComponents()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 63420cf1dd8SToby Isaac @*/ 635d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetNumComponents(PetscDualSpace sp, PetscInt Nc) 636d71ae5a4SJacob Faibussowitsch { 63720cf1dd8SToby Isaac PetscFunctionBegin; 63820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 63928b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 64020cf1dd8SToby Isaac sp->Nc = Nc; 6413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64220cf1dd8SToby Isaac } 64320cf1dd8SToby Isaac 64420cf1dd8SToby Isaac /*@ 64520cf1dd8SToby Isaac PetscDualSpaceGetFunctional - Get the i-th basis functional in the dual space 64620cf1dd8SToby Isaac 64720cf1dd8SToby Isaac Not collective 64820cf1dd8SToby Isaac 64920cf1dd8SToby Isaac Input Parameters: 650dce8aebaSBarry Smith + sp - The `PetscDualSpace` 65120cf1dd8SToby Isaac - i - The basis number 65220cf1dd8SToby Isaac 65320cf1dd8SToby Isaac Output Parameter: 65420cf1dd8SToby Isaac . functional - The basis functional 65520cf1dd8SToby Isaac 65620cf1dd8SToby Isaac Level: intermediate 65720cf1dd8SToby Isaac 658dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()` 65920cf1dd8SToby Isaac @*/ 660d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetFunctional(PetscDualSpace sp, PetscInt i, PetscQuadrature *functional) 661d71ae5a4SJacob Faibussowitsch { 66220cf1dd8SToby Isaac PetscInt dim; 66320cf1dd8SToby Isaac 66420cf1dd8SToby Isaac PetscFunctionBegin; 66520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 66620cf1dd8SToby Isaac PetscValidPointer(functional, 3); 6679566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &dim)); 66863a3b9bcSJacob 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); 66920cf1dd8SToby Isaac *functional = sp->functional[i]; 6703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 67120cf1dd8SToby Isaac } 67220cf1dd8SToby Isaac 67320cf1dd8SToby Isaac /*@ 67420cf1dd8SToby Isaac PetscDualSpaceGetDimension - Get the dimension of the dual space, i.e. the number of basis functionals 67520cf1dd8SToby Isaac 67620cf1dd8SToby Isaac Not collective 67720cf1dd8SToby Isaac 67820cf1dd8SToby Isaac Input Parameter: 679dce8aebaSBarry Smith . sp - The `PetscDualSpace` 68020cf1dd8SToby Isaac 68120cf1dd8SToby Isaac Output Parameter: 68220cf1dd8SToby Isaac . dim - The dimension 68320cf1dd8SToby Isaac 68420cf1dd8SToby Isaac Level: intermediate 68520cf1dd8SToby Isaac 686dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 68720cf1dd8SToby Isaac @*/ 688d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDimension(PetscDualSpace sp, PetscInt *dim) 689d71ae5a4SJacob Faibussowitsch { 69020cf1dd8SToby Isaac PetscFunctionBegin; 69120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 692dadcf809SJacob Faibussowitsch PetscValidIntPointer(dim, 2); 693b4457527SToby Isaac if (sp->spdim < 0) { 694b4457527SToby Isaac PetscSection section; 695b4457527SToby Isaac 6969566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 697b4457527SToby Isaac if (section) { 6989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &(sp->spdim))); 699b4457527SToby Isaac } else sp->spdim = 0; 700b4457527SToby Isaac } 701b4457527SToby Isaac *dim = sp->spdim; 7023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70320cf1dd8SToby Isaac } 70420cf1dd8SToby Isaac 705b4457527SToby Isaac /*@ 706b4457527SToby Isaac PetscDualSpaceGetInteriorDimension - Get the interior dimension of the dual space, i.e. the number of basis functionals assigned to the interior of the reference domain 707b4457527SToby Isaac 708b4457527SToby Isaac Not collective 709b4457527SToby Isaac 710b4457527SToby Isaac Input Parameter: 711dce8aebaSBarry Smith . sp - The `PetscDualSpace` 712b4457527SToby Isaac 713b4457527SToby Isaac Output Parameter: 714b4457527SToby Isaac . dim - The dimension 715b4457527SToby Isaac 716b4457527SToby Isaac Level: intermediate 717b4457527SToby Isaac 718dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 719b4457527SToby Isaac @*/ 720d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetInteriorDimension(PetscDualSpace sp, PetscInt *intdim) 721d71ae5a4SJacob Faibussowitsch { 722b4457527SToby Isaac PetscFunctionBegin; 723b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 724dadcf809SJacob Faibussowitsch PetscValidIntPointer(intdim, 2); 725b4457527SToby Isaac if (sp->spintdim < 0) { 726b4457527SToby Isaac PetscSection section; 727b4457527SToby Isaac 7289566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 729b4457527SToby Isaac if (section) { 7309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &(sp->spintdim))); 731b4457527SToby Isaac } else sp->spintdim = 0; 732b4457527SToby Isaac } 733b4457527SToby Isaac *intdim = sp->spintdim; 7343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 735b4457527SToby Isaac } 736b4457527SToby Isaac 737b4457527SToby Isaac /*@ 738b4457527SToby Isaac PetscDualSpaceGetUniform - Whether this dual space is uniform 739b4457527SToby Isaac 740b4457527SToby Isaac Not collective 741b4457527SToby Isaac 742b4457527SToby Isaac Input Parameters: 743b4457527SToby Isaac . sp - A dual space 744b4457527SToby Isaac 745b4457527SToby Isaac Output Parameters: 746dce8aebaSBarry Smith . uniform - `PETSC_TRUE` if (a) the dual space is the same for each point in a stratum of the reference `DMPLEX`, and 747dce8aebaSBarry Smith (b) every symmetry of each point in the reference `DMPLEX` is also a symmetry of the point's dual space. 748b4457527SToby Isaac 749b4457527SToby Isaac Level: advanced 750b4457527SToby Isaac 751dce8aebaSBarry Smith Note: 752dce8aebaSBarry Smith All of the usual spaces on simplex or tensor-product elements will be uniform, only reference cells 753b4457527SToby Isaac with non-uniform strata (like trianguar-prisms) or anisotropic hp dual spaces will not be uniform. 754b4457527SToby Isaac 755dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetPointSubspace()`, `PetscDualSpaceGetSymmetries()` 756b4457527SToby Isaac @*/ 757d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetUniform(PetscDualSpace sp, PetscBool *uniform) 758d71ae5a4SJacob Faibussowitsch { 759b4457527SToby Isaac PetscFunctionBegin; 760b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 761dadcf809SJacob Faibussowitsch PetscValidBoolPointer(uniform, 2); 762b4457527SToby Isaac *uniform = sp->uniform; 7633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 764b4457527SToby Isaac } 765b4457527SToby Isaac 76620cf1dd8SToby Isaac /*@C 76720cf1dd8SToby Isaac PetscDualSpaceGetNumDof - Get the number of degrees of freedom for each spatial (topological) dimension 76820cf1dd8SToby Isaac 76920cf1dd8SToby Isaac Not collective 77020cf1dd8SToby Isaac 77120cf1dd8SToby Isaac Input Parameter: 772dce8aebaSBarry Smith . sp - The `PetscDualSpace` 77320cf1dd8SToby Isaac 77420cf1dd8SToby Isaac Output Parameter: 77520cf1dd8SToby Isaac . numDof - An array of length dim+1 which holds the number of dofs for each dimension 77620cf1dd8SToby Isaac 77720cf1dd8SToby Isaac Level: intermediate 77820cf1dd8SToby Isaac 779dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 78020cf1dd8SToby Isaac @*/ 781d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetNumDof(PetscDualSpace sp, const PetscInt **numDof) 782d71ae5a4SJacob Faibussowitsch { 78320cf1dd8SToby Isaac PetscFunctionBegin; 78420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 78520cf1dd8SToby Isaac PetscValidPointer(numDof, 2); 78628b400f6SJacob 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"); 787b4457527SToby Isaac if (!sp->numDof) { 788b4457527SToby Isaac DM dm; 789b4457527SToby Isaac PetscInt depth, d; 790b4457527SToby Isaac PetscSection section; 791b4457527SToby Isaac 7929566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 7939566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 7949566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth + 1, &(sp->numDof))); 7959566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 796b4457527SToby Isaac for (d = 0; d <= depth; d++) { 797b4457527SToby Isaac PetscInt dStart, dEnd; 798b4457527SToby Isaac 7999566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 800b4457527SToby Isaac if (dEnd <= dStart) continue; 8019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, dStart, &(sp->numDof[d]))); 802b4457527SToby Isaac } 803b4457527SToby Isaac } 804b4457527SToby Isaac *numDof = sp->numDof; 80508401ef6SPierre Jolivet PetscCheck(*numDof, PetscObjectComm((PetscObject)sp), PETSC_ERR_LIB, "Empty numDof[] returned from dual space implementation"); 8063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 80720cf1dd8SToby Isaac } 80820cf1dd8SToby Isaac 809b4457527SToby Isaac /* create the section of the right size and set a permutation for topological ordering */ 810d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSectionCreate_Internal(PetscDualSpace sp, PetscSection *topSection) 811d71ae5a4SJacob Faibussowitsch { 812b4457527SToby Isaac DM dm; 813b4457527SToby Isaac PetscInt pStart, pEnd, cStart, cEnd, c, depth, count, i; 814b4457527SToby Isaac PetscInt *seen, *perm; 815b4457527SToby Isaac PetscSection section; 816b4457527SToby Isaac 817b4457527SToby Isaac PetscFunctionBegin; 818b4457527SToby Isaac dm = sp->dm; 8199566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion)); 8209566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 8229566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &seen)); 8239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &perm)); 8249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8259566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 826b4457527SToby Isaac for (c = cStart, count = 0; c < cEnd; c++) { 827b4457527SToby Isaac PetscInt closureSize = -1, e; 828b4457527SToby Isaac PetscInt *closure = NULL; 829b4457527SToby Isaac 830b4457527SToby Isaac perm[count++] = c; 831b4457527SToby Isaac seen[c - pStart] = 1; 8329566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 833b4457527SToby Isaac for (e = 0; e < closureSize; e++) { 834b4457527SToby Isaac PetscInt point = closure[2 * e]; 835b4457527SToby Isaac 836b4457527SToby Isaac if (seen[point - pStart]) continue; 837b4457527SToby Isaac perm[count++] = point; 838b4457527SToby Isaac seen[point - pStart] = 1; 839b4457527SToby Isaac } 8409566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 841b4457527SToby Isaac } 8421dca8a05SBarry Smith PetscCheck(count == pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad topological ordering"); 8439371c9d4SSatish Balay for (i = 0; i < pEnd - pStart; i++) 8449371c9d4SSatish Balay if (perm[i] != i) break; 845b4457527SToby Isaac if (i < pEnd - pStart) { 846b4457527SToby Isaac IS permIS; 847b4457527SToby Isaac 8489566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pEnd - pStart, perm, PETSC_OWN_POINTER, &permIS)); 8499566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(permIS)); 8509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(section, permIS)); 8519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS)); 852b4457527SToby Isaac } else { 8539566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 854b4457527SToby Isaac } 8559566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 856b4457527SToby Isaac *topSection = section; 8573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 858b4457527SToby Isaac } 859b4457527SToby Isaac 860b4457527SToby Isaac /* mark boundary points and set up */ 861d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSectionSetUp_Internal(PetscDualSpace sp, PetscSection section) 862d71ae5a4SJacob Faibussowitsch { 863b4457527SToby Isaac DM dm; 864b4457527SToby Isaac DMLabel boundary; 865b4457527SToby Isaac PetscInt pStart, pEnd, p; 866b4457527SToby Isaac 867b4457527SToby Isaac PetscFunctionBegin; 868b4457527SToby Isaac dm = sp->dm; 8699566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "boundary", &boundary)); 8709566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 8719566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, 1, boundary)); 8729566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, boundary)); 8739566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 874b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 875b4457527SToby Isaac PetscInt bval; 876b4457527SToby Isaac 8779566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(boundary, p, &bval)); 878b4457527SToby Isaac if (bval == 1) { 879b4457527SToby Isaac PetscInt dof; 880b4457527SToby Isaac 8819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 8829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetConstraintDof(section, p, dof)); 883b4457527SToby Isaac } 884b4457527SToby Isaac } 8859566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&boundary)); 8869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 8873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 888b4457527SToby Isaac } 889b4457527SToby Isaac 890a4ce7ad1SMatthew G. Knepley /*@ 891dce8aebaSBarry Smith PetscDualSpaceGetSection - Create a `PetscSection` over the reference cell with the layout from this space 892a4ce7ad1SMatthew G. Knepley 893a4ce7ad1SMatthew G. Knepley Collective on sp 894a4ce7ad1SMatthew G. Knepley 895a4ce7ad1SMatthew G. Knepley Input Parameters: 896dce8aebaSBarry Smith . sp - The `PetscDualSpace` 897a4ce7ad1SMatthew G. Knepley 898a4ce7ad1SMatthew G. Knepley Output Parameter: 899a4ce7ad1SMatthew G. Knepley . section - The section 900a4ce7ad1SMatthew G. Knepley 901a4ce7ad1SMatthew G. Knepley Level: advanced 902a4ce7ad1SMatthew G. Knepley 903dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscSection`, `PetscDualSpaceCreate()`, `DMPLEX` 904a4ce7ad1SMatthew G. Knepley @*/ 905d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetSection(PetscDualSpace sp, PetscSection *section) 906d71ae5a4SJacob Faibussowitsch { 907b4457527SToby Isaac PetscInt pStart, pEnd, p; 908b4457527SToby Isaac 909b4457527SToby Isaac PetscFunctionBegin; 91078f1d139SRomain Beucher if (!sp->dm) { 91178f1d139SRomain Beucher *section = NULL; 9123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 91378f1d139SRomain Beucher } 914b4457527SToby Isaac if (!sp->pointSection) { 915b4457527SToby Isaac /* mark the boundary */ 9169566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionCreate_Internal(sp, &(sp->pointSection))); 9179566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(sp->dm, &pStart, &pEnd)); 918b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 919b4457527SToby Isaac PetscDualSpace psp; 920b4457527SToby Isaac 9219566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, p, &psp)); 922b4457527SToby Isaac if (psp) { 923b4457527SToby Isaac PetscInt dof; 924b4457527SToby Isaac 9259566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorDimension(psp, &dof)); 9269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sp->pointSection, p, dof)); 927b4457527SToby Isaac } 928b4457527SToby Isaac } 9299566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionSetUp_Internal(sp, sp->pointSection)); 930b4457527SToby Isaac } 931b4457527SToby Isaac *section = sp->pointSection; 9323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 933b4457527SToby Isaac } 934b4457527SToby Isaac 935b4457527SToby Isaac /* this assumes that all of the point dual spaces store their interior dofs first, which is true when the point DMs 936b4457527SToby Isaac * have one cell */ 937d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushForwardSubspaces_Internal(PetscDualSpace sp, PetscInt sStart, PetscInt sEnd) 938d71ae5a4SJacob Faibussowitsch { 939b4457527SToby Isaac PetscReal *sv0, *v0, *J; 940b4457527SToby Isaac PetscSection section; 941b4457527SToby Isaac PetscInt dim, s, k; 94220cf1dd8SToby Isaac DM dm; 94320cf1dd8SToby Isaac 94420cf1dd8SToby Isaac PetscFunctionBegin; 9459566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 9469566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9479566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 9489566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim, &sv0, dim * dim, &J)); 9499566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFormDegree(sp, &k)); 950b4457527SToby Isaac for (s = sStart; s < sEnd; s++) { 951b4457527SToby Isaac PetscReal detJ, hdetJ; 952b4457527SToby Isaac PetscDualSpace ssp; 953b4457527SToby Isaac PetscInt dof, off, f, sdim; 954b4457527SToby Isaac PetscInt i, j; 955b4457527SToby Isaac DM sdm; 95620cf1dd8SToby Isaac 9579566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, s, &ssp)); 958b4457527SToby Isaac if (!ssp) continue; 9599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, s, &dof)); 9609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, s, &off)); 961b4457527SToby Isaac /* get the first vertex of the reference cell */ 9629566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(ssp, &sdm)); 9639566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sdm, &sdim)); 9649566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(sdm, 0, sv0, NULL, NULL, &hdetJ)); 9659566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, s, v0, J, NULL, &detJ)); 966b4457527SToby Isaac /* compactify Jacobian */ 9679371c9d4SSatish Balay for (i = 0; i < dim; i++) 9689371c9d4SSatish Balay for (j = 0; j < sdim; j++) J[i * sdim + j] = J[i * dim + j]; 969b4457527SToby Isaac for (f = 0; f < dof; f++) { 970b4457527SToby Isaac PetscQuadrature fn; 97120cf1dd8SToby Isaac 9729566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(ssp, f, &fn)); 9739566063dSJacob Faibussowitsch PetscCall(PetscQuadraturePushForward(fn, dim, sv0, v0, J, k, &(sp->functional[off + f]))); 97420cf1dd8SToby Isaac } 97520cf1dd8SToby Isaac } 9769566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, sv0, J)); 9773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97820cf1dd8SToby Isaac } 97920cf1dd8SToby Isaac 98020cf1dd8SToby Isaac /*@C 98120cf1dd8SToby Isaac PetscDualSpaceApply - Apply a functional from the dual space basis to an input function 98220cf1dd8SToby Isaac 98320cf1dd8SToby Isaac Input Parameters: 984dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 98520cf1dd8SToby Isaac . f - The basis functional index 98620cf1dd8SToby Isaac . time - The time 98720cf1dd8SToby 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) 98820cf1dd8SToby Isaac . numComp - The number of components for the function 98920cf1dd8SToby Isaac . func - The input function 99020cf1dd8SToby Isaac - ctx - A context for the function 99120cf1dd8SToby Isaac 99220cf1dd8SToby Isaac Output Parameter: 99320cf1dd8SToby Isaac . value - numComp output values 99420cf1dd8SToby Isaac 995dce8aebaSBarry Smith Calling Sequence of func: 996dce8aebaSBarry Smith .vb 997dce8aebaSBarry Smith func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt numComponents, PetscScalar values[], void *ctx) 998dce8aebaSBarry Smith .ve 99920cf1dd8SToby Isaac 1000a4ce7ad1SMatthew G. Knepley Level: beginner 100120cf1dd8SToby Isaac 1002dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 100320cf1dd8SToby Isaac @*/ 1004d71ae5a4SJacob 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) 1005d71ae5a4SJacob Faibussowitsch { 100620cf1dd8SToby Isaac PetscFunctionBegin; 100720cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 100820cf1dd8SToby Isaac PetscValidPointer(cgeom, 4); 1009dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 1010dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, apply, f, time, cgeom, numComp, func, ctx, value); 10113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 101220cf1dd8SToby Isaac } 101320cf1dd8SToby Isaac 101420cf1dd8SToby Isaac /*@C 1015dce8aebaSBarry Smith PetscDualSpaceApplyAll - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetAllData()` 101620cf1dd8SToby Isaac 101720cf1dd8SToby Isaac Input Parameters: 1018dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1019dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetAllData()` 102020cf1dd8SToby Isaac 102120cf1dd8SToby Isaac Output Parameter: 102220cf1dd8SToby Isaac . spValue - The values of all dual space functionals 102320cf1dd8SToby Isaac 1024dce8aebaSBarry Smith Level: advanced 102520cf1dd8SToby Isaac 1026dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 102720cf1dd8SToby Isaac @*/ 1028d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyAll(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1029d71ae5a4SJacob Faibussowitsch { 103020cf1dd8SToby Isaac PetscFunctionBegin; 103120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1032dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyall, pointEval, spValue); 10333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 103420cf1dd8SToby Isaac } 103520cf1dd8SToby Isaac 103620cf1dd8SToby Isaac /*@C 1037dce8aebaSBarry Smith PetscDualSpaceApplyInterior - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1038b4457527SToby Isaac 1039b4457527SToby Isaac Input Parameters: 1040dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1041dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1042b4457527SToby Isaac 1043b4457527SToby Isaac Output Parameter: 1044b4457527SToby Isaac . spValue - The values of interior dual space functionals 1045b4457527SToby Isaac 1046dce8aebaSBarry Smith Level: advanced 1047b4457527SToby Isaac 1048dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 1049b4457527SToby Isaac @*/ 1050d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyInterior(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1051d71ae5a4SJacob Faibussowitsch { 1052b4457527SToby Isaac PetscFunctionBegin; 1053b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1054dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyint, pointEval, spValue); 10553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1056b4457527SToby Isaac } 1057b4457527SToby Isaac 1058b4457527SToby Isaac /*@C 105920cf1dd8SToby Isaac PetscDualSpaceApplyDefault - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional. 106020cf1dd8SToby Isaac 106120cf1dd8SToby Isaac Input Parameters: 1062dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 106320cf1dd8SToby Isaac . f - The basis functional index 106420cf1dd8SToby Isaac . time - The time 106520cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian) 106620cf1dd8SToby Isaac . Nc - The number of components for the function 106720cf1dd8SToby Isaac . func - The input function 106820cf1dd8SToby Isaac - ctx - A context for the function 106920cf1dd8SToby Isaac 107020cf1dd8SToby Isaac Output Parameter: 107120cf1dd8SToby Isaac . value - The output value 107220cf1dd8SToby Isaac 1073dce8aebaSBarry Smith Calling Sequence of func: 1074dce8aebaSBarry Smith .vb 1075dce8aebaSBarry Smith func(PetscInt dim, PetscReal time, const PetscReal x[],PetscInt numComponents, PetscScalar values[], void *ctx) 1076dce8aebaSBarry Smith .ve 107720cf1dd8SToby Isaac 1078dce8aebaSBarry Smith Level: advanced 107920cf1dd8SToby Isaac 1080dce8aebaSBarry Smith Note: 1081dce8aebaSBarry 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. 108220cf1dd8SToby Isaac 1083dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 108420cf1dd8SToby Isaac @*/ 1085d71ae5a4SJacob 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) 1086d71ae5a4SJacob Faibussowitsch { 108720cf1dd8SToby Isaac DM dm; 108820cf1dd8SToby Isaac PetscQuadrature n; 108920cf1dd8SToby Isaac const PetscReal *points, *weights; 109020cf1dd8SToby Isaac PetscReal x[3]; 109120cf1dd8SToby Isaac PetscScalar *val; 109220cf1dd8SToby Isaac PetscInt dim, dE, qNc, c, Nq, q; 109320cf1dd8SToby Isaac PetscBool isAffine; 109420cf1dd8SToby Isaac 109520cf1dd8SToby Isaac PetscFunctionBegin; 109620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1097dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 10989566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 10999566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 11009566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, &dim, &qNc, &Nq, &points, &weights)); 110163a3b9bcSJacob 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); 110263a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 11039566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 110420cf1dd8SToby Isaac *value = 0.0; 110520cf1dd8SToby Isaac isAffine = cgeom->isAffine; 110620cf1dd8SToby Isaac dE = cgeom->dimEmbed; 110720cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 110820cf1dd8SToby Isaac if (isAffine) { 110920cf1dd8SToby Isaac CoordinatesRefToReal(dE, cgeom->dim, cgeom->xi, cgeom->v, cgeom->J, &points[q * dim], x); 11109566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, x, Nc, val, ctx)); 111120cf1dd8SToby Isaac } else { 11129566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, &cgeom->v[dE * q], Nc, val, ctx)); 111320cf1dd8SToby Isaac } 1114ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) *value += val[c] * weights[q * Nc + c]; 111520cf1dd8SToby Isaac } 11169566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 11173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 111820cf1dd8SToby Isaac } 111920cf1dd8SToby Isaac 112020cf1dd8SToby Isaac /*@C 1121dce8aebaSBarry Smith PetscDualSpaceApplyAllDefault - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetAllData()` 112220cf1dd8SToby Isaac 112320cf1dd8SToby Isaac Input Parameters: 1124dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1125dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetAllData()` 112620cf1dd8SToby Isaac 112720cf1dd8SToby Isaac Output Parameter: 112820cf1dd8SToby Isaac . spValue - The values of all dual space functionals 112920cf1dd8SToby Isaac 1130dce8aebaSBarry Smith Level: advanced 113120cf1dd8SToby Isaac 1132dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 113320cf1dd8SToby Isaac @*/ 1134d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyAllDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1135d71ae5a4SJacob Faibussowitsch { 1136b4457527SToby Isaac Vec pointValues, dofValues; 1137b4457527SToby Isaac Mat allMat; 113820cf1dd8SToby Isaac 113920cf1dd8SToby Isaac PetscFunctionBegin; 114020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 114120cf1dd8SToby Isaac PetscValidScalarPointer(pointEval, 2); 1142064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11439566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetAllData(sp, NULL, &allMat)); 114448a46eb9SPierre Jolivet if (!(sp->allNodeValues)) PetscCall(MatCreateVecs(allMat, &(sp->allNodeValues), NULL)); 1145b4457527SToby Isaac pointValues = sp->allNodeValues; 114648a46eb9SPierre Jolivet if (!(sp->allDofValues)) PetscCall(MatCreateVecs(allMat, NULL, &(sp->allDofValues))); 1147b4457527SToby Isaac dofValues = sp->allDofValues; 11489566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11499566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11509566063dSJacob Faibussowitsch PetscCall(MatMult(allMat, pointValues, dofValues)); 11519566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11529566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 11533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 115420cf1dd8SToby Isaac } 1155b4457527SToby Isaac 1156b4457527SToby Isaac /*@C 1157dce8aebaSBarry Smith PetscDualSpaceApplyInteriorDefault - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1158b4457527SToby Isaac 1159b4457527SToby Isaac Input Parameters: 1160dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1161dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1162b4457527SToby Isaac 1163b4457527SToby Isaac Output Parameter: 1164b4457527SToby Isaac . spValue - The values of interior dual space functionals 1165b4457527SToby Isaac 1166dce8aebaSBarry Smith Level: advanced 1167b4457527SToby Isaac 1168dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 1169b4457527SToby Isaac @*/ 1170d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyInteriorDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1171d71ae5a4SJacob Faibussowitsch { 1172b4457527SToby Isaac Vec pointValues, dofValues; 1173b4457527SToby Isaac Mat intMat; 1174b4457527SToby Isaac 1175b4457527SToby Isaac PetscFunctionBegin; 1176b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1177b4457527SToby Isaac PetscValidScalarPointer(pointEval, 2); 1178064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11799566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(sp, NULL, &intMat)); 118048a46eb9SPierre Jolivet if (!(sp->intNodeValues)) PetscCall(MatCreateVecs(intMat, &(sp->intNodeValues), NULL)); 1181b4457527SToby Isaac pointValues = sp->intNodeValues; 118248a46eb9SPierre Jolivet if (!(sp->intDofValues)) PetscCall(MatCreateVecs(intMat, NULL, &(sp->intDofValues))); 1183b4457527SToby Isaac dofValues = sp->intDofValues; 11849566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11859566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11869566063dSJacob Faibussowitsch PetscCall(MatMult(intMat, pointValues, dofValues)); 11879566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11889566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 11893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 119020cf1dd8SToby Isaac } 119120cf1dd8SToby Isaac 1192a4ce7ad1SMatthew G. Knepley /*@ 1193b4457527SToby Isaac PetscDualSpaceGetAllData - Get all quadrature nodes from this space, and the matrix that sends quadrature node values to degree-of-freedom values 1194a4ce7ad1SMatthew G. Knepley 1195a4ce7ad1SMatthew G. Knepley Input Parameter: 1196a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1197a4ce7ad1SMatthew G. Knepley 1198d8d19677SJose E. Roman Output Parameters: 1199dce8aebaSBarry Smith + allNodes - A `PetscQuadrature` object containing all evaluation nodes 1200dce8aebaSBarry Smith - allMat - A `Mat` for the node-to-dof transformation 1201a4ce7ad1SMatthew G. Knepley 1202a4ce7ad1SMatthew G. Knepley Level: advanced 1203a4ce7ad1SMatthew G. Knepley 1204dce8aebaSBarry Smith .seealso: `PetscQuadrature`, `PetscDualSpace`, `PetscDualSpaceCreate()`, `Mat` 1205a4ce7ad1SMatthew G. Knepley @*/ 1206d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetAllData(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 1207d71ae5a4SJacob Faibussowitsch { 120820cf1dd8SToby Isaac PetscFunctionBegin; 120920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1210b4457527SToby Isaac if (allNodes) PetscValidPointer(allNodes, 2); 1211b4457527SToby Isaac if (allMat) PetscValidPointer(allMat, 3); 1212b4457527SToby Isaac if ((!sp->allNodes || !sp->allMat) && sp->ops->createalldata) { 1213b4457527SToby Isaac PetscQuadrature qpoints; 1214b4457527SToby Isaac Mat amat; 1215b4457527SToby Isaac 1216dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createalldata, &qpoints, &amat); 12179566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->allNodes))); 12189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->allMat))); 1219b4457527SToby Isaac sp->allNodes = qpoints; 1220b4457527SToby Isaac sp->allMat = amat; 122120cf1dd8SToby Isaac } 1222b4457527SToby Isaac if (allNodes) *allNodes = sp->allNodes; 1223b4457527SToby Isaac if (allMat) *allMat = sp->allMat; 12243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 122520cf1dd8SToby Isaac } 122620cf1dd8SToby Isaac 1227a4ce7ad1SMatthew G. Knepley /*@ 1228b4457527SToby Isaac PetscDualSpaceCreateAllDataDefault - Create all evaluation nodes and the node-to-dof matrix by examining functionals 1229a4ce7ad1SMatthew G. Knepley 1230a4ce7ad1SMatthew G. Knepley Input Parameter: 1231a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1232a4ce7ad1SMatthew G. Knepley 1233d8d19677SJose E. Roman Output Parameters: 1234dce8aebaSBarry Smith + allNodes - A `PetscQuadrature` object containing all evaluation nodes 1235dce8aebaSBarry Smith - allMat - A `Mat` for the node-to-dof transformation 1236a4ce7ad1SMatthew G. Knepley 1237a4ce7ad1SMatthew G. Knepley Level: advanced 1238a4ce7ad1SMatthew G. Knepley 1239dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`, `Mat`, `PetscQuadrature` 1240a4ce7ad1SMatthew G. Knepley @*/ 1241d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreateAllDataDefault(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 1242d71ae5a4SJacob Faibussowitsch { 124320cf1dd8SToby Isaac PetscInt spdim; 124420cf1dd8SToby Isaac PetscInt numPoints, offset; 124520cf1dd8SToby Isaac PetscReal *points; 124620cf1dd8SToby Isaac PetscInt f, dim; 1247b4457527SToby Isaac PetscInt Nc, nrows, ncols; 1248b4457527SToby Isaac PetscInt maxNumPoints; 124920cf1dd8SToby Isaac PetscQuadrature q; 1250b4457527SToby Isaac Mat A; 125120cf1dd8SToby Isaac 125220cf1dd8SToby Isaac PetscFunctionBegin; 12539566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 12549566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &spdim)); 125520cf1dd8SToby Isaac if (!spdim) { 12569566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes)); 12579566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, 0, 0, 0, NULL, NULL)); 125820cf1dd8SToby Isaac } 1259b4457527SToby Isaac nrows = spdim; 12609566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, 0, &q)); 12619566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, NULL, &numPoints, NULL, NULL)); 1262b4457527SToby Isaac maxNumPoints = numPoints; 126320cf1dd8SToby Isaac for (f = 1; f < spdim; f++) { 126420cf1dd8SToby Isaac PetscInt Np; 126520cf1dd8SToby Isaac 12669566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q)); 12679566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL)); 126820cf1dd8SToby Isaac numPoints += Np; 1269b4457527SToby Isaac maxNumPoints = PetscMax(maxNumPoints, Np); 127020cf1dd8SToby Isaac } 1271b4457527SToby Isaac ncols = numPoints * Nc; 12729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points)); 12739566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, nrows, ncols, maxNumPoints * Nc, NULL, &A)); 127420cf1dd8SToby Isaac for (f = 0, offset = 0; f < spdim; f++) { 1275b4457527SToby Isaac const PetscReal *p, *w; 127620cf1dd8SToby Isaac PetscInt Np, i; 1277b4457527SToby Isaac PetscInt fnc; 127820cf1dd8SToby Isaac 12799566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q)); 12809566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, &fnc, &Np, &p, &w)); 128108401ef6SPierre Jolivet PetscCheck(fnc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "functional component mismatch"); 1282ad540459SPierre Jolivet for (i = 0; i < Np * dim; i++) points[offset * dim + i] = p[i]; 128348a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(A, f, offset * Nc, w[i], INSERT_VALUES)); 1284b4457527SToby Isaac offset += Np; 1285b4457527SToby Isaac } 12869566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 12879566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 12889566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes)); 12899566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, dim, 0, numPoints, points, NULL)); 1290b4457527SToby Isaac *allMat = A; 12913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1292b4457527SToby Isaac } 1293b4457527SToby Isaac 1294b4457527SToby Isaac /*@ 1295b4457527SToby Isaac PetscDualSpaceGetInteriorData - Get all quadrature points necessary to compute the interior degrees of freedom from 1296b4457527SToby Isaac this space, as well as the matrix that computes the degrees of freedom from the quadrature values. Degrees of 1297dce8aebaSBarry Smith freedom are interior degrees of freedom if they belong (by `PetscDualSpaceGetSection()`) to interior points in the 1298dce8aebaSBarry Smith reference `DMPLEX`: complementary boundary degrees of freedom are marked as constrained in the section returned by 1299dce8aebaSBarry Smith `PetscDualSpaceGetSection()`). 1300b4457527SToby Isaac 1301b4457527SToby Isaac Input Parameter: 1302b4457527SToby Isaac . sp - The dualspace 1303b4457527SToby Isaac 1304d8d19677SJose E. Roman Output Parameters: 1305dce8aebaSBarry Smith + intNodes - A `PetscQuadrature` object containing all evaluation points needed to evaluate interior degrees of freedom 1306b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1307dce8aebaSBarry Smith the size of the constrained layout (`PetscSectionGetConstrainStorageSize()`) of the dual space section, 1308dce8aebaSBarry Smith npoints is the number of points in intNodes and nc is `PetscDualSpaceGetNumComponents()`. 1309b4457527SToby Isaac 1310b4457527SToby Isaac Level: advanced 1311b4457527SToby Isaac 1312dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `Mat`, `PetscDualSpaceCreate()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceGetNumComponents()`, `PetscQuadratureGetData()` 1313b4457527SToby Isaac @*/ 1314d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetInteriorData(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1315d71ae5a4SJacob Faibussowitsch { 1316b4457527SToby Isaac PetscFunctionBegin; 1317b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1318b4457527SToby Isaac if (intNodes) PetscValidPointer(intNodes, 2); 1319b4457527SToby Isaac if (intMat) PetscValidPointer(intMat, 3); 1320b4457527SToby Isaac if ((!sp->intNodes || !sp->intMat) && sp->ops->createintdata) { 1321b4457527SToby Isaac PetscQuadrature qpoints; 1322b4457527SToby Isaac Mat imat; 1323b4457527SToby Isaac 1324dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createintdata, &qpoints, &imat); 13259566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->intNodes))); 13269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->intMat))); 1327b4457527SToby Isaac sp->intNodes = qpoints; 1328b4457527SToby Isaac sp->intMat = imat; 1329b4457527SToby Isaac } 1330b4457527SToby Isaac if (intNodes) *intNodes = sp->intNodes; 1331b4457527SToby Isaac if (intMat) *intMat = sp->intMat; 13323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1333b4457527SToby Isaac } 1334b4457527SToby Isaac 1335b4457527SToby Isaac /*@ 1336b4457527SToby Isaac PetscDualSpaceCreateInteriorDataDefault - Create quadrature points by examining interior functionals and create the matrix mapping quadrature point values to interior dual space values 1337b4457527SToby Isaac 1338b4457527SToby Isaac Input Parameter: 1339b4457527SToby Isaac . sp - The dualspace 1340b4457527SToby Isaac 1341d8d19677SJose E. Roman Output Parameters: 1342dce8aebaSBarry Smith + intNodes - A `PetscQuadrature` object containing all evaluation points needed to evaluate interior degrees of freedom 1343b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1344dce8aebaSBarry Smith the size of the constrained layout (`PetscSectionGetConstrainStorageSize()`) of the dual space section, 1345dce8aebaSBarry Smith npoints is the number of points in allNodes and nc is `PetscDualSpaceGetNumComponents()`. 1346b4457527SToby Isaac 1347b4457527SToby Isaac Level: advanced 1348b4457527SToby Isaac 1349dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `Mat`, `PetscDualSpaceCreate()`, `PetscDualSpaceGetInteriorData()` 1350b4457527SToby Isaac @*/ 1351d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreateInteriorDataDefault(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1352d71ae5a4SJacob Faibussowitsch { 1353b4457527SToby Isaac DM dm; 1354b4457527SToby Isaac PetscInt spdim0; 1355b4457527SToby Isaac PetscInt Nc; 1356b4457527SToby Isaac PetscInt pStart, pEnd, p, f; 1357b4457527SToby Isaac PetscSection section; 1358b4457527SToby Isaac PetscInt numPoints, offset, matoffset; 1359b4457527SToby Isaac PetscReal *points; 1360b4457527SToby Isaac PetscInt dim; 1361b4457527SToby Isaac PetscInt *nnz; 1362b4457527SToby Isaac PetscQuadrature q; 1363b4457527SToby Isaac Mat imat; 1364b4457527SToby Isaac 1365b4457527SToby Isaac PetscFunctionBegin; 1366b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 13679566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 13689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &spdim0)); 1369b4457527SToby Isaac if (!spdim0) { 1370b4457527SToby Isaac *intNodes = NULL; 1371b4457527SToby Isaac *intMat = NULL; 13723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1373b4457527SToby Isaac } 13749566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 13759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 13769566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 13779566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 13789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(spdim0, &nnz)); 1379b4457527SToby Isaac for (p = pStart, f = 0, numPoints = 0; p < pEnd; p++) { 1380b4457527SToby Isaac PetscInt dof, cdof, off, d; 1381b4457527SToby Isaac 13829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 13839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1384b4457527SToby Isaac if (!(dof - cdof)) continue; 13859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1386b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1387b4457527SToby Isaac PetscInt Np; 1388b4457527SToby Isaac 13899566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q)); 13909566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL)); 1391b4457527SToby Isaac nnz[f] = Np * Nc; 1392b4457527SToby Isaac numPoints += Np; 1393b4457527SToby Isaac } 1394b4457527SToby Isaac } 13959566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, spdim0, numPoints * Nc, 0, nnz, &imat)); 13969566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 13979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points)); 1398b4457527SToby Isaac for (p = pStart, f = 0, offset = 0, matoffset = 0; p < pEnd; p++) { 1399b4457527SToby Isaac PetscInt dof, cdof, off, d; 1400b4457527SToby Isaac 14019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 14029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1403b4457527SToby Isaac if (!(dof - cdof)) continue; 14049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1405b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1406b4457527SToby Isaac const PetscReal *p; 1407b4457527SToby Isaac const PetscReal *w; 1408b4457527SToby Isaac PetscInt Np, i; 1409b4457527SToby Isaac 14109566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q)); 14119566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, &p, &w)); 1412ad540459SPierre Jolivet for (i = 0; i < Np * dim; i++) points[offset + i] = p[i]; 141348a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(imat, f, matoffset + i, w[i], INSERT_VALUES)); 1414b4457527SToby Isaac offset += Np * dim; 1415b4457527SToby Isaac matoffset += Np * Nc; 1416b4457527SToby Isaac } 1417b4457527SToby Isaac } 14189566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, intNodes)); 14199566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*intNodes, dim, 0, numPoints, points, NULL)); 14209566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(imat, MAT_FINAL_ASSEMBLY)); 14219566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(imat, MAT_FINAL_ASSEMBLY)); 1422b4457527SToby Isaac *intMat = imat; 14233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 142420cf1dd8SToby Isaac } 142520cf1dd8SToby Isaac 14264f9ab2b4SJed Brown /*@ 1427dce8aebaSBarry Smith PetscDualSpaceEqual - Determine if two dual spaces are equivalent 14284f9ab2b4SJed Brown 14294f9ab2b4SJed Brown Input Parameters: 1430dce8aebaSBarry Smith + A - A `PetscDualSpace` object 1431dce8aebaSBarry Smith - B - Another `PetscDualSpace` object 14324f9ab2b4SJed Brown 14334f9ab2b4SJed Brown Output Parameter: 1434dce8aebaSBarry Smith . equal - `PETSC_TRUE` if the dual spaces are equivalent 14354f9ab2b4SJed Brown 14364f9ab2b4SJed Brown Level: advanced 14374f9ab2b4SJed Brown 1438dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 14394f9ab2b4SJed Brown @*/ 1440d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceEqual(PetscDualSpace A, PetscDualSpace B, PetscBool *equal) 1441d71ae5a4SJacob Faibussowitsch { 14424f9ab2b4SJed Brown PetscInt sizeA, sizeB, dimA, dimB; 14434f9ab2b4SJed Brown const PetscInt *dofA, *dofB; 14444f9ab2b4SJed Brown PetscQuadrature quadA, quadB; 14454f9ab2b4SJed Brown Mat matA, matB; 14464f9ab2b4SJed Brown 14474f9ab2b4SJed Brown PetscFunctionBegin; 14484f9ab2b4SJed Brown PetscValidHeaderSpecific(A, PETSCDUALSPACE_CLASSID, 1); 14494f9ab2b4SJed Brown PetscValidHeaderSpecific(B, PETSCDUALSPACE_CLASSID, 2); 14504f9ab2b4SJed Brown PetscValidBoolPointer(equal, 3); 14514f9ab2b4SJed Brown *equal = PETSC_FALSE; 14529566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(A, &sizeA)); 14539566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(B, &sizeB)); 14543ba16761SJacob Faibussowitsch if (sizeB != sizeA) PetscFunctionReturn(PETSC_SUCCESS); 14559566063dSJacob Faibussowitsch PetscCall(DMGetDimension(A->dm, &dimA)); 14569566063dSJacob Faibussowitsch PetscCall(DMGetDimension(B->dm, &dimB)); 14573ba16761SJacob Faibussowitsch if (dimA != dimB) PetscFunctionReturn(PETSC_SUCCESS); 14584f9ab2b4SJed Brown 14599566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(A, &dofA)); 14609566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(B, &dofB)); 14614f9ab2b4SJed Brown for (PetscInt d = 0; d < dimA; d++) { 14623ba16761SJacob Faibussowitsch if (dofA[d] != dofB[d]) PetscFunctionReturn(PETSC_SUCCESS); 14634f9ab2b4SJed Brown } 14644f9ab2b4SJed Brown 14659566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(A, &quadA, &matA)); 14669566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(B, &quadB, &matB)); 14674f9ab2b4SJed Brown if (!quadA && !quadB) { 14684f9ab2b4SJed Brown *equal = PETSC_TRUE; 14694f9ab2b4SJed Brown } else if (quadA && quadB) { 14709566063dSJacob Faibussowitsch PetscCall(PetscQuadratureEqual(quadA, quadB, equal)); 14713ba16761SJacob Faibussowitsch if (*equal == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS); 14723ba16761SJacob Faibussowitsch if (!matA && !matB) PetscFunctionReturn(PETSC_SUCCESS); 14739566063dSJacob Faibussowitsch if (matA && matB) PetscCall(MatEqual(matA, matB, equal)); 14744f9ab2b4SJed Brown else *equal = PETSC_FALSE; 14754f9ab2b4SJed Brown } 14763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14774f9ab2b4SJed Brown } 14784f9ab2b4SJed Brown 147920cf1dd8SToby Isaac /*@C 148020cf1dd8SToby Isaac PetscDualSpaceApplyFVM - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional at the cell centroid. 148120cf1dd8SToby Isaac 148220cf1dd8SToby Isaac Input Parameters: 1483dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 148420cf1dd8SToby Isaac . f - The basis functional index 148520cf1dd8SToby Isaac . time - The time 148620cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we currently just use the centroid 148720cf1dd8SToby Isaac . Nc - The number of components for the function 148820cf1dd8SToby Isaac . func - The input function 148920cf1dd8SToby Isaac - ctx - A context for the function 149020cf1dd8SToby Isaac 149120cf1dd8SToby Isaac Output Parameter: 149220cf1dd8SToby Isaac . value - The output value (scalar) 149320cf1dd8SToby Isaac 1494dce8aebaSBarry Smith Calling Sequence of func: 1495dce8aebaSBarry Smith .vb 1496dce8aebaSBarry Smith func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt numComponents, PetscScalar values[], void *ctx) 1497dce8aebaSBarry Smith .ve 1498dce8aebaSBarry Smith Level: advanced 149920cf1dd8SToby Isaac 1500dce8aebaSBarry Smith Note: 1501dce8aebaSBarry 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. 150220cf1dd8SToby Isaac 1503dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 150420cf1dd8SToby Isaac @*/ 1505d71ae5a4SJacob 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) 1506d71ae5a4SJacob Faibussowitsch { 150720cf1dd8SToby Isaac DM dm; 150820cf1dd8SToby Isaac PetscQuadrature n; 150920cf1dd8SToby Isaac const PetscReal *points, *weights; 151020cf1dd8SToby Isaac PetscScalar *val; 151120cf1dd8SToby Isaac PetscInt dimEmbed, qNc, c, Nq, q; 151220cf1dd8SToby Isaac 151320cf1dd8SToby Isaac PetscFunctionBegin; 151420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1515dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 15169566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 15179566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 15189566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 15199566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, NULL, &qNc, &Nq, &points, &weights)); 152063a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 15219566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 152220cf1dd8SToby Isaac *value = 0.; 152320cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 15249566063dSJacob Faibussowitsch PetscCall((*func)(dimEmbed, time, cgeom->centroid, Nc, val, ctx)); 1525ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) *value += val[c] * weights[q * Nc + c]; 152620cf1dd8SToby Isaac } 15279566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 15283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 152920cf1dd8SToby Isaac } 153020cf1dd8SToby Isaac 153120cf1dd8SToby Isaac /*@ 153220cf1dd8SToby Isaac PetscDualSpaceGetHeightSubspace - Get the subset of the dual space basis that is supported on a mesh point of a 153320cf1dd8SToby Isaac given height. This assumes that the reference cell is symmetric over points of this height. 153420cf1dd8SToby Isaac 153520cf1dd8SToby Isaac Not collective 153620cf1dd8SToby Isaac 153720cf1dd8SToby Isaac Input Parameters: 1538dce8aebaSBarry Smith + sp - the `PetscDualSpace` object 153920cf1dd8SToby Isaac - height - the height of the mesh point for which the subspace is desired 154020cf1dd8SToby Isaac 154120cf1dd8SToby Isaac Output Parameter: 154220cf1dd8SToby Isaac . subsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 154320cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 154420cf1dd8SToby Isaac 154520cf1dd8SToby Isaac Level: advanced 154620cf1dd8SToby Isaac 1547dce8aebaSBarry Smith Notes: 1548dce8aebaSBarry Smith If the dual space is not defined on mesh points of the given height (e.g. if the space is discontinuous and 1549dce8aebaSBarry Smith pointwise values are not defined on the element boundaries), or if the implementation of `PetscDualSpace` does not 1550dce8aebaSBarry Smith support extracting subspaces, then NULL is returned. 1551dce8aebaSBarry Smith 1552dce8aebaSBarry Smith This does not increment the reference count on the returned dual space, and the user should not destroy it. 1553dce8aebaSBarry Smith 1554dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscSpaceGetHeightSubspace()`, `PetscDualSpace`, `PetscDualSpaceGetPointSubspace()` 155520cf1dd8SToby Isaac @*/ 1556d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetHeightSubspace(PetscDualSpace sp, PetscInt height, PetscDualSpace *subsp) 1557d71ae5a4SJacob Faibussowitsch { 1558b4457527SToby Isaac PetscInt depth = -1, cStart, cEnd; 1559b4457527SToby Isaac DM dm; 156020cf1dd8SToby Isaac 156120cf1dd8SToby Isaac PetscFunctionBegin; 156220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1563064a246eSJacob Faibussowitsch PetscValidPointer(subsp, 3); 156408401ef6SPierre 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"); 156520cf1dd8SToby Isaac *subsp = NULL; 1566b4457527SToby Isaac dm = sp->dm; 15679566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 15681dca8a05SBarry Smith PetscCheck(height >= 0 && height <= depth, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid height"); 15699566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1570b4457527SToby Isaac if (height == 0 && cEnd == cStart + 1) { 1571b4457527SToby Isaac *subsp = sp; 15723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1573b4457527SToby Isaac } 1574b4457527SToby Isaac if (!sp->heightSpaces) { 1575b4457527SToby Isaac PetscInt h; 15769566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth + 1, &(sp->heightSpaces))); 1577b4457527SToby Isaac 1578b4457527SToby Isaac for (h = 0; h <= depth; h++) { 1579b4457527SToby Isaac if (h == 0 && cEnd == cStart + 1) continue; 15809566063dSJacob Faibussowitsch if (sp->ops->createheightsubspace) PetscCall((*sp->ops->createheightsubspace)(sp, height, &(sp->heightSpaces[h]))); 1581b4457527SToby Isaac else if (sp->pointSpaces) { 1582b4457527SToby Isaac PetscInt hStart, hEnd; 1583b4457527SToby Isaac 15849566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &hStart, &hEnd)); 1585b4457527SToby Isaac if (hEnd > hStart) { 1586665f567fSMatthew G. Knepley const char *name; 1587665f567fSMatthew G. Knepley 15889566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(sp->pointSpaces[hStart]))); 1589665f567fSMatthew G. Knepley if (sp->pointSpaces[hStart]) { 15909566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name)); 15919566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sp->pointSpaces[hStart], name)); 1592665f567fSMatthew G. Knepley } 1593b4457527SToby Isaac sp->heightSpaces[h] = sp->pointSpaces[hStart]; 1594b4457527SToby Isaac } 1595b4457527SToby Isaac } 1596b4457527SToby Isaac } 1597b4457527SToby Isaac } 1598b4457527SToby Isaac *subsp = sp->heightSpaces[height]; 15993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 160020cf1dd8SToby Isaac } 160120cf1dd8SToby Isaac 160220cf1dd8SToby Isaac /*@ 160320cf1dd8SToby Isaac PetscDualSpaceGetPointSubspace - Get the subset of the dual space basis that is supported on a particular mesh point. 160420cf1dd8SToby Isaac 160520cf1dd8SToby Isaac Not collective 160620cf1dd8SToby Isaac 160720cf1dd8SToby Isaac Input Parameters: 1608dce8aebaSBarry Smith + sp - the `PetscDualSpace` object 160920cf1dd8SToby Isaac - point - the point (in the dual space's DM) for which the subspace is desired 161020cf1dd8SToby Isaac 161120cf1dd8SToby Isaac Output Parameters: 1612dce8aebaSBarry Smith bdsp - the subspace. The functionals in the subspace are with respect to the intrinsic geometry of the 161320cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 161420cf1dd8SToby Isaac 161520cf1dd8SToby Isaac Level: advanced 161620cf1dd8SToby Isaac 1617dce8aebaSBarry Smith Notes: 1618dce8aebaSBarry Smith If the dual space is not defined on the mesh point (e.g. if the space is discontinuous and pointwise values are not 1619dce8aebaSBarry Smith defined on the element boundaries), or if the implementation of `PetscDualSpace` does not support extracting 1620dce8aebaSBarry Smith subspaces, then NULL is returned. 1621dce8aebaSBarry Smith 1622dce8aebaSBarry Smith This does not increment the reference count on the returned dual space, and the user should not destroy it. 1623dce8aebaSBarry Smith 1624dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetHeightSubspace()` 162520cf1dd8SToby Isaac @*/ 1626d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetPointSubspace(PetscDualSpace sp, PetscInt point, PetscDualSpace *bdsp) 1627d71ae5a4SJacob Faibussowitsch { 1628b4457527SToby Isaac PetscInt pStart = 0, pEnd = 0, cStart, cEnd; 1629b4457527SToby Isaac DM dm; 163020cf1dd8SToby Isaac 163120cf1dd8SToby Isaac PetscFunctionBegin; 163220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1633064a246eSJacob Faibussowitsch PetscValidPointer(bdsp, 3); 163420cf1dd8SToby Isaac *bdsp = NULL; 1635b4457527SToby Isaac dm = sp->dm; 16369566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 16371dca8a05SBarry Smith PetscCheck(point >= pStart && point <= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid point"); 16389566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1639b4457527SToby 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 */ 1640b4457527SToby Isaac *bdsp = sp; 16413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1642b4457527SToby Isaac } 1643b4457527SToby Isaac if (!sp->pointSpaces) { 1644b4457527SToby Isaac PetscInt p; 16459566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &(sp->pointSpaces))); 164620cf1dd8SToby Isaac 1647b4457527SToby Isaac for (p = 0; p < pEnd - pStart; p++) { 1648b4457527SToby Isaac if (p + pStart == cStart && cEnd == cStart + 1) continue; 16499566063dSJacob Faibussowitsch if (sp->ops->createpointsubspace) PetscCall((*sp->ops->createpointsubspace)(sp, p + pStart, &(sp->pointSpaces[p]))); 1650b4457527SToby Isaac else if (sp->heightSpaces || sp->ops->createheightsubspace) { 1651b4457527SToby Isaac PetscInt dim, depth, height; 1652b4457527SToby Isaac DMLabel label; 1653b4457527SToby Isaac 16549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &dim)); 16559566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 16569566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, p + pStart, &depth)); 165720cf1dd8SToby Isaac height = dim - depth; 16589566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(sp, height, &(sp->pointSpaces[p]))); 16599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sp->pointSpaces[p])); 166020cf1dd8SToby Isaac } 1661b4457527SToby Isaac } 1662b4457527SToby Isaac } 1663b4457527SToby Isaac *bdsp = sp->pointSpaces[point - pStart]; 16643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 166520cf1dd8SToby Isaac } 166620cf1dd8SToby Isaac 16676f905325SMatthew G. Knepley /*@C 16686f905325SMatthew G. Knepley PetscDualSpaceGetSymmetries - Returns a description of the symmetries of this basis 16696f905325SMatthew G. Knepley 16706f905325SMatthew G. Knepley Not collective 16716f905325SMatthew G. Knepley 16726f905325SMatthew G. Knepley Input Parameter: 1673dce8aebaSBarry Smith . sp - the `PetscDualSpace` object 16746f905325SMatthew G. Knepley 16756f905325SMatthew G. Knepley Output Parameters: 1676b4457527SToby Isaac + perms - Permutations of the interior degrees of freedom, parameterized by the point orientation 1677b4457527SToby Isaac - flips - Sign reversal of the interior degrees of freedom, parameterized by the point orientation 16786f905325SMatthew G. Knepley 16796f905325SMatthew G. Knepley Level: developer 16806f905325SMatthew G. Knepley 1681dce8aebaSBarry Smith Note: 1682dce8aebaSBarry Smith The permutation and flip arrays are organized in the following way 1683dce8aebaSBarry Smith .vb 1684dce8aebaSBarry Smith perms[p][ornt][dof # on point] = new local dof # 1685dce8aebaSBarry Smith flips[p][ornt][dof # on point] = reversal or not 1686dce8aebaSBarry Smith .ve 1687dce8aebaSBarry Smith 1688dce8aebaSBarry Smith .seealso: `PetscDualSpace` 16896f905325SMatthew G. Knepley @*/ 1690d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetSymmetries(PetscDualSpace sp, const PetscInt ****perms, const PetscScalar ****flips) 1691d71ae5a4SJacob Faibussowitsch { 16926f905325SMatthew G. Knepley PetscFunctionBegin; 16936f905325SMatthew G. Knepley PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 16949371c9d4SSatish Balay if (perms) { 16959371c9d4SSatish Balay PetscValidPointer(perms, 2); 16969371c9d4SSatish Balay *perms = NULL; 16979371c9d4SSatish Balay } 16989371c9d4SSatish Balay if (flips) { 16999371c9d4SSatish Balay PetscValidPointer(flips, 3); 17009371c9d4SSatish Balay *flips = NULL; 17019371c9d4SSatish Balay } 17029566063dSJacob Faibussowitsch if (sp->ops->getsymmetries) PetscCall((sp->ops->getsymmetries)(sp, perms, flips)); 17033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17046f905325SMatthew G. Knepley } 17054bee2e38SMatthew G. Knepley 17064bee2e38SMatthew G. Knepley /*@ 1707b4457527SToby Isaac PetscDualSpaceGetFormDegree - Get the form degree k for the k-form the describes the pushforwards/pullbacks of this 1708b4457527SToby Isaac dual space's functionals. 1709b4457527SToby Isaac 1710b4457527SToby Isaac Input Parameter: 1711dce8aebaSBarry Smith . dsp - The `PetscDualSpace` 1712b4457527SToby Isaac 1713b4457527SToby Isaac Output Parameter: 1714b4457527SToby 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 1715b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1716b4457527SToby 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). 1717b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1718b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1719b4457527SToby Isaac but are stored as 1-forms. 1720b4457527SToby Isaac 1721b4457527SToby Isaac Level: developer 1722b4457527SToby Isaac 1723dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 1724b4457527SToby Isaac @*/ 1725d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetFormDegree(PetscDualSpace dsp, PetscInt *k) 1726d71ae5a4SJacob Faibussowitsch { 1727b4457527SToby Isaac PetscFunctionBeginHot; 1728b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1729dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1730b4457527SToby Isaac *k = dsp->k; 17313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1732b4457527SToby Isaac } 1733b4457527SToby Isaac 1734b4457527SToby Isaac /*@ 1735b4457527SToby Isaac PetscDualSpaceSetFormDegree - Set the form degree k for the k-form the describes the pushforwards/pullbacks of this 1736b4457527SToby Isaac dual space's functionals. 1737b4457527SToby Isaac 1738d8d19677SJose E. Roman Input Parameters: 1739dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 1740b4457527SToby 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 1741b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1742b4457527SToby 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). 1743b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1744b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1745b4457527SToby Isaac but are stored as 1-forms. 1746b4457527SToby Isaac 1747b4457527SToby Isaac Level: developer 1748b4457527SToby Isaac 1749dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 1750b4457527SToby Isaac @*/ 1751d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetFormDegree(PetscDualSpace dsp, PetscInt k) 1752d71ae5a4SJacob Faibussowitsch { 1753b4457527SToby Isaac PetscInt dim; 1754b4457527SToby Isaac 1755b4457527SToby Isaac PetscFunctionBeginHot; 1756b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 175728b400f6SJacob Faibussowitsch PetscCheck(!dsp->setupcalled, PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 1758b4457527SToby Isaac dim = dsp->dm->dim; 17591dca8a05SBarry 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); 1760b4457527SToby Isaac dsp->k = k; 17613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1762b4457527SToby Isaac } 1763b4457527SToby Isaac 1764b4457527SToby Isaac /*@ 17654bee2e38SMatthew G. Knepley PetscDualSpaceGetDeRahm - Get the k-simplex associated with the functionals in this dual space 17664bee2e38SMatthew G. Knepley 17674bee2e38SMatthew G. Knepley Input Parameter: 1768dce8aebaSBarry Smith . dsp - The `PetscDualSpace` 17694bee2e38SMatthew G. Knepley 17704bee2e38SMatthew G. Knepley Output Parameter: 17714bee2e38SMatthew G. Knepley . k - The simplex dimension 17724bee2e38SMatthew G. Knepley 1773a4ce7ad1SMatthew G. Knepley Level: developer 17744bee2e38SMatthew G. Knepley 1775dce8aebaSBarry Smith Note: 1776dce8aebaSBarry Smith Currently supported values are 1777dce8aebaSBarry Smith .vb 1778dce8aebaSBarry Smith 0: These are H_1 methods that only transform coordinates 1779dce8aebaSBarry Smith 1: These are Hcurl methods that transform functions using the covariant Piola transform (COVARIANT_PIOLA_TRANSFORM) 1780dce8aebaSBarry Smith 2: These are the same as 1 1781dce8aebaSBarry Smith 3: These are Hdiv methods that transform functions using the contravariant Piola transform (CONTRAVARIANT_PIOLA_TRANSFORM) 1782dce8aebaSBarry Smith .ve 17834bee2e38SMatthew G. Knepley 1784dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 17854bee2e38SMatthew G. Knepley @*/ 1786d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDeRahm(PetscDualSpace dsp, PetscInt *k) 1787d71ae5a4SJacob Faibussowitsch { 1788b4457527SToby Isaac PetscInt dim; 1789b4457527SToby Isaac 17904bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 17914bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1792dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1793b4457527SToby Isaac dim = dsp->dm->dim; 1794b4457527SToby Isaac if (!dsp->k) *k = IDENTITY_TRANSFORM; 1795b4457527SToby Isaac else if (dsp->k == 1) *k = COVARIANT_PIOLA_TRANSFORM; 1796b4457527SToby Isaac else if (dsp->k == -(dim - 1)) *k = CONTRAVARIANT_PIOLA_TRANSFORM; 1797b4457527SToby Isaac else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unsupported transformation"); 17983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17994bee2e38SMatthew G. Knepley } 18004bee2e38SMatthew G. Knepley 18014bee2e38SMatthew G. Knepley /*@C 18024bee2e38SMatthew G. Knepley PetscDualSpaceTransform - Transform the function values 18034bee2e38SMatthew G. Knepley 18044bee2e38SMatthew G. Knepley Input Parameters: 1805dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 18064bee2e38SMatthew G. Knepley . trans - The type of transform 18074bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18084bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18094bee2e38SMatthew G. Knepley . Nv - The number of function samples 18104bee2e38SMatthew G. Knepley . Nc - The number of function components 18114bee2e38SMatthew G. Knepley - vals - The function values 18124bee2e38SMatthew G. Knepley 18134bee2e38SMatthew G. Knepley Output Parameter: 18144bee2e38SMatthew G. Knepley . vals - The transformed function values 18154bee2e38SMatthew G. Knepley 1816a4ce7ad1SMatthew G. Knepley Level: intermediate 18174bee2e38SMatthew G. Knepley 1818dce8aebaSBarry Smith Note: 1819dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18202edcad52SToby Isaac 1821dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransformGradient()`, `PetscDualSpaceTransformHessian()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 18224bee2e38SMatthew G. Knepley @*/ 1823d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransform(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 1824d71ae5a4SJacob Faibussowitsch { 1825b4457527SToby Isaac PetscReal Jstar[9] = {0}; 1826b4457527SToby Isaac PetscInt dim, v, c, Nk; 18274bee2e38SMatthew G. Knepley 18284bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18294bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18304bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1831dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 1832b4457527SToby Isaac /* TODO: not handling dimEmbed != dim right now */ 18332ae266adSMatthew G. Knepley dim = dsp->dm->dim; 1834b4457527SToby Isaac /* No change needed for 0-forms */ 18353ba16761SJacob Faibussowitsch if (!dsp->k) PetscFunctionReturn(PETSC_SUCCESS); 18369566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(dsp->k), &Nk)); 1837b4457527SToby Isaac /* TODO: use fegeom->isAffine */ 18389566063dSJacob Faibussowitsch PetscCall(PetscDTAltVPullbackMatrix(dim, dim, isInverse ? fegeom->J : fegeom->invJ, dsp->k, Jstar)); 18394bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1840b4457527SToby Isaac switch (Nk) { 1841b4457527SToby Isaac case 1: 1842b4457527SToby Isaac for (c = 0; c < Nc; c++) vals[v * Nc + c] *= Jstar[0]; 18434bee2e38SMatthew G. Knepley break; 1844b4457527SToby Isaac case 2: 1845b4457527SToby Isaac for (c = 0; c < Nc; c += 2) DMPlex_Mult2DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]); 18464bee2e38SMatthew G. Knepley break; 1847b4457527SToby Isaac case 3: 1848b4457527SToby Isaac for (c = 0; c < Nc; c += 3) DMPlex_Mult3DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]); 1849b4457527SToby Isaac break; 1850d71ae5a4SJacob Faibussowitsch default: 1851d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported form size %" PetscInt_FMT " for transformation", Nk); 1852b4457527SToby Isaac } 18534bee2e38SMatthew G. Knepley } 18543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18554bee2e38SMatthew G. Knepley } 1856b4457527SToby Isaac 18574bee2e38SMatthew G. Knepley /*@C 18584bee2e38SMatthew G. Knepley PetscDualSpaceTransformGradient - Transform the function gradient values 18594bee2e38SMatthew G. Knepley 18604bee2e38SMatthew G. Knepley Input Parameters: 1861dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 18624bee2e38SMatthew G. Knepley . trans - The type of transform 18634bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18644bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18654bee2e38SMatthew G. Knepley . Nv - The number of function gradient samples 18664bee2e38SMatthew G. Knepley . Nc - The number of function components 18674bee2e38SMatthew G. Knepley - vals - The function gradient values 18684bee2e38SMatthew G. Knepley 18694bee2e38SMatthew G. Knepley Output Parameter: 1870f9244615SMatthew G. Knepley . vals - The transformed function gradient values 18714bee2e38SMatthew G. Knepley 1872a4ce7ad1SMatthew G. Knepley Level: intermediate 18734bee2e38SMatthew G. Knepley 1874dce8aebaSBarry Smith Note: 1875dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18762edcad52SToby Isaac 1877dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 18784bee2e38SMatthew G. Knepley @*/ 1879d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransformGradient(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 1880d71ae5a4SJacob Faibussowitsch { 188127f02ce8SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 188227f02ce8SMatthew G. Knepley PetscInt v, c, d; 18834bee2e38SMatthew G. Knepley 18844bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18854bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18864bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1887dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 188827f02ce8SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 188963a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 189027f02ce8SMatthew G. Knepley #endif 18914bee2e38SMatthew G. Knepley /* Transform gradient */ 189227f02ce8SMatthew G. Knepley if (dim == dE) { 18934bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 18944bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 18959371c9d4SSatish Balay switch (dim) { 1896d71ae5a4SJacob Faibussowitsch case 1: 1897d71ae5a4SJacob Faibussowitsch vals[(v * Nc + c) * dim] *= fegeom->invJ[0]; 1898d71ae5a4SJacob Faibussowitsch break; 1899d71ae5a4SJacob Faibussowitsch case 2: 1900d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]); 1901d71ae5a4SJacob Faibussowitsch break; 1902d71ae5a4SJacob Faibussowitsch case 3: 1903d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]); 1904d71ae5a4SJacob Faibussowitsch break; 1905d71ae5a4SJacob Faibussowitsch default: 1906d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19074bee2e38SMatthew G. Knepley } 19084bee2e38SMatthew G. Knepley } 19094bee2e38SMatthew G. Knepley } 191027f02ce8SMatthew G. Knepley } else { 191127f02ce8SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1912ad540459SPierre 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]); 191327f02ce8SMatthew G. Knepley } 191427f02ce8SMatthew G. Knepley } 19154bee2e38SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 19163ba16761SJacob Faibussowitsch if (Nc == 1 || Nc != dim) PetscFunctionReturn(PETSC_SUCCESS); 19174bee2e38SMatthew G. Knepley switch (trans) { 1918d71ae5a4SJacob Faibussowitsch case IDENTITY_TRANSFORM: 1919d71ae5a4SJacob Faibussowitsch break; 19204bee2e38SMatthew G. Knepley case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 19214bee2e38SMatthew G. Knepley if (isInverse) { 19224bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19234bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19249371c9d4SSatish Balay switch (dim) { 1925d71ae5a4SJacob Faibussowitsch case 2: 1926d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1927d71ae5a4SJacob Faibussowitsch break; 1928d71ae5a4SJacob Faibussowitsch case 3: 1929d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1930d71ae5a4SJacob Faibussowitsch break; 1931d71ae5a4SJacob Faibussowitsch default: 1932d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19334bee2e38SMatthew G. Knepley } 19344bee2e38SMatthew G. Knepley } 19354bee2e38SMatthew G. Knepley } 19364bee2e38SMatthew G. Knepley } else { 19374bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19384bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19399371c9d4SSatish Balay switch (dim) { 1940d71ae5a4SJacob Faibussowitsch case 2: 1941d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1942d71ae5a4SJacob Faibussowitsch break; 1943d71ae5a4SJacob Faibussowitsch case 3: 1944d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1945d71ae5a4SJacob Faibussowitsch break; 1946d71ae5a4SJacob Faibussowitsch default: 1947d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19484bee2e38SMatthew G. Knepley } 19494bee2e38SMatthew G. Knepley } 19504bee2e38SMatthew G. Knepley } 19514bee2e38SMatthew G. Knepley } 19524bee2e38SMatthew G. Knepley break; 19534bee2e38SMatthew G. Knepley case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 19544bee2e38SMatthew G. Knepley if (isInverse) { 19554bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19564bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19579371c9d4SSatish Balay switch (dim) { 1958d71ae5a4SJacob Faibussowitsch case 2: 1959d71ae5a4SJacob Faibussowitsch DMPlex_Mult2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1960d71ae5a4SJacob Faibussowitsch break; 1961d71ae5a4SJacob Faibussowitsch case 3: 1962d71ae5a4SJacob Faibussowitsch DMPlex_Mult3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1963d71ae5a4SJacob Faibussowitsch break; 1964d71ae5a4SJacob Faibussowitsch default: 1965d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19664bee2e38SMatthew G. Knepley } 19674bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] *= fegeom->detJ[0]; 19684bee2e38SMatthew G. Knepley } 19694bee2e38SMatthew G. Knepley } 19704bee2e38SMatthew G. Knepley } else { 19714bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19724bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19739371c9d4SSatish Balay switch (dim) { 1974d71ae5a4SJacob Faibussowitsch case 2: 1975d71ae5a4SJacob Faibussowitsch DMPlex_Mult2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1976d71ae5a4SJacob Faibussowitsch break; 1977d71ae5a4SJacob Faibussowitsch case 3: 1978d71ae5a4SJacob Faibussowitsch DMPlex_Mult3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1979d71ae5a4SJacob Faibussowitsch break; 1980d71ae5a4SJacob Faibussowitsch default: 1981d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19824bee2e38SMatthew G. Knepley } 19834bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] /= fegeom->detJ[0]; 19844bee2e38SMatthew G. Knepley } 19854bee2e38SMatthew G. Knepley } 19864bee2e38SMatthew G. Knepley } 19874bee2e38SMatthew G. Knepley break; 19884bee2e38SMatthew G. Knepley } 19893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19904bee2e38SMatthew G. Knepley } 19914bee2e38SMatthew G. Knepley 19924bee2e38SMatthew G. Knepley /*@C 1993f9244615SMatthew G. Knepley PetscDualSpaceTransformHessian - Transform the function Hessian values 1994f9244615SMatthew G. Knepley 1995f9244615SMatthew G. Knepley Input Parameters: 1996dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 1997f9244615SMatthew G. Knepley . trans - The type of transform 1998f9244615SMatthew G. Knepley . isInverse - Flag to invert the transform 1999f9244615SMatthew G. Knepley . fegeom - The cell geometry 2000f9244615SMatthew G. Knepley . Nv - The number of function Hessian samples 2001f9244615SMatthew G. Knepley . Nc - The number of function components 2002f9244615SMatthew G. Knepley - vals - The function gradient values 2003f9244615SMatthew G. Knepley 2004f9244615SMatthew G. Knepley Output Parameter: 2005f9244615SMatthew G. Knepley . vals - The transformed function Hessian values 2006f9244615SMatthew G. Knepley 2007f9244615SMatthew G. Knepley Level: intermediate 2008f9244615SMatthew G. Knepley 2009dce8aebaSBarry Smith Note: 2010dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2011f9244615SMatthew G. Knepley 2012dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 2013f9244615SMatthew G. Knepley @*/ 2014d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransformHessian(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 2015d71ae5a4SJacob Faibussowitsch { 2016f9244615SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 2017f9244615SMatthew G. Knepley PetscInt v, c; 2018f9244615SMatthew G. Knepley 2019f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2020f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2021f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 4); 2022dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 2023f9244615SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 202463a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 2025f9244615SMatthew G. Knepley #endif 2026f9244615SMatthew G. Knepley /* Transform Hessian: J^{-T}_{ik} J^{-T}_{jl} H(f)_{kl} = J^{-T}_{ik} H(f)_{kl} J^{-1}_{lj} */ 2027f9244615SMatthew G. Knepley if (dim == dE) { 2028f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2029f9244615SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 20309371c9d4SSatish Balay switch (dim) { 2031d71ae5a4SJacob Faibussowitsch case 1: 2032d71ae5a4SJacob Faibussowitsch vals[(v * Nc + c) * dim * dim] *= PetscSqr(fegeom->invJ[0]); 2033d71ae5a4SJacob Faibussowitsch break; 2034d71ae5a4SJacob Faibussowitsch case 2: 2035d71ae5a4SJacob Faibussowitsch DMPlex_PTAP2DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]); 2036d71ae5a4SJacob Faibussowitsch break; 2037d71ae5a4SJacob Faibussowitsch case 3: 2038d71ae5a4SJacob Faibussowitsch DMPlex_PTAP3DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]); 2039d71ae5a4SJacob Faibussowitsch break; 2040d71ae5a4SJacob Faibussowitsch default: 2041d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 2042f9244615SMatthew G. Knepley } 2043f9244615SMatthew G. Knepley } 2044f9244615SMatthew G. Knepley } 2045f9244615SMatthew G. Knepley } else { 2046f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2047ad540459SPierre 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]); 2048f9244615SMatthew G. Knepley } 2049f9244615SMatthew G. Knepley } 2050f9244615SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 20513ba16761SJacob Faibussowitsch if (Nc == 1 || Nc != dim) PetscFunctionReturn(PETSC_SUCCESS); 2052f9244615SMatthew G. Knepley switch (trans) { 2053d71ae5a4SJacob Faibussowitsch case IDENTITY_TRANSFORM: 2054d71ae5a4SJacob Faibussowitsch break; 2055d71ae5a4SJacob Faibussowitsch case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 2056d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2057d71ae5a4SJacob Faibussowitsch case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 2058d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2059f9244615SMatthew G. Knepley } 20603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2061f9244615SMatthew G. Knepley } 2062f9244615SMatthew G. Knepley 2063f9244615SMatthew G. Knepley /*@C 20644bee2e38SMatthew 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. 20654bee2e38SMatthew G. Knepley 20664bee2e38SMatthew G. Knepley Input Parameters: 2067dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 20684bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 20694bee2e38SMatthew G. Knepley . Nq - The number of function samples 20704bee2e38SMatthew G. Knepley . Nc - The number of function components 20714bee2e38SMatthew G. Knepley - pointEval - The function values 20724bee2e38SMatthew G. Knepley 20734bee2e38SMatthew G. Knepley Output Parameter: 20744bee2e38SMatthew G. Knepley . pointEval - The transformed function values 20754bee2e38SMatthew G. Knepley 20764bee2e38SMatthew G. Knepley Level: advanced 20774bee2e38SMatthew G. Knepley 2078dce8aebaSBarry Smith Notes: 2079dce8aebaSBarry 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. 20804bee2e38SMatthew G. Knepley 2081da81f932SPierre Jolivet This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 20822edcad52SToby Isaac 2083dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 20844bee2e38SMatthew G. Knepley @*/ 2085d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePullback(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2086d71ae5a4SJacob Faibussowitsch { 20874bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2088b4457527SToby Isaac PetscInt k; 20894bee2e38SMatthew G. Knepley 20904bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 20914bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 20924bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2093dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 20944bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 20954bee2e38SMatthew G. Knepley This determines their transformation properties. */ 20969566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 20979371c9d4SSatish Balay switch (k) { 2098d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2099d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2100d71ae5a4SJacob Faibussowitsch break; 2101d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2102d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2103d71ae5a4SJacob Faibussowitsch break; 2104b4457527SToby Isaac case 2: 2105d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2106d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2107d71ae5a4SJacob Faibussowitsch break; 2108d71ae5a4SJacob Faibussowitsch default: 2109d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 21104bee2e38SMatthew G. Knepley } 21119566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_TRUE, fegeom, Nq, Nc, pointEval)); 21123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21134bee2e38SMatthew G. Knepley } 21144bee2e38SMatthew G. Knepley 21154bee2e38SMatthew G. Knepley /*@C 21164bee2e38SMatthew 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. 21174bee2e38SMatthew G. Knepley 21184bee2e38SMatthew G. Knepley Input Parameters: 2119dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 21204bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21214bee2e38SMatthew G. Knepley . Nq - The number of function samples 21224bee2e38SMatthew G. Knepley . Nc - The number of function components 21234bee2e38SMatthew G. Knepley - pointEval - The function values 21244bee2e38SMatthew G. Knepley 21254bee2e38SMatthew G. Knepley Output Parameter: 21264bee2e38SMatthew G. Knepley . pointEval - The transformed function values 21274bee2e38SMatthew G. Knepley 21284bee2e38SMatthew G. Knepley Level: advanced 21294bee2e38SMatthew G. Knepley 2130dce8aebaSBarry Smith Notes: 2131dce8aebaSBarry 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. 21324bee2e38SMatthew G. Knepley 2133dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21342edcad52SToby Isaac 2135dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 21364bee2e38SMatthew G. Knepley @*/ 2137d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforward(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2138d71ae5a4SJacob Faibussowitsch { 21394bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2140b4457527SToby Isaac PetscInt k; 21414bee2e38SMatthew G. Knepley 21424bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21434bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 21444bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2145dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 21464bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 21474bee2e38SMatthew G. Knepley This determines their transformation properties. */ 21489566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 21499371c9d4SSatish Balay switch (k) { 2150d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2151d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2152d71ae5a4SJacob Faibussowitsch break; 2153d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2154d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2155d71ae5a4SJacob Faibussowitsch break; 2156b4457527SToby Isaac case 2: 2157d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2158d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2159d71ae5a4SJacob Faibussowitsch break; 2160d71ae5a4SJacob Faibussowitsch default: 2161d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 21624bee2e38SMatthew G. Knepley } 21639566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 21643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21654bee2e38SMatthew G. Knepley } 21664bee2e38SMatthew G. Knepley 21674bee2e38SMatthew G. Knepley /*@C 21684bee2e38SMatthew 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. 21694bee2e38SMatthew G. Knepley 21704bee2e38SMatthew G. Knepley Input Parameters: 2171dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 21724bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21734bee2e38SMatthew G. Knepley . Nq - The number of function gradient samples 21744bee2e38SMatthew G. Knepley . Nc - The number of function components 21754bee2e38SMatthew G. Knepley - pointEval - The function gradient values 21764bee2e38SMatthew G. Knepley 21774bee2e38SMatthew G. Knepley Output Parameter: 21784bee2e38SMatthew G. Knepley . pointEval - The transformed function gradient values 21794bee2e38SMatthew G. Knepley 21804bee2e38SMatthew G. Knepley Level: advanced 21814bee2e38SMatthew G. Knepley 2182dce8aebaSBarry Smith Notes: 2183dce8aebaSBarry 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. 21844bee2e38SMatthew G. Knepley 2185dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21862edcad52SToby Isaac 2187dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2188dc0529c6SBarry Smith @*/ 2189d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforwardGradient(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2190d71ae5a4SJacob Faibussowitsch { 21914bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2192b4457527SToby Isaac PetscInt k; 21934bee2e38SMatthew G. Knepley 21944bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21954bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 21964bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2197dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 21984bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 21994bee2e38SMatthew G. Knepley This determines their transformation properties. */ 22009566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 22019371c9d4SSatish Balay switch (k) { 2202d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2203d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2204d71ae5a4SJacob Faibussowitsch break; 2205d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2206d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2207d71ae5a4SJacob Faibussowitsch break; 2208b4457527SToby Isaac case 2: 2209d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2210d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2211d71ae5a4SJacob Faibussowitsch break; 2212d71ae5a4SJacob Faibussowitsch default: 2213d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 22144bee2e38SMatthew G. Knepley } 22159566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformGradient(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 22163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22174bee2e38SMatthew G. Knepley } 2218f9244615SMatthew G. Knepley 2219f9244615SMatthew G. Knepley /*@C 2220f9244615SMatthew 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. 2221f9244615SMatthew G. Knepley 2222f9244615SMatthew G. Knepley Input Parameters: 2223dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 2224f9244615SMatthew G. Knepley . fegeom - The geometry for this cell 2225f9244615SMatthew G. Knepley . Nq - The number of function Hessian samples 2226f9244615SMatthew G. Knepley . Nc - The number of function components 2227f9244615SMatthew G. Knepley - pointEval - The function gradient values 2228f9244615SMatthew G. Knepley 2229f9244615SMatthew G. Knepley Output Parameter: 2230f9244615SMatthew G. Knepley . pointEval - The transformed function Hessian values 2231f9244615SMatthew G. Knepley 2232f9244615SMatthew G. Knepley Level: advanced 2233f9244615SMatthew G. Knepley 2234dce8aebaSBarry Smith Notes: 2235dce8aebaSBarry 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. 2236f9244615SMatthew G. Knepley 2237dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2238f9244615SMatthew G. Knepley 2239dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2240f9244615SMatthew G. Knepley @*/ 2241d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforwardHessian(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2242d71ae5a4SJacob Faibussowitsch { 2243f9244615SMatthew G. Knepley PetscDualSpaceTransformType trans; 2244f9244615SMatthew G. Knepley PetscInt k; 2245f9244615SMatthew G. Knepley 2246f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2247f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2248f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2249dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 2250f9244615SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 2251f9244615SMatthew G. Knepley This determines their transformation properties. */ 22529566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 22539371c9d4SSatish Balay switch (k) { 2254d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2255d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2256d71ae5a4SJacob Faibussowitsch break; 2257d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2258d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2259d71ae5a4SJacob Faibussowitsch break; 2260f9244615SMatthew G. Knepley case 2: 2261d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2262d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2263d71ae5a4SJacob Faibussowitsch break; 2264d71ae5a4SJacob Faibussowitsch default: 2265d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 2266f9244615SMatthew G. Knepley } 22679566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformHessian(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 22683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2269f9244615SMatthew G. Knepley } 2270