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: 22*20f4b53cSBarry Smith . 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: 53*20f4b53cSBarry Smith . 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 116*20f4b53cSBarry Smith Collective 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 209*20f4b53cSBarry Smith Collective 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 218*20f4b53cSBarry Smith Note: 219*20f4b53cSBarry Smith See `PetscObjectViewFromOptions()` for possible command line values 220*20f4b53cSBarry Smith 221db781477SPatrick Sanan .seealso: `PetscDualSpace`, `PetscDualSpaceView()`, `PetscObjectViewFromOptions()`, `PetscDualSpaceCreate()` 222fe2efc57SMark @*/ 223d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceViewFromOptions(PetscDualSpace A, PetscObject obj, const char name[]) 224d71ae5a4SJacob Faibussowitsch { 225fe2efc57SMark PetscFunctionBegin; 226fe2efc57SMark PetscValidHeaderSpecific(A, PETSCDUALSPACE_CLASSID, 1); 2279566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 2283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 229fe2efc57SMark } 230fe2efc57SMark 23120cf1dd8SToby Isaac /*@ 232dce8aebaSBarry Smith PetscDualSpaceView - Views a `PetscDualSpace` 23320cf1dd8SToby Isaac 234*20f4b53cSBarry Smith Collective 23520cf1dd8SToby Isaac 236d8d19677SJose E. Roman Input Parameters: 237dce8aebaSBarry Smith + sp - the `PetscDualSpace` object to view 23820cf1dd8SToby Isaac - v - the viewer 23920cf1dd8SToby Isaac 240a4ce7ad1SMatthew G. Knepley Level: beginner 24120cf1dd8SToby Isaac 242dce8aebaSBarry Smith .seealso: `PetscViewer`, `PetscDualSpaceDestroy()`, `PetscDualSpace` 24320cf1dd8SToby Isaac @*/ 244d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceView(PetscDualSpace sp, PetscViewer v) 245d71ae5a4SJacob Faibussowitsch { 246d9bac1caSLisandro Dalcin PetscBool iascii; 24720cf1dd8SToby Isaac 24820cf1dd8SToby Isaac PetscFunctionBegin; 24920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 250d9bac1caSLisandro Dalcin if (v) PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2); 2519566063dSJacob Faibussowitsch if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)sp), &v)); 2529566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii)); 2539566063dSJacob Faibussowitsch if (iascii) PetscCall(PetscDualSpaceView_ASCII(sp, v)); 2543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25520cf1dd8SToby Isaac } 25620cf1dd8SToby Isaac 25720cf1dd8SToby Isaac /*@ 258dce8aebaSBarry Smith PetscDualSpaceSetFromOptions - sets parameters in a `PetscDualSpace` from the options database 25920cf1dd8SToby Isaac 260*20f4b53cSBarry Smith Collective 26120cf1dd8SToby Isaac 26220cf1dd8SToby Isaac Input Parameter: 263dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to set options for 26420cf1dd8SToby Isaac 265dce8aebaSBarry Smith Options Database Keys: 2668f2aacc6SMatthew G. Knepley + -petscdualspace_order <order> - the approximation order of the space 267fe36a153SMatthew G. Knepley . -petscdualspace_form_degree <deg> - the form degree, say 0 for point evaluations, or 2 for area integrals 2688f2aacc6SMatthew G. Knepley . -petscdualspace_components <c> - the number of components, say d for a vector field 269a9c5e6deSMatthew G. Knepley . -petscdualspace_refcell <celltype> - Reference cell type name 270a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_continuity - Flag for continuous element 271a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_tensor - Flag for tensor dual space 272a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_trimmed - Flag for trimmed dual space 273a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_node_type <nodetype> - Lagrange node location type 274a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_node_endpoints - Flag for nodes that include endpoints 275a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_node_exponent - Gauss-Jacobi weight function exponent 276a9c5e6deSMatthew G. Knepley . -petscdualspace_lagrange_use_moments - Use moments (where appropriate) for functionals 277a9c5e6deSMatthew G. Knepley - -petscdualspace_lagrange_moment_order <order> - Quadrature order for moment functionals 27820cf1dd8SToby Isaac 279a4ce7ad1SMatthew G. Knepley Level: intermediate 28020cf1dd8SToby Isaac 281dce8aebaSBarry Smith .seealso: `PetscDualSpaceView()`, `PetscDualSpace`, `PetscObjectSetFromOptions()` 28220cf1dd8SToby Isaac @*/ 283d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetFromOptions(PetscDualSpace sp) 284d71ae5a4SJacob Faibussowitsch { 2852df84da0SMatthew G. Knepley DMPolytopeType refCell = DM_POLYTOPE_TRIANGLE; 28620cf1dd8SToby Isaac const char *defaultType; 28720cf1dd8SToby Isaac char name[256]; 288f783ec47SMatthew G. Knepley PetscBool flg; 28920cf1dd8SToby Isaac 29020cf1dd8SToby Isaac PetscFunctionBegin; 29120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 29220cf1dd8SToby Isaac if (!((PetscObject)sp)->type_name) { 29320cf1dd8SToby Isaac defaultType = PETSCDUALSPACELAGRANGE; 29420cf1dd8SToby Isaac } else { 29520cf1dd8SToby Isaac defaultType = ((PetscObject)sp)->type_name; 29620cf1dd8SToby Isaac } 2979566063dSJacob Faibussowitsch if (!PetscSpaceRegisterAllCalled) PetscCall(PetscSpaceRegisterAll()); 29820cf1dd8SToby Isaac 299d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)sp); 3009566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-petscdualspace_type", "Dual space", "PetscDualSpaceSetType", PetscDualSpaceList, defaultType, name, 256, &flg)); 30120cf1dd8SToby Isaac if (flg) { 3029566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, name)); 30320cf1dd8SToby Isaac } else if (!((PetscObject)sp)->type_name) { 3049566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(sp, defaultType)); 30520cf1dd8SToby Isaac } 3069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_order", "The approximation order", "PetscDualSpaceSetOrder", sp->order, &sp->order, NULL, 0)); 3079566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-petscdualspace_form_degree", "The form degree of the dofs", "PetscDualSpaceSetFormDegree", sp->k, &sp->k, NULL)); 3089566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-petscdualspace_components", "The number of components", "PetscDualSpaceSetNumComponents", sp->Nc, &sp->Nc, NULL, 1)); 309dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, setfromoptions, PetscOptionsObject); 3109566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-petscdualspace_refcell", "Reference cell shape", "PetscDualSpaceSetReferenceCell", DMPolytopeTypes, (PetscEnum)refCell, (PetscEnum *)&refCell, &flg)); 311063ee4adSMatthew G. Knepley if (flg) { 312063ee4adSMatthew G. Knepley DM K; 313063ee4adSMatthew G. Knepley 3149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, refCell, &K)); 3159566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(sp, K)); 3169566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 317063ee4adSMatthew G. Knepley } 318063ee4adSMatthew G. Knepley 31920cf1dd8SToby Isaac /* process any options handlers added with PetscObjectAddOptionsHandler() */ 320dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)sp, PetscOptionsObject)); 321d0609cedSBarry Smith PetscOptionsEnd(); 322063ee4adSMatthew G. Knepley sp->setfromoptionscalled = PETSC_TRUE; 3233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32420cf1dd8SToby Isaac } 32520cf1dd8SToby Isaac 32620cf1dd8SToby Isaac /*@ 327dce8aebaSBarry Smith PetscDualSpaceSetUp - Construct a basis for a `PetscDualSpace` 32820cf1dd8SToby Isaac 329*20f4b53cSBarry Smith Collective 33020cf1dd8SToby Isaac 33120cf1dd8SToby Isaac Input Parameter: 332dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to setup 33320cf1dd8SToby Isaac 334a4ce7ad1SMatthew G. Knepley Level: intermediate 33520cf1dd8SToby Isaac 336dce8aebaSBarry Smith .seealso: `PetscDualSpaceView()`, `PetscDualSpaceDestroy()`, `PetscDualSpace` 33720cf1dd8SToby Isaac @*/ 338d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetUp(PetscDualSpace sp) 339d71ae5a4SJacob Faibussowitsch { 34020cf1dd8SToby Isaac PetscFunctionBegin; 34120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 3423ba16761SJacob Faibussowitsch if (sp->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3439566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 34420cf1dd8SToby Isaac sp->setupcalled = PETSC_TRUE; 345dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, setup); 3469566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 3479566063dSJacob Faibussowitsch if (sp->setfromoptionscalled) PetscCall(PetscDualSpaceViewFromOptions(sp, NULL, "-petscdualspace_view")); 3483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34920cf1dd8SToby Isaac } 35020cf1dd8SToby Isaac 351d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDualSpaceClearDMData_Internal(PetscDualSpace sp, DM dm) 352d71ae5a4SJacob Faibussowitsch { 353b4457527SToby Isaac PetscInt pStart = -1, pEnd = -1, depth = -1; 354b4457527SToby Isaac 355b4457527SToby Isaac PetscFunctionBegin; 3563ba16761SJacob Faibussowitsch if (!dm) PetscFunctionReturn(PETSC_SUCCESS); 3579566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 359b4457527SToby Isaac 360b4457527SToby Isaac if (sp->pointSpaces) { 361b4457527SToby Isaac PetscInt i; 362b4457527SToby Isaac 36348a46eb9SPierre Jolivet for (i = 0; i < pEnd - pStart; i++) PetscCall(PetscDualSpaceDestroy(&(sp->pointSpaces[i]))); 364b4457527SToby Isaac } 3659566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->pointSpaces)); 366b4457527SToby Isaac 367b4457527SToby Isaac if (sp->heightSpaces) { 368b4457527SToby Isaac PetscInt i; 369b4457527SToby Isaac 37048a46eb9SPierre Jolivet for (i = 0; i <= depth; i++) PetscCall(PetscDualSpaceDestroy(&(sp->heightSpaces[i]))); 371b4457527SToby Isaac } 3729566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->heightSpaces)); 373b4457527SToby Isaac 3749566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(sp->pointSection))); 3759566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->intNodes))); 3769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->intDofValues))); 3779566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->intNodeValues))); 3789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->intMat))); 3799566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->allNodes))); 3809566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->allDofValues))); 3819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&(sp->allNodeValues))); 3829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->allMat))); 3839566063dSJacob Faibussowitsch PetscCall(PetscFree(sp->numDof)); 3843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 385b4457527SToby Isaac } 386b4457527SToby Isaac 38720cf1dd8SToby Isaac /*@ 388dce8aebaSBarry Smith PetscDualSpaceDestroy - Destroys a `PetscDualSpace` object 38920cf1dd8SToby Isaac 390*20f4b53cSBarry Smith Collective 39120cf1dd8SToby Isaac 39220cf1dd8SToby Isaac Input Parameter: 393dce8aebaSBarry Smith . sp - the `PetscDualSpace` object to destroy 39420cf1dd8SToby Isaac 395a4ce7ad1SMatthew G. Knepley Level: beginner 39620cf1dd8SToby Isaac 397dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceView()`, `PetscDualSpace()`, `PetscDualSpaceCreate()` 39820cf1dd8SToby Isaac @*/ 399d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceDestroy(PetscDualSpace *sp) 400d71ae5a4SJacob Faibussowitsch { 40120cf1dd8SToby Isaac PetscInt dim, f; 402b4457527SToby Isaac DM dm; 40320cf1dd8SToby Isaac 40420cf1dd8SToby Isaac PetscFunctionBegin; 4053ba16761SJacob Faibussowitsch if (!*sp) PetscFunctionReturn(PETSC_SUCCESS); 40620cf1dd8SToby Isaac PetscValidHeaderSpecific((*sp), PETSCDUALSPACE_CLASSID, 1); 40720cf1dd8SToby Isaac 4089371c9d4SSatish Balay if (--((PetscObject)(*sp))->refct > 0) { 4099371c9d4SSatish Balay *sp = NULL; 4103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4119371c9d4SSatish Balay } 41220cf1dd8SToby Isaac ((PetscObject)(*sp))->refct = 0; 41320cf1dd8SToby Isaac 4149566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(*sp, &dim)); 415b4457527SToby Isaac dm = (*sp)->dm; 416b4457527SToby Isaac 417dbbe0bcdSBarry Smith PetscTryTypeMethod((*sp), destroy); 4189566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceClearDMData_Internal(*sp, dm)); 419b4457527SToby Isaac 42048a46eb9SPierre Jolivet for (f = 0; f < dim; ++f) PetscCall(PetscQuadratureDestroy(&(*sp)->functional[f])); 4219566063dSJacob Faibussowitsch PetscCall(PetscFree((*sp)->functional)); 4229566063dSJacob Faibussowitsch PetscCall(DMDestroy(&(*sp)->dm)); 4239566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(sp)); 4243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42520cf1dd8SToby Isaac } 42620cf1dd8SToby Isaac 42720cf1dd8SToby Isaac /*@ 428dce8aebaSBarry Smith PetscDualSpaceCreate - Creates an empty `PetscDualSpace` object. The type can then be set with `PetscDualSpaceSetType()`. 42920cf1dd8SToby Isaac 430d083f849SBarry Smith Collective 43120cf1dd8SToby Isaac 43220cf1dd8SToby Isaac Input Parameter: 433dce8aebaSBarry Smith . comm - The communicator for the `PetscDualSpace` object 43420cf1dd8SToby Isaac 43520cf1dd8SToby Isaac Output Parameter: 436dce8aebaSBarry Smith . sp - The `PetscDualSpace` object 43720cf1dd8SToby Isaac 43820cf1dd8SToby Isaac Level: beginner 43920cf1dd8SToby Isaac 440dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetType()`, `PETSCDUALSPACELAGRANGE` 44120cf1dd8SToby Isaac @*/ 442d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreate(MPI_Comm comm, PetscDualSpace *sp) 443d71ae5a4SJacob Faibussowitsch { 44420cf1dd8SToby Isaac PetscDualSpace s; 44520cf1dd8SToby Isaac 44620cf1dd8SToby Isaac PetscFunctionBegin; 44720cf1dd8SToby Isaac PetscValidPointer(sp, 2); 4489566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(FECitation, &FEcite)); 44920cf1dd8SToby Isaac *sp = NULL; 4509566063dSJacob Faibussowitsch PetscCall(PetscFEInitializePackage()); 45120cf1dd8SToby Isaac 4529566063dSJacob Faibussowitsch PetscCall(PetscHeaderCreate(s, PETSCDUALSPACE_CLASSID, "PetscDualSpace", "Dual Space", "PetscDualSpace", comm, PetscDualSpaceDestroy, PetscDualSpaceView)); 45320cf1dd8SToby Isaac 45420cf1dd8SToby Isaac s->order = 0; 45520cf1dd8SToby Isaac s->Nc = 1; 4564bee2e38SMatthew G. Knepley s->k = 0; 457b4457527SToby Isaac s->spdim = -1; 458b4457527SToby Isaac s->spintdim = -1; 459b4457527SToby Isaac s->uniform = PETSC_TRUE; 46020cf1dd8SToby Isaac s->setupcalled = PETSC_FALSE; 46120cf1dd8SToby Isaac 46220cf1dd8SToby Isaac *sp = s; 4633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46420cf1dd8SToby Isaac } 46520cf1dd8SToby Isaac 46620cf1dd8SToby Isaac /*@ 467dce8aebaSBarry Smith PetscDualSpaceDuplicate - Creates a duplicate `PetscDualSpace` object that is not setup. 46820cf1dd8SToby Isaac 469*20f4b53cSBarry Smith Collective 47020cf1dd8SToby Isaac 47120cf1dd8SToby Isaac Input Parameter: 472dce8aebaSBarry Smith . sp - The original `PetscDualSpace` 47320cf1dd8SToby Isaac 47420cf1dd8SToby Isaac Output Parameter: 475dce8aebaSBarry Smith . spNew - The duplicate `PetscDualSpace` 47620cf1dd8SToby Isaac 47720cf1dd8SToby Isaac Level: beginner 47820cf1dd8SToby Isaac 479dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`, `PetscDualSpaceSetType()` 48020cf1dd8SToby Isaac @*/ 481d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceDuplicate(PetscDualSpace sp, PetscDualSpace *spNew) 482d71ae5a4SJacob Faibussowitsch { 483b4457527SToby Isaac DM dm; 484b4457527SToby Isaac PetscDualSpaceType type; 485b4457527SToby Isaac const char *name; 48620cf1dd8SToby Isaac 48720cf1dd8SToby Isaac PetscFunctionBegin; 48820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 48920cf1dd8SToby Isaac PetscValidPointer(spNew, 2); 4909566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(PetscObjectComm((PetscObject)sp), spNew)); 4919566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name)); 4929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*spNew, name)); 4939566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetType(sp, &type)); 4949566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(*spNew, type)); 4959566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 4969566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(*spNew, dm)); 497b4457527SToby Isaac 498b4457527SToby Isaac (*spNew)->order = sp->order; 499b4457527SToby Isaac (*spNew)->k = sp->k; 500b4457527SToby Isaac (*spNew)->Nc = sp->Nc; 501b4457527SToby Isaac (*spNew)->uniform = sp->uniform; 502dbbe0bcdSBarry Smith PetscTryTypeMethod(sp, duplicate, *spNew); 5033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50420cf1dd8SToby Isaac } 50520cf1dd8SToby Isaac 50620cf1dd8SToby Isaac /*@ 507dce8aebaSBarry Smith PetscDualSpaceGetDM - Get the `DM` representing the reference cell of a `PetscDualSpace` 50820cf1dd8SToby Isaac 509*20f4b53cSBarry Smith Not Collective 51020cf1dd8SToby Isaac 51120cf1dd8SToby Isaac Input Parameter: 512dce8aebaSBarry Smith . sp - The `PetscDualSpace` 51320cf1dd8SToby Isaac 51420cf1dd8SToby Isaac Output Parameter: 515dce8aebaSBarry Smith . dm - The reference cell, that is a `DM` that consists of a single cell 51620cf1dd8SToby Isaac 51720cf1dd8SToby Isaac Level: intermediate 51820cf1dd8SToby Isaac 519dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetDM()`, `PetscDualSpaceCreate()` 52020cf1dd8SToby Isaac @*/ 521d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDM(PetscDualSpace sp, DM *dm) 522d71ae5a4SJacob Faibussowitsch { 52320cf1dd8SToby Isaac PetscFunctionBegin; 52420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 52520cf1dd8SToby Isaac PetscValidPointer(dm, 2); 52620cf1dd8SToby Isaac *dm = sp->dm; 5273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52820cf1dd8SToby Isaac } 52920cf1dd8SToby Isaac 53020cf1dd8SToby Isaac /*@ 531dce8aebaSBarry Smith PetscDualSpaceSetDM - Get the `DM` representing the reference cell 53220cf1dd8SToby Isaac 533*20f4b53cSBarry Smith Not Collective 53420cf1dd8SToby Isaac 53520cf1dd8SToby Isaac Input Parameters: 536dce8aebaSBarry Smith + sp - The `PetscDual`Space 53720cf1dd8SToby Isaac - dm - The reference cell 53820cf1dd8SToby Isaac 53920cf1dd8SToby Isaac Level: intermediate 54020cf1dd8SToby Isaac 541dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `DM`, `PetscDualSpaceGetDM()`, `PetscDualSpaceCreate()` 54220cf1dd8SToby Isaac @*/ 543d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetDM(PetscDualSpace sp, DM dm) 544d71ae5a4SJacob Faibussowitsch { 54520cf1dd8SToby Isaac PetscFunctionBegin; 54620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 54720cf1dd8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 54828b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change DM after dualspace is set up"); 5499566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 55048a46eb9SPierre Jolivet if (sp->dm && sp->dm != dm) PetscCall(PetscDualSpaceClearDMData_Internal(sp, sp->dm)); 5519566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sp->dm)); 55220cf1dd8SToby Isaac sp->dm = dm; 5533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55420cf1dd8SToby Isaac } 55520cf1dd8SToby Isaac 55620cf1dd8SToby Isaac /*@ 55720cf1dd8SToby Isaac PetscDualSpaceGetOrder - Get the order of the dual space 55820cf1dd8SToby Isaac 559*20f4b53cSBarry Smith Not Collective 56020cf1dd8SToby Isaac 56120cf1dd8SToby Isaac Input Parameter: 562dce8aebaSBarry Smith . sp - The `PetscDualSpace` 56320cf1dd8SToby Isaac 56420cf1dd8SToby Isaac Output Parameter: 56520cf1dd8SToby Isaac . order - The order 56620cf1dd8SToby Isaac 56720cf1dd8SToby Isaac Level: intermediate 56820cf1dd8SToby Isaac 569dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceSetOrder()`, `PetscDualSpaceCreate()` 57020cf1dd8SToby Isaac @*/ 571d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetOrder(PetscDualSpace sp, PetscInt *order) 572d71ae5a4SJacob Faibussowitsch { 57320cf1dd8SToby Isaac PetscFunctionBegin; 57420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 575dadcf809SJacob Faibussowitsch PetscValidIntPointer(order, 2); 57620cf1dd8SToby Isaac *order = sp->order; 5773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57820cf1dd8SToby Isaac } 57920cf1dd8SToby Isaac 58020cf1dd8SToby Isaac /*@ 58120cf1dd8SToby Isaac PetscDualSpaceSetOrder - Set the order of the dual space 58220cf1dd8SToby Isaac 583*20f4b53cSBarry Smith Not Collective 58420cf1dd8SToby Isaac 58520cf1dd8SToby Isaac Input Parameters: 586dce8aebaSBarry Smith + sp - The `PetscDualSpace` 58720cf1dd8SToby Isaac - order - The order 58820cf1dd8SToby Isaac 58920cf1dd8SToby Isaac Level: intermediate 59020cf1dd8SToby Isaac 591dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetOrder()`, `PetscDualSpaceCreate()` 59220cf1dd8SToby Isaac @*/ 593d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetOrder(PetscDualSpace sp, PetscInt order) 594d71ae5a4SJacob Faibussowitsch { 59520cf1dd8SToby Isaac PetscFunctionBegin; 59620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 59728b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change order after dualspace is set up"); 59820cf1dd8SToby Isaac sp->order = order; 5993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60020cf1dd8SToby Isaac } 60120cf1dd8SToby Isaac 60220cf1dd8SToby Isaac /*@ 60320cf1dd8SToby Isaac PetscDualSpaceGetNumComponents - Return the number of components for this space 60420cf1dd8SToby Isaac 60520cf1dd8SToby Isaac Input Parameter: 606dce8aebaSBarry Smith . sp - The `PetscDualSpace` 60720cf1dd8SToby Isaac 60820cf1dd8SToby Isaac Output Parameter: 60920cf1dd8SToby Isaac . Nc - The number of components 61020cf1dd8SToby Isaac 61120cf1dd8SToby Isaac Level: intermediate 61220cf1dd8SToby Isaac 613dce8aebaSBarry Smith Note: 614dce8aebaSBarry Smith A vector space, for example, will have d components, where d is the spatial dimension 615dce8aebaSBarry Smith 616db781477SPatrick Sanan .seealso: `PetscDualSpaceSetNumComponents()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 61720cf1dd8SToby Isaac @*/ 618d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetNumComponents(PetscDualSpace sp, PetscInt *Nc) 619d71ae5a4SJacob Faibussowitsch { 62020cf1dd8SToby Isaac PetscFunctionBegin; 62120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 622dadcf809SJacob Faibussowitsch PetscValidIntPointer(Nc, 2); 62320cf1dd8SToby Isaac *Nc = sp->Nc; 6243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 62520cf1dd8SToby Isaac } 62620cf1dd8SToby Isaac 62720cf1dd8SToby Isaac /*@ 62820cf1dd8SToby Isaac PetscDualSpaceSetNumComponents - Set the number of components for this space 62920cf1dd8SToby Isaac 63020cf1dd8SToby Isaac Input Parameters: 631dce8aebaSBarry Smith + sp - The `PetscDualSpace` 63220cf1dd8SToby Isaac - order - The number of components 63320cf1dd8SToby Isaac 63420cf1dd8SToby Isaac Level: intermediate 63520cf1dd8SToby Isaac 636db781477SPatrick Sanan .seealso: `PetscDualSpaceGetNumComponents()`, `PetscDualSpaceCreate()`, `PetscDualSpace` 63720cf1dd8SToby Isaac @*/ 638d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetNumComponents(PetscDualSpace sp, PetscInt Nc) 639d71ae5a4SJacob Faibussowitsch { 64020cf1dd8SToby Isaac PetscFunctionBegin; 64120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 64228b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 64320cf1dd8SToby Isaac sp->Nc = Nc; 6443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64520cf1dd8SToby Isaac } 64620cf1dd8SToby Isaac 64720cf1dd8SToby Isaac /*@ 64820cf1dd8SToby Isaac PetscDualSpaceGetFunctional - Get the i-th basis functional in the dual space 64920cf1dd8SToby Isaac 650*20f4b53cSBarry Smith Not Collective 65120cf1dd8SToby Isaac 65220cf1dd8SToby Isaac Input Parameters: 653dce8aebaSBarry Smith + sp - The `PetscDualSpace` 65420cf1dd8SToby Isaac - i - The basis number 65520cf1dd8SToby Isaac 65620cf1dd8SToby Isaac Output Parameter: 65720cf1dd8SToby Isaac . functional - The basis functional 65820cf1dd8SToby Isaac 65920cf1dd8SToby Isaac Level: intermediate 66020cf1dd8SToby Isaac 661dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceCreate()` 66220cf1dd8SToby Isaac @*/ 663d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetFunctional(PetscDualSpace sp, PetscInt i, PetscQuadrature *functional) 664d71ae5a4SJacob Faibussowitsch { 66520cf1dd8SToby Isaac PetscInt dim; 66620cf1dd8SToby Isaac 66720cf1dd8SToby Isaac PetscFunctionBegin; 66820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 66920cf1dd8SToby Isaac PetscValidPointer(functional, 3); 6709566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &dim)); 67163a3b9bcSJacob 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); 67220cf1dd8SToby Isaac *functional = sp->functional[i]; 6733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 67420cf1dd8SToby Isaac } 67520cf1dd8SToby Isaac 67620cf1dd8SToby Isaac /*@ 67720cf1dd8SToby Isaac PetscDualSpaceGetDimension - Get the dimension of the dual space, i.e. the number of basis functionals 67820cf1dd8SToby Isaac 679*20f4b53cSBarry Smith Not Collective 68020cf1dd8SToby Isaac 68120cf1dd8SToby Isaac Input Parameter: 682dce8aebaSBarry Smith . sp - The `PetscDualSpace` 68320cf1dd8SToby Isaac 68420cf1dd8SToby Isaac Output Parameter: 68520cf1dd8SToby Isaac . dim - The dimension 68620cf1dd8SToby Isaac 68720cf1dd8SToby Isaac Level: intermediate 68820cf1dd8SToby Isaac 689dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 69020cf1dd8SToby Isaac @*/ 691d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDimension(PetscDualSpace sp, PetscInt *dim) 692d71ae5a4SJacob Faibussowitsch { 69320cf1dd8SToby Isaac PetscFunctionBegin; 69420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 695dadcf809SJacob Faibussowitsch PetscValidIntPointer(dim, 2); 696b4457527SToby Isaac if (sp->spdim < 0) { 697b4457527SToby Isaac PetscSection section; 698b4457527SToby Isaac 6999566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 700b4457527SToby Isaac if (section) { 7019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &(sp->spdim))); 702b4457527SToby Isaac } else sp->spdim = 0; 703b4457527SToby Isaac } 704b4457527SToby Isaac *dim = sp->spdim; 7053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70620cf1dd8SToby Isaac } 70720cf1dd8SToby Isaac 708b4457527SToby Isaac /*@ 709b4457527SToby 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 710b4457527SToby Isaac 711*20f4b53cSBarry Smith Not Collective 712b4457527SToby Isaac 713b4457527SToby Isaac Input Parameter: 714dce8aebaSBarry Smith . sp - The `PetscDualSpace` 715b4457527SToby Isaac 716b4457527SToby Isaac Output Parameter: 717b4457527SToby Isaac . dim - The dimension 718b4457527SToby Isaac 719b4457527SToby Isaac Level: intermediate 720b4457527SToby Isaac 721dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 722b4457527SToby Isaac @*/ 723d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetInteriorDimension(PetscDualSpace sp, PetscInt *intdim) 724d71ae5a4SJacob Faibussowitsch { 725b4457527SToby Isaac PetscFunctionBegin; 726b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 727dadcf809SJacob Faibussowitsch PetscValidIntPointer(intdim, 2); 728b4457527SToby Isaac if (sp->spintdim < 0) { 729b4457527SToby Isaac PetscSection section; 730b4457527SToby Isaac 7319566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 732b4457527SToby Isaac if (section) { 7339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &(sp->spintdim))); 734b4457527SToby Isaac } else sp->spintdim = 0; 735b4457527SToby Isaac } 736b4457527SToby Isaac *intdim = sp->spintdim; 7373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 738b4457527SToby Isaac } 739b4457527SToby Isaac 740b4457527SToby Isaac /*@ 741b4457527SToby Isaac PetscDualSpaceGetUniform - Whether this dual space is uniform 742b4457527SToby Isaac 743*20f4b53cSBarry Smith Not Collective 744b4457527SToby Isaac 745b4457527SToby Isaac Input Parameters: 746b4457527SToby Isaac . sp - A dual space 747b4457527SToby Isaac 748b4457527SToby Isaac Output Parameters: 749dce8aebaSBarry Smith . uniform - `PETSC_TRUE` if (a) the dual space is the same for each point in a stratum of the reference `DMPLEX`, and 750dce8aebaSBarry Smith (b) every symmetry of each point in the reference `DMPLEX` is also a symmetry of the point's dual space. 751b4457527SToby Isaac 752b4457527SToby Isaac Level: advanced 753b4457527SToby Isaac 754dce8aebaSBarry Smith Note: 755dce8aebaSBarry Smith All of the usual spaces on simplex or tensor-product elements will be uniform, only reference cells 756b4457527SToby Isaac with non-uniform strata (like trianguar-prisms) or anisotropic hp dual spaces will not be uniform. 757b4457527SToby Isaac 758dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetPointSubspace()`, `PetscDualSpaceGetSymmetries()` 759b4457527SToby Isaac @*/ 760d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetUniform(PetscDualSpace sp, PetscBool *uniform) 761d71ae5a4SJacob Faibussowitsch { 762b4457527SToby Isaac PetscFunctionBegin; 763b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 764dadcf809SJacob Faibussowitsch PetscValidBoolPointer(uniform, 2); 765b4457527SToby Isaac *uniform = sp->uniform; 7663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 767b4457527SToby Isaac } 768b4457527SToby Isaac 76920cf1dd8SToby Isaac /*@C 77020cf1dd8SToby Isaac PetscDualSpaceGetNumDof - Get the number of degrees of freedom for each spatial (topological) dimension 77120cf1dd8SToby Isaac 772*20f4b53cSBarry Smith Not Collective 77320cf1dd8SToby Isaac 77420cf1dd8SToby Isaac Input Parameter: 775dce8aebaSBarry Smith . sp - The `PetscDualSpace` 77620cf1dd8SToby Isaac 77720cf1dd8SToby Isaac Output Parameter: 77820cf1dd8SToby Isaac . numDof - An array of length dim+1 which holds the number of dofs for each dimension 77920cf1dd8SToby Isaac 78020cf1dd8SToby Isaac Level: intermediate 78120cf1dd8SToby Isaac 782dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetFunctional()`, `PetscDualSpaceCreate()` 78320cf1dd8SToby Isaac @*/ 784d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetNumDof(PetscDualSpace sp, const PetscInt **numDof) 785d71ae5a4SJacob Faibussowitsch { 78620cf1dd8SToby Isaac PetscFunctionBegin; 78720cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 78820cf1dd8SToby Isaac PetscValidPointer(numDof, 2); 78928b400f6SJacob 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"); 790b4457527SToby Isaac if (!sp->numDof) { 791b4457527SToby Isaac DM dm; 792b4457527SToby Isaac PetscInt depth, d; 793b4457527SToby Isaac PetscSection section; 794b4457527SToby Isaac 7959566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 7969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 7979566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth + 1, &(sp->numDof))); 7989566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 799b4457527SToby Isaac for (d = 0; d <= depth; d++) { 800b4457527SToby Isaac PetscInt dStart, dEnd; 801b4457527SToby Isaac 8029566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 803b4457527SToby Isaac if (dEnd <= dStart) continue; 8049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, dStart, &(sp->numDof[d]))); 805b4457527SToby Isaac } 806b4457527SToby Isaac } 807b4457527SToby Isaac *numDof = sp->numDof; 80808401ef6SPierre Jolivet PetscCheck(*numDof, PetscObjectComm((PetscObject)sp), PETSC_ERR_LIB, "Empty numDof[] returned from dual space implementation"); 8093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81020cf1dd8SToby Isaac } 81120cf1dd8SToby Isaac 812b4457527SToby Isaac /* create the section of the right size and set a permutation for topological ordering */ 813d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSectionCreate_Internal(PetscDualSpace sp, PetscSection *topSection) 814d71ae5a4SJacob Faibussowitsch { 815b4457527SToby Isaac DM dm; 816b4457527SToby Isaac PetscInt pStart, pEnd, cStart, cEnd, c, depth, count, i; 817b4457527SToby Isaac PetscInt *seen, *perm; 818b4457527SToby Isaac PetscSection section; 819b4457527SToby Isaac 820b4457527SToby Isaac PetscFunctionBegin; 821b4457527SToby Isaac dm = sp->dm; 8229566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion)); 8239566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 8259566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &seen)); 8269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &perm)); 8279566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8289566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 829b4457527SToby Isaac for (c = cStart, count = 0; c < cEnd; c++) { 830b4457527SToby Isaac PetscInt closureSize = -1, e; 831b4457527SToby Isaac PetscInt *closure = NULL; 832b4457527SToby Isaac 833b4457527SToby Isaac perm[count++] = c; 834b4457527SToby Isaac seen[c - pStart] = 1; 8359566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 836b4457527SToby Isaac for (e = 0; e < closureSize; e++) { 837b4457527SToby Isaac PetscInt point = closure[2 * e]; 838b4457527SToby Isaac 839b4457527SToby Isaac if (seen[point - pStart]) continue; 840b4457527SToby Isaac perm[count++] = point; 841b4457527SToby Isaac seen[point - pStart] = 1; 842b4457527SToby Isaac } 8439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 844b4457527SToby Isaac } 8451dca8a05SBarry Smith PetscCheck(count == pEnd - pStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad topological ordering"); 8469371c9d4SSatish Balay for (i = 0; i < pEnd - pStart; i++) 8479371c9d4SSatish Balay if (perm[i] != i) break; 848b4457527SToby Isaac if (i < pEnd - pStart) { 849b4457527SToby Isaac IS permIS; 850b4457527SToby Isaac 8519566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pEnd - pStart, perm, PETSC_OWN_POINTER, &permIS)); 8529566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(permIS)); 8539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(section, permIS)); 8549566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS)); 855b4457527SToby Isaac } else { 8569566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 857b4457527SToby Isaac } 8589566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 859b4457527SToby Isaac *topSection = section; 8603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 861b4457527SToby Isaac } 862b4457527SToby Isaac 863b4457527SToby Isaac /* mark boundary points and set up */ 864d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSectionSetUp_Internal(PetscDualSpace sp, PetscSection section) 865d71ae5a4SJacob Faibussowitsch { 866b4457527SToby Isaac DM dm; 867b4457527SToby Isaac DMLabel boundary; 868b4457527SToby Isaac PetscInt pStart, pEnd, p; 869b4457527SToby Isaac 870b4457527SToby Isaac PetscFunctionBegin; 871b4457527SToby Isaac dm = sp->dm; 8729566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "boundary", &boundary)); 8739566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 8749566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, 1, boundary)); 8759566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, boundary)); 8769566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 877b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 878b4457527SToby Isaac PetscInt bval; 879b4457527SToby Isaac 8809566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(boundary, p, &bval)); 881b4457527SToby Isaac if (bval == 1) { 882b4457527SToby Isaac PetscInt dof; 883b4457527SToby Isaac 8849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 8859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetConstraintDof(section, p, dof)); 886b4457527SToby Isaac } 887b4457527SToby Isaac } 8889566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&boundary)); 8899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 8903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 891b4457527SToby Isaac } 892b4457527SToby Isaac 893a4ce7ad1SMatthew G. Knepley /*@ 894dce8aebaSBarry Smith PetscDualSpaceGetSection - Create a `PetscSection` over the reference cell with the layout from this space 895a4ce7ad1SMatthew G. Knepley 896*20f4b53cSBarry Smith Collective 897a4ce7ad1SMatthew G. Knepley 898a4ce7ad1SMatthew G. Knepley Input Parameters: 899dce8aebaSBarry Smith . sp - The `PetscDualSpace` 900a4ce7ad1SMatthew G. Knepley 901a4ce7ad1SMatthew G. Knepley Output Parameter: 902a4ce7ad1SMatthew G. Knepley . section - The section 903a4ce7ad1SMatthew G. Knepley 904a4ce7ad1SMatthew G. Knepley Level: advanced 905a4ce7ad1SMatthew G. Knepley 906dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscSection`, `PetscDualSpaceCreate()`, `DMPLEX` 907a4ce7ad1SMatthew G. Knepley @*/ 908d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetSection(PetscDualSpace sp, PetscSection *section) 909d71ae5a4SJacob Faibussowitsch { 910b4457527SToby Isaac PetscInt pStart, pEnd, p; 911b4457527SToby Isaac 912b4457527SToby Isaac PetscFunctionBegin; 91378f1d139SRomain Beucher if (!sp->dm) { 91478f1d139SRomain Beucher *section = NULL; 9153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 91678f1d139SRomain Beucher } 917b4457527SToby Isaac if (!sp->pointSection) { 918b4457527SToby Isaac /* mark the boundary */ 9199566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionCreate_Internal(sp, &(sp->pointSection))); 9209566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(sp->dm, &pStart, &pEnd)); 921b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 922b4457527SToby Isaac PetscDualSpace psp; 923b4457527SToby Isaac 9249566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, p, &psp)); 925b4457527SToby Isaac if (psp) { 926b4457527SToby Isaac PetscInt dof; 927b4457527SToby Isaac 9289566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorDimension(psp, &dof)); 9299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sp->pointSection, p, dof)); 930b4457527SToby Isaac } 931b4457527SToby Isaac } 9329566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSectionSetUp_Internal(sp, sp->pointSection)); 933b4457527SToby Isaac } 934b4457527SToby Isaac *section = sp->pointSection; 9353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 936b4457527SToby Isaac } 937b4457527SToby Isaac 938b4457527SToby Isaac /* this assumes that all of the point dual spaces store their interior dofs first, which is true when the point DMs 939b4457527SToby Isaac * have one cell */ 940d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushForwardSubspaces_Internal(PetscDualSpace sp, PetscInt sStart, PetscInt sEnd) 941d71ae5a4SJacob Faibussowitsch { 942b4457527SToby Isaac PetscReal *sv0, *v0, *J; 943b4457527SToby Isaac PetscSection section; 944b4457527SToby Isaac PetscInt dim, s, k; 94520cf1dd8SToby Isaac DM dm; 94620cf1dd8SToby Isaac 94720cf1dd8SToby Isaac PetscFunctionBegin; 9489566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 9499566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9509566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 9519566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim, &sv0, dim * dim, &J)); 9529566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFormDegree(sp, &k)); 953b4457527SToby Isaac for (s = sStart; s < sEnd; s++) { 954b4457527SToby Isaac PetscReal detJ, hdetJ; 955b4457527SToby Isaac PetscDualSpace ssp; 956b4457527SToby Isaac PetscInt dof, off, f, sdim; 957b4457527SToby Isaac PetscInt i, j; 958b4457527SToby Isaac DM sdm; 95920cf1dd8SToby Isaac 9609566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetPointSubspace(sp, s, &ssp)); 961b4457527SToby Isaac if (!ssp) continue; 9629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, s, &dof)); 9639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, s, &off)); 964b4457527SToby Isaac /* get the first vertex of the reference cell */ 9659566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(ssp, &sdm)); 9669566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sdm, &sdim)); 9679566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(sdm, 0, sv0, NULL, NULL, &hdetJ)); 9689566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, s, v0, J, NULL, &detJ)); 969b4457527SToby Isaac /* compactify Jacobian */ 9709371c9d4SSatish Balay for (i = 0; i < dim; i++) 9719371c9d4SSatish Balay for (j = 0; j < sdim; j++) J[i * sdim + j] = J[i * dim + j]; 972b4457527SToby Isaac for (f = 0; f < dof; f++) { 973b4457527SToby Isaac PetscQuadrature fn; 97420cf1dd8SToby Isaac 9759566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(ssp, f, &fn)); 9769566063dSJacob Faibussowitsch PetscCall(PetscQuadraturePushForward(fn, dim, sv0, v0, J, k, &(sp->functional[off + f]))); 97720cf1dd8SToby Isaac } 97820cf1dd8SToby Isaac } 9799566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, sv0, J)); 9803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98120cf1dd8SToby Isaac } 98220cf1dd8SToby Isaac 98320cf1dd8SToby Isaac /*@C 98420cf1dd8SToby Isaac PetscDualSpaceApply - Apply a functional from the dual space basis to an input function 98520cf1dd8SToby Isaac 98620cf1dd8SToby Isaac Input Parameters: 987dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 98820cf1dd8SToby Isaac . f - The basis functional index 98920cf1dd8SToby Isaac . time - The time 99020cf1dd8SToby 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) 99120cf1dd8SToby Isaac . numComp - The number of components for the function 99220cf1dd8SToby Isaac . func - The input function 99320cf1dd8SToby Isaac - ctx - A context for the function 99420cf1dd8SToby Isaac 99520cf1dd8SToby Isaac Output Parameter: 99620cf1dd8SToby Isaac . value - numComp output values 99720cf1dd8SToby Isaac 998*20f4b53cSBarry Smith Calling Sequence of `func`: 999dce8aebaSBarry Smith .vb 1000*20f4b53cSBarry Smith PetscErrorCode func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt numComponents, PetscScalar values[], void *ctx) 1001dce8aebaSBarry Smith .ve 100220cf1dd8SToby Isaac 1003a4ce7ad1SMatthew G. Knepley Level: beginner 100420cf1dd8SToby Isaac 1005dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 100620cf1dd8SToby Isaac @*/ 1007d71ae5a4SJacob 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) 1008d71ae5a4SJacob Faibussowitsch { 100920cf1dd8SToby Isaac PetscFunctionBegin; 101020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 101120cf1dd8SToby Isaac PetscValidPointer(cgeom, 4); 1012dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 1013dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, apply, f, time, cgeom, numComp, func, ctx, value); 10143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 101520cf1dd8SToby Isaac } 101620cf1dd8SToby Isaac 101720cf1dd8SToby Isaac /*@C 1018dce8aebaSBarry Smith PetscDualSpaceApplyAll - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetAllData()` 101920cf1dd8SToby Isaac 102020cf1dd8SToby Isaac Input Parameters: 1021dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1022dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetAllData()` 102320cf1dd8SToby Isaac 102420cf1dd8SToby Isaac Output Parameter: 102520cf1dd8SToby Isaac . spValue - The values of all dual space functionals 102620cf1dd8SToby Isaac 1027dce8aebaSBarry Smith Level: advanced 102820cf1dd8SToby Isaac 1029dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 103020cf1dd8SToby Isaac @*/ 1031d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyAll(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1032d71ae5a4SJacob Faibussowitsch { 103320cf1dd8SToby Isaac PetscFunctionBegin; 103420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1035dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyall, pointEval, spValue); 10363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 103720cf1dd8SToby Isaac } 103820cf1dd8SToby Isaac 103920cf1dd8SToby Isaac /*@C 1040dce8aebaSBarry Smith PetscDualSpaceApplyInterior - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1041b4457527SToby Isaac 1042b4457527SToby Isaac Input Parameters: 1043dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1044dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1045b4457527SToby Isaac 1046b4457527SToby Isaac Output Parameter: 1047b4457527SToby Isaac . spValue - The values of interior dual space functionals 1048b4457527SToby Isaac 1049dce8aebaSBarry Smith Level: advanced 1050b4457527SToby Isaac 1051dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 1052b4457527SToby Isaac @*/ 1053d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyInterior(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1054d71ae5a4SJacob Faibussowitsch { 1055b4457527SToby Isaac PetscFunctionBegin; 1056b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1057dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, applyint, pointEval, spValue); 10583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1059b4457527SToby Isaac } 1060b4457527SToby Isaac 1061b4457527SToby Isaac /*@C 106220cf1dd8SToby Isaac PetscDualSpaceApplyDefault - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional. 106320cf1dd8SToby Isaac 106420cf1dd8SToby Isaac Input Parameters: 1065dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 106620cf1dd8SToby Isaac . f - The basis functional index 106720cf1dd8SToby Isaac . time - The time 106820cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian) 106920cf1dd8SToby Isaac . Nc - The number of components for the function 107020cf1dd8SToby Isaac . func - The input function 107120cf1dd8SToby Isaac - ctx - A context for the function 107220cf1dd8SToby Isaac 107320cf1dd8SToby Isaac Output Parameter: 107420cf1dd8SToby Isaac . value - The output value 107520cf1dd8SToby Isaac 1076*20f4b53cSBarry Smith Calling Sequence of `func`: 1077dce8aebaSBarry Smith .vb 1078*20f4b53cSBarry Smith PetscErrorCode func(PetscInt dim, PetscReal time, const PetscReal x[],PetscInt numComponents, PetscScalar values[], void *ctx) 1079dce8aebaSBarry Smith .ve 108020cf1dd8SToby Isaac 1081dce8aebaSBarry Smith Level: advanced 108220cf1dd8SToby Isaac 1083dce8aebaSBarry Smith Note: 1084dce8aebaSBarry 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. 108520cf1dd8SToby Isaac 1086dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 108720cf1dd8SToby Isaac @*/ 1088d71ae5a4SJacob 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) 1089d71ae5a4SJacob Faibussowitsch { 109020cf1dd8SToby Isaac DM dm; 109120cf1dd8SToby Isaac PetscQuadrature n; 109220cf1dd8SToby Isaac const PetscReal *points, *weights; 109320cf1dd8SToby Isaac PetscReal x[3]; 109420cf1dd8SToby Isaac PetscScalar *val; 109520cf1dd8SToby Isaac PetscInt dim, dE, qNc, c, Nq, q; 109620cf1dd8SToby Isaac PetscBool isAffine; 109720cf1dd8SToby Isaac 109820cf1dd8SToby Isaac PetscFunctionBegin; 109920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1100dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 11019566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 11029566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 11039566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, &dim, &qNc, &Nq, &points, &weights)); 110463a3b9bcSJacob 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); 110563a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 11069566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 110720cf1dd8SToby Isaac *value = 0.0; 110820cf1dd8SToby Isaac isAffine = cgeom->isAffine; 110920cf1dd8SToby Isaac dE = cgeom->dimEmbed; 111020cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 111120cf1dd8SToby Isaac if (isAffine) { 111220cf1dd8SToby Isaac CoordinatesRefToReal(dE, cgeom->dim, cgeom->xi, cgeom->v, cgeom->J, &points[q * dim], x); 11139566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, x, Nc, val, ctx)); 111420cf1dd8SToby Isaac } else { 11159566063dSJacob Faibussowitsch PetscCall((*func)(dE, time, &cgeom->v[dE * q], Nc, val, ctx)); 111620cf1dd8SToby Isaac } 1117ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) *value += val[c] * weights[q * Nc + c]; 111820cf1dd8SToby Isaac } 11199566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 11203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 112120cf1dd8SToby Isaac } 112220cf1dd8SToby Isaac 112320cf1dd8SToby Isaac /*@C 1124dce8aebaSBarry Smith PetscDualSpaceApplyAllDefault - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetAllData()` 112520cf1dd8SToby Isaac 112620cf1dd8SToby Isaac Input Parameters: 1127dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1128dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetAllData()` 112920cf1dd8SToby Isaac 113020cf1dd8SToby Isaac Output Parameter: 113120cf1dd8SToby Isaac . spValue - The values of all dual space functionals 113220cf1dd8SToby Isaac 1133dce8aebaSBarry Smith Level: advanced 113420cf1dd8SToby Isaac 1135dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 113620cf1dd8SToby Isaac @*/ 1137d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyAllDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1138d71ae5a4SJacob Faibussowitsch { 1139b4457527SToby Isaac Vec pointValues, dofValues; 1140b4457527SToby Isaac Mat allMat; 114120cf1dd8SToby Isaac 114220cf1dd8SToby Isaac PetscFunctionBegin; 114320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 114420cf1dd8SToby Isaac PetscValidScalarPointer(pointEval, 2); 1145064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11469566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetAllData(sp, NULL, &allMat)); 114748a46eb9SPierre Jolivet if (!(sp->allNodeValues)) PetscCall(MatCreateVecs(allMat, &(sp->allNodeValues), NULL)); 1148b4457527SToby Isaac pointValues = sp->allNodeValues; 114948a46eb9SPierre Jolivet if (!(sp->allDofValues)) PetscCall(MatCreateVecs(allMat, NULL, &(sp->allDofValues))); 1150b4457527SToby Isaac dofValues = sp->allDofValues; 11519566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11529566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11539566063dSJacob Faibussowitsch PetscCall(MatMult(allMat, pointValues, dofValues)); 11549566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11559566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 11563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 115720cf1dd8SToby Isaac } 1158b4457527SToby Isaac 1159b4457527SToby Isaac /*@C 1160dce8aebaSBarry Smith PetscDualSpaceApplyInteriorDefault - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1161b4457527SToby Isaac 1162b4457527SToby Isaac Input Parameters: 1163dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 1164dce8aebaSBarry Smith - pointEval - Evaluation at the points returned by `PetscDualSpaceGetInteriorData()` 1165b4457527SToby Isaac 1166b4457527SToby Isaac Output Parameter: 1167b4457527SToby Isaac . spValue - The values of interior dual space functionals 1168b4457527SToby Isaac 1169dce8aebaSBarry Smith Level: advanced 1170b4457527SToby Isaac 1171dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 1172b4457527SToby Isaac @*/ 1173d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceApplyInteriorDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1174d71ae5a4SJacob Faibussowitsch { 1175b4457527SToby Isaac Vec pointValues, dofValues; 1176b4457527SToby Isaac Mat intMat; 1177b4457527SToby Isaac 1178b4457527SToby Isaac PetscFunctionBegin; 1179b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1180b4457527SToby Isaac PetscValidScalarPointer(pointEval, 2); 1181064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11829566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(sp, NULL, &intMat)); 118348a46eb9SPierre Jolivet if (!(sp->intNodeValues)) PetscCall(MatCreateVecs(intMat, &(sp->intNodeValues), NULL)); 1184b4457527SToby Isaac pointValues = sp->intNodeValues; 118548a46eb9SPierre Jolivet if (!(sp->intDofValues)) PetscCall(MatCreateVecs(intMat, NULL, &(sp->intDofValues))); 1186b4457527SToby Isaac dofValues = sp->intDofValues; 11879566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pointValues, pointEval)); 11889566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dofValues, spValue)); 11899566063dSJacob Faibussowitsch PetscCall(MatMult(intMat, pointValues, dofValues)); 11909566063dSJacob Faibussowitsch PetscCall(VecResetArray(dofValues)); 11919566063dSJacob Faibussowitsch PetscCall(VecResetArray(pointValues)); 11923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 119320cf1dd8SToby Isaac } 119420cf1dd8SToby Isaac 1195a4ce7ad1SMatthew G. Knepley /*@ 1196b4457527SToby Isaac PetscDualSpaceGetAllData - Get all quadrature nodes from this space, and the matrix that sends quadrature node values to degree-of-freedom values 1197a4ce7ad1SMatthew G. Knepley 1198a4ce7ad1SMatthew G. Knepley Input Parameter: 1199a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1200a4ce7ad1SMatthew G. Knepley 1201d8d19677SJose E. Roman Output Parameters: 1202dce8aebaSBarry Smith + allNodes - A `PetscQuadrature` object containing all evaluation nodes 1203dce8aebaSBarry Smith - allMat - A `Mat` for the node-to-dof transformation 1204a4ce7ad1SMatthew G. Knepley 1205a4ce7ad1SMatthew G. Knepley Level: advanced 1206a4ce7ad1SMatthew G. Knepley 1207dce8aebaSBarry Smith .seealso: `PetscQuadrature`, `PetscDualSpace`, `PetscDualSpaceCreate()`, `Mat` 1208a4ce7ad1SMatthew G. Knepley @*/ 1209d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetAllData(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 1210d71ae5a4SJacob Faibussowitsch { 121120cf1dd8SToby Isaac PetscFunctionBegin; 121220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1213b4457527SToby Isaac if (allNodes) PetscValidPointer(allNodes, 2); 1214b4457527SToby Isaac if (allMat) PetscValidPointer(allMat, 3); 1215b4457527SToby Isaac if ((!sp->allNodes || !sp->allMat) && sp->ops->createalldata) { 1216b4457527SToby Isaac PetscQuadrature qpoints; 1217b4457527SToby Isaac Mat amat; 1218b4457527SToby Isaac 1219dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createalldata, &qpoints, &amat); 12209566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->allNodes))); 12219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->allMat))); 1222b4457527SToby Isaac sp->allNodes = qpoints; 1223b4457527SToby Isaac sp->allMat = amat; 122420cf1dd8SToby Isaac } 1225b4457527SToby Isaac if (allNodes) *allNodes = sp->allNodes; 1226b4457527SToby Isaac if (allMat) *allMat = sp->allMat; 12273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 122820cf1dd8SToby Isaac } 122920cf1dd8SToby Isaac 1230a4ce7ad1SMatthew G. Knepley /*@ 1231b4457527SToby Isaac PetscDualSpaceCreateAllDataDefault - Create all evaluation nodes and the node-to-dof matrix by examining functionals 1232a4ce7ad1SMatthew G. Knepley 1233a4ce7ad1SMatthew G. Knepley Input Parameter: 1234a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1235a4ce7ad1SMatthew G. Knepley 1236d8d19677SJose E. Roman Output Parameters: 1237dce8aebaSBarry Smith + allNodes - A `PetscQuadrature` object containing all evaluation nodes 1238dce8aebaSBarry Smith - allMat - A `Mat` for the node-to-dof transformation 1239a4ce7ad1SMatthew G. Knepley 1240a4ce7ad1SMatthew G. Knepley Level: advanced 1241a4ce7ad1SMatthew G. Knepley 1242dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()`, `Mat`, `PetscQuadrature` 1243a4ce7ad1SMatthew G. Knepley @*/ 1244d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreateAllDataDefault(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 1245d71ae5a4SJacob Faibussowitsch { 124620cf1dd8SToby Isaac PetscInt spdim; 124720cf1dd8SToby Isaac PetscInt numPoints, offset; 124820cf1dd8SToby Isaac PetscReal *points; 124920cf1dd8SToby Isaac PetscInt f, dim; 1250b4457527SToby Isaac PetscInt Nc, nrows, ncols; 1251b4457527SToby Isaac PetscInt maxNumPoints; 125220cf1dd8SToby Isaac PetscQuadrature q; 1253b4457527SToby Isaac Mat A; 125420cf1dd8SToby Isaac 125520cf1dd8SToby Isaac PetscFunctionBegin; 12569566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 12579566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &spdim)); 125820cf1dd8SToby Isaac if (!spdim) { 12599566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes)); 12609566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, 0, 0, 0, NULL, NULL)); 126120cf1dd8SToby Isaac } 1262b4457527SToby Isaac nrows = spdim; 12639566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, 0, &q)); 12649566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, NULL, &numPoints, NULL, NULL)); 1265b4457527SToby Isaac maxNumPoints = numPoints; 126620cf1dd8SToby Isaac for (f = 1; f < spdim; f++) { 126720cf1dd8SToby Isaac PetscInt Np; 126820cf1dd8SToby Isaac 12699566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q)); 12709566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL)); 127120cf1dd8SToby Isaac numPoints += Np; 1272b4457527SToby Isaac maxNumPoints = PetscMax(maxNumPoints, Np); 127320cf1dd8SToby Isaac } 1274b4457527SToby Isaac ncols = numPoints * Nc; 12759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points)); 12769566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, nrows, ncols, maxNumPoints * Nc, NULL, &A)); 127720cf1dd8SToby Isaac for (f = 0, offset = 0; f < spdim; f++) { 1278b4457527SToby Isaac const PetscReal *p, *w; 127920cf1dd8SToby Isaac PetscInt Np, i; 1280b4457527SToby Isaac PetscInt fnc; 128120cf1dd8SToby Isaac 12829566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &q)); 12839566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, &fnc, &Np, &p, &w)); 128408401ef6SPierre Jolivet PetscCheck(fnc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "functional component mismatch"); 1285ad540459SPierre Jolivet for (i = 0; i < Np * dim; i++) points[offset * dim + i] = p[i]; 128648a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(A, f, offset * Nc, w[i], INSERT_VALUES)); 1287b4457527SToby Isaac offset += Np; 1288b4457527SToby Isaac } 12899566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 12909566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 12919566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, allNodes)); 12929566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*allNodes, dim, 0, numPoints, points, NULL)); 1293b4457527SToby Isaac *allMat = A; 12943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1295b4457527SToby Isaac } 1296b4457527SToby Isaac 1297b4457527SToby Isaac /*@ 1298b4457527SToby Isaac PetscDualSpaceGetInteriorData - Get all quadrature points necessary to compute the interior degrees of freedom from 1299b4457527SToby Isaac this space, as well as the matrix that computes the degrees of freedom from the quadrature values. Degrees of 1300dce8aebaSBarry Smith freedom are interior degrees of freedom if they belong (by `PetscDualSpaceGetSection()`) to interior points in the 1301dce8aebaSBarry Smith reference `DMPLEX`: complementary boundary degrees of freedom are marked as constrained in the section returned by 1302dce8aebaSBarry Smith `PetscDualSpaceGetSection()`). 1303b4457527SToby Isaac 1304b4457527SToby Isaac Input Parameter: 1305b4457527SToby Isaac . sp - The dualspace 1306b4457527SToby Isaac 1307d8d19677SJose E. Roman Output Parameters: 1308dce8aebaSBarry Smith + intNodes - A `PetscQuadrature` object containing all evaluation points needed to evaluate interior degrees of freedom 1309b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1310dce8aebaSBarry Smith the size of the constrained layout (`PetscSectionGetConstrainStorageSize()`) of the dual space section, 1311dce8aebaSBarry Smith npoints is the number of points in intNodes and nc is `PetscDualSpaceGetNumComponents()`. 1312b4457527SToby Isaac 1313b4457527SToby Isaac Level: advanced 1314b4457527SToby Isaac 1315dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `Mat`, `PetscDualSpaceCreate()`, `PetscDualSpaceGetDimension()`, `PetscDualSpaceGetNumComponents()`, `PetscQuadratureGetData()` 1316b4457527SToby Isaac @*/ 1317d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetInteriorData(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1318d71ae5a4SJacob Faibussowitsch { 1319b4457527SToby Isaac PetscFunctionBegin; 1320b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1321b4457527SToby Isaac if (intNodes) PetscValidPointer(intNodes, 2); 1322b4457527SToby Isaac if (intMat) PetscValidPointer(intMat, 3); 1323b4457527SToby Isaac if ((!sp->intNodes || !sp->intMat) && sp->ops->createintdata) { 1324b4457527SToby Isaac PetscQuadrature qpoints; 1325b4457527SToby Isaac Mat imat; 1326b4457527SToby Isaac 1327dbbe0bcdSBarry Smith PetscUseTypeMethod(sp, createintdata, &qpoints, &imat); 13289566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&(sp->intNodes))); 13299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(sp->intMat))); 1330b4457527SToby Isaac sp->intNodes = qpoints; 1331b4457527SToby Isaac sp->intMat = imat; 1332b4457527SToby Isaac } 1333b4457527SToby Isaac if (intNodes) *intNodes = sp->intNodes; 1334b4457527SToby Isaac if (intMat) *intMat = sp->intMat; 13353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1336b4457527SToby Isaac } 1337b4457527SToby Isaac 1338b4457527SToby Isaac /*@ 1339b4457527SToby Isaac PetscDualSpaceCreateInteriorDataDefault - Create quadrature points by examining interior functionals and create the matrix mapping quadrature point values to interior dual space values 1340b4457527SToby Isaac 1341b4457527SToby Isaac Input Parameter: 1342b4457527SToby Isaac . sp - The dualspace 1343b4457527SToby Isaac 1344d8d19677SJose E. Roman Output Parameters: 1345dce8aebaSBarry Smith + intNodes - A `PetscQuadrature` object containing all evaluation points needed to evaluate interior degrees of freedom 1346b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1347dce8aebaSBarry Smith the size of the constrained layout (`PetscSectionGetConstrainStorageSize()`) of the dual space section, 1348dce8aebaSBarry Smith npoints is the number of points in allNodes and nc is `PetscDualSpaceGetNumComponents()`. 1349b4457527SToby Isaac 1350b4457527SToby Isaac Level: advanced 1351b4457527SToby Isaac 1352dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscQuadrature`, `Mat`, `PetscDualSpaceCreate()`, `PetscDualSpaceGetInteriorData()` 1353b4457527SToby Isaac @*/ 1354d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceCreateInteriorDataDefault(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1355d71ae5a4SJacob Faibussowitsch { 1356b4457527SToby Isaac DM dm; 1357b4457527SToby Isaac PetscInt spdim0; 1358b4457527SToby Isaac PetscInt Nc; 1359b4457527SToby Isaac PetscInt pStart, pEnd, p, f; 1360b4457527SToby Isaac PetscSection section; 1361b4457527SToby Isaac PetscInt numPoints, offset, matoffset; 1362b4457527SToby Isaac PetscReal *points; 1363b4457527SToby Isaac PetscInt dim; 1364b4457527SToby Isaac PetscInt *nnz; 1365b4457527SToby Isaac PetscQuadrature q; 1366b4457527SToby Isaac Mat imat; 1367b4457527SToby Isaac 1368b4457527SToby Isaac PetscFunctionBegin; 1369b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 13709566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSection(sp, §ion)); 13719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(section, &spdim0)); 1372b4457527SToby Isaac if (!spdim0) { 1373b4457527SToby Isaac *intNodes = NULL; 1374b4457527SToby Isaac *intMat = NULL; 13753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1376b4457527SToby Isaac } 13779566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(sp, &Nc)); 13789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 13799566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 13809566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 13819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(spdim0, &nnz)); 1382b4457527SToby Isaac for (p = pStart, f = 0, numPoints = 0; p < pEnd; p++) { 1383b4457527SToby Isaac PetscInt dof, cdof, off, d; 1384b4457527SToby Isaac 13859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 13869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1387b4457527SToby Isaac if (!(dof - cdof)) continue; 13889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1389b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1390b4457527SToby Isaac PetscInt Np; 1391b4457527SToby Isaac 13929566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q)); 13939566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, NULL, NULL)); 1394b4457527SToby Isaac nnz[f] = Np * Nc; 1395b4457527SToby Isaac numPoints += Np; 1396b4457527SToby Isaac } 1397b4457527SToby Isaac } 13989566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, spdim0, numPoints * Nc, 0, nnz, &imat)); 13999566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 14009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * numPoints, &points)); 1401b4457527SToby Isaac for (p = pStart, f = 0, offset = 0, matoffset = 0; p < pEnd; p++) { 1402b4457527SToby Isaac PetscInt dof, cdof, off, d; 1403b4457527SToby Isaac 14049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 14059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, p, &cdof)); 1406b4457527SToby Isaac if (!(dof - cdof)) continue; 14079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 1408b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1409b4457527SToby Isaac const PetscReal *p; 1410b4457527SToby Isaac const PetscReal *w; 1411b4457527SToby Isaac PetscInt Np, i; 1412b4457527SToby Isaac 14139566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, off, &q)); 14149566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Np, &p, &w)); 1415ad540459SPierre Jolivet for (i = 0; i < Np * dim; i++) points[offset + i] = p[i]; 141648a46eb9SPierre Jolivet for (i = 0; i < Np * Nc; i++) PetscCall(MatSetValue(imat, f, matoffset + i, w[i], INSERT_VALUES)); 1417b4457527SToby Isaac offset += Np * dim; 1418b4457527SToby Isaac matoffset += Np * Nc; 1419b4457527SToby Isaac } 1420b4457527SToby Isaac } 14219566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, intNodes)); 14229566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*intNodes, dim, 0, numPoints, points, NULL)); 14239566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(imat, MAT_FINAL_ASSEMBLY)); 14249566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(imat, MAT_FINAL_ASSEMBLY)); 1425b4457527SToby Isaac *intMat = imat; 14263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 142720cf1dd8SToby Isaac } 142820cf1dd8SToby Isaac 14294f9ab2b4SJed Brown /*@ 1430dce8aebaSBarry Smith PetscDualSpaceEqual - Determine if two dual spaces are equivalent 14314f9ab2b4SJed Brown 14324f9ab2b4SJed Brown Input Parameters: 1433dce8aebaSBarry Smith + A - A `PetscDualSpace` object 1434dce8aebaSBarry Smith - B - Another `PetscDualSpace` object 14354f9ab2b4SJed Brown 14364f9ab2b4SJed Brown Output Parameter: 1437dce8aebaSBarry Smith . equal - `PETSC_TRUE` if the dual spaces are equivalent 14384f9ab2b4SJed Brown 14394f9ab2b4SJed Brown Level: advanced 14404f9ab2b4SJed Brown 1441dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 14424f9ab2b4SJed Brown @*/ 1443d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceEqual(PetscDualSpace A, PetscDualSpace B, PetscBool *equal) 1444d71ae5a4SJacob Faibussowitsch { 14454f9ab2b4SJed Brown PetscInt sizeA, sizeB, dimA, dimB; 14464f9ab2b4SJed Brown const PetscInt *dofA, *dofB; 14474f9ab2b4SJed Brown PetscQuadrature quadA, quadB; 14484f9ab2b4SJed Brown Mat matA, matB; 14494f9ab2b4SJed Brown 14504f9ab2b4SJed Brown PetscFunctionBegin; 14514f9ab2b4SJed Brown PetscValidHeaderSpecific(A, PETSCDUALSPACE_CLASSID, 1); 14524f9ab2b4SJed Brown PetscValidHeaderSpecific(B, PETSCDUALSPACE_CLASSID, 2); 14534f9ab2b4SJed Brown PetscValidBoolPointer(equal, 3); 14544f9ab2b4SJed Brown *equal = PETSC_FALSE; 14559566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(A, &sizeA)); 14569566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(B, &sizeB)); 14573ba16761SJacob Faibussowitsch if (sizeB != sizeA) PetscFunctionReturn(PETSC_SUCCESS); 14589566063dSJacob Faibussowitsch PetscCall(DMGetDimension(A->dm, &dimA)); 14599566063dSJacob Faibussowitsch PetscCall(DMGetDimension(B->dm, &dimB)); 14603ba16761SJacob Faibussowitsch if (dimA != dimB) PetscFunctionReturn(PETSC_SUCCESS); 14614f9ab2b4SJed Brown 14629566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(A, &dofA)); 14639566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(B, &dofB)); 14644f9ab2b4SJed Brown for (PetscInt d = 0; d < dimA; d++) { 14653ba16761SJacob Faibussowitsch if (dofA[d] != dofB[d]) PetscFunctionReturn(PETSC_SUCCESS); 14664f9ab2b4SJed Brown } 14674f9ab2b4SJed Brown 14689566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(A, &quadA, &matA)); 14699566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetInteriorData(B, &quadB, &matB)); 14704f9ab2b4SJed Brown if (!quadA && !quadB) { 14714f9ab2b4SJed Brown *equal = PETSC_TRUE; 14724f9ab2b4SJed Brown } else if (quadA && quadB) { 14739566063dSJacob Faibussowitsch PetscCall(PetscQuadratureEqual(quadA, quadB, equal)); 14743ba16761SJacob Faibussowitsch if (*equal == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS); 14753ba16761SJacob Faibussowitsch if (!matA && !matB) PetscFunctionReturn(PETSC_SUCCESS); 14769566063dSJacob Faibussowitsch if (matA && matB) PetscCall(MatEqual(matA, matB, equal)); 14774f9ab2b4SJed Brown else *equal = PETSC_FALSE; 14784f9ab2b4SJed Brown } 14793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14804f9ab2b4SJed Brown } 14814f9ab2b4SJed Brown 148220cf1dd8SToby Isaac /*@C 148320cf1dd8SToby Isaac PetscDualSpaceApplyFVM - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional at the cell centroid. 148420cf1dd8SToby Isaac 148520cf1dd8SToby Isaac Input Parameters: 1486dce8aebaSBarry Smith + sp - The `PetscDualSpace` object 148720cf1dd8SToby Isaac . f - The basis functional index 148820cf1dd8SToby Isaac . time - The time 148920cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we currently just use the centroid 149020cf1dd8SToby Isaac . Nc - The number of components for the function 149120cf1dd8SToby Isaac . func - The input function 149220cf1dd8SToby Isaac - ctx - A context for the function 149320cf1dd8SToby Isaac 149420cf1dd8SToby Isaac Output Parameter: 149520cf1dd8SToby Isaac . value - The output value (scalar) 149620cf1dd8SToby Isaac 1497*20f4b53cSBarry Smith Calling Sequence of `func`: 1498dce8aebaSBarry Smith .vb 1499*20f4b53cSBarry Smith PetscErrorCode func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt numComponents, PetscScalar values[], void *ctx) 1500dce8aebaSBarry Smith .ve 1501*20f4b53cSBarry Smith 1502dce8aebaSBarry Smith Level: advanced 150320cf1dd8SToby Isaac 1504dce8aebaSBarry Smith Note: 1505dce8aebaSBarry 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. 150620cf1dd8SToby Isaac 1507dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceCreate()` 150820cf1dd8SToby Isaac @*/ 1509d71ae5a4SJacob 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) 1510d71ae5a4SJacob Faibussowitsch { 151120cf1dd8SToby Isaac DM dm; 151220cf1dd8SToby Isaac PetscQuadrature n; 151320cf1dd8SToby Isaac const PetscReal *points, *weights; 151420cf1dd8SToby Isaac PetscScalar *val; 151520cf1dd8SToby Isaac PetscInt dimEmbed, qNc, c, Nq, q; 151620cf1dd8SToby Isaac 151720cf1dd8SToby Isaac PetscFunctionBegin; 151820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1519dadcf809SJacob Faibussowitsch PetscValidScalarPointer(value, 8); 15209566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(sp, &dm)); 15219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 15229566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(sp, f, &n)); 15239566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(n, NULL, &qNc, &Nq, &points, &weights)); 152463a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_SIZ, "The quadrature components %" PetscInt_FMT " != function components %" PetscInt_FMT, qNc, Nc); 15259566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 152620cf1dd8SToby Isaac *value = 0.; 152720cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 15289566063dSJacob Faibussowitsch PetscCall((*func)(dimEmbed, time, cgeom->centroid, Nc, val, ctx)); 1529ad540459SPierre Jolivet for (c = 0; c < Nc; ++c) *value += val[c] * weights[q * Nc + c]; 153020cf1dd8SToby Isaac } 15319566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 15323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 153320cf1dd8SToby Isaac } 153420cf1dd8SToby Isaac 153520cf1dd8SToby Isaac /*@ 153620cf1dd8SToby Isaac PetscDualSpaceGetHeightSubspace - Get the subset of the dual space basis that is supported on a mesh point of a 153720cf1dd8SToby Isaac given height. This assumes that the reference cell is symmetric over points of this height. 153820cf1dd8SToby Isaac 1539*20f4b53cSBarry Smith Not Collective 154020cf1dd8SToby Isaac 154120cf1dd8SToby Isaac Input Parameters: 1542dce8aebaSBarry Smith + sp - the `PetscDualSpace` object 154320cf1dd8SToby Isaac - height - the height of the mesh point for which the subspace is desired 154420cf1dd8SToby Isaac 154520cf1dd8SToby Isaac Output Parameter: 154620cf1dd8SToby Isaac . subsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 154720cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 154820cf1dd8SToby Isaac 154920cf1dd8SToby Isaac Level: advanced 155020cf1dd8SToby Isaac 1551dce8aebaSBarry Smith Notes: 1552dce8aebaSBarry Smith If the dual space is not defined on mesh points of the given height (e.g. if the space is discontinuous and 1553dce8aebaSBarry Smith pointwise values are not defined on the element boundaries), or if the implementation of `PetscDualSpace` does not 1554dce8aebaSBarry Smith support extracting subspaces, then NULL is returned. 1555dce8aebaSBarry Smith 1556dce8aebaSBarry Smith This does not increment the reference count on the returned dual space, and the user should not destroy it. 1557dce8aebaSBarry Smith 1558dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscSpaceGetHeightSubspace()`, `PetscDualSpace`, `PetscDualSpaceGetPointSubspace()` 155920cf1dd8SToby Isaac @*/ 1560d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetHeightSubspace(PetscDualSpace sp, PetscInt height, PetscDualSpace *subsp) 1561d71ae5a4SJacob Faibussowitsch { 1562b4457527SToby Isaac PetscInt depth = -1, cStart, cEnd; 1563b4457527SToby Isaac DM dm; 156420cf1dd8SToby Isaac 156520cf1dd8SToby Isaac PetscFunctionBegin; 156620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1567064a246eSJacob Faibussowitsch PetscValidPointer(subsp, 3); 156808401ef6SPierre 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"); 156920cf1dd8SToby Isaac *subsp = NULL; 1570b4457527SToby Isaac dm = sp->dm; 15719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 15721dca8a05SBarry Smith PetscCheck(height >= 0 && height <= depth, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid height"); 15739566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1574b4457527SToby Isaac if (height == 0 && cEnd == cStart + 1) { 1575b4457527SToby Isaac *subsp = sp; 15763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1577b4457527SToby Isaac } 1578b4457527SToby Isaac if (!sp->heightSpaces) { 1579b4457527SToby Isaac PetscInt h; 15809566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth + 1, &(sp->heightSpaces))); 1581b4457527SToby Isaac 1582b4457527SToby Isaac for (h = 0; h <= depth; h++) { 1583b4457527SToby Isaac if (h == 0 && cEnd == cStart + 1) continue; 15849566063dSJacob Faibussowitsch if (sp->ops->createheightsubspace) PetscCall((*sp->ops->createheightsubspace)(sp, height, &(sp->heightSpaces[h]))); 1585b4457527SToby Isaac else if (sp->pointSpaces) { 1586b4457527SToby Isaac PetscInt hStart, hEnd; 1587b4457527SToby Isaac 15889566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &hStart, &hEnd)); 1589b4457527SToby Isaac if (hEnd > hStart) { 1590665f567fSMatthew G. Knepley const char *name; 1591665f567fSMatthew G. Knepley 15929566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(sp->pointSpaces[hStart]))); 1593665f567fSMatthew G. Knepley if (sp->pointSpaces[hStart]) { 15949566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)sp, &name)); 15959566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sp->pointSpaces[hStart], name)); 1596665f567fSMatthew G. Knepley } 1597b4457527SToby Isaac sp->heightSpaces[h] = sp->pointSpaces[hStart]; 1598b4457527SToby Isaac } 1599b4457527SToby Isaac } 1600b4457527SToby Isaac } 1601b4457527SToby Isaac } 1602b4457527SToby Isaac *subsp = sp->heightSpaces[height]; 16033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 160420cf1dd8SToby Isaac } 160520cf1dd8SToby Isaac 160620cf1dd8SToby Isaac /*@ 160720cf1dd8SToby Isaac PetscDualSpaceGetPointSubspace - Get the subset of the dual space basis that is supported on a particular mesh point. 160820cf1dd8SToby Isaac 1609*20f4b53cSBarry Smith Not Collective 161020cf1dd8SToby Isaac 161120cf1dd8SToby Isaac Input Parameters: 1612dce8aebaSBarry Smith + sp - the `PetscDualSpace` object 161320cf1dd8SToby Isaac - point - the point (in the dual space's DM) for which the subspace is desired 161420cf1dd8SToby Isaac 161520cf1dd8SToby Isaac Output Parameters: 1616dce8aebaSBarry Smith bdsp - the subspace. The functionals in the subspace are with respect to the intrinsic geometry of the 161720cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 161820cf1dd8SToby Isaac 161920cf1dd8SToby Isaac Level: advanced 162020cf1dd8SToby Isaac 1621dce8aebaSBarry Smith Notes: 1622dce8aebaSBarry Smith If the dual space is not defined on the mesh point (e.g. if the space is discontinuous and pointwise values are not 1623dce8aebaSBarry Smith defined on the element boundaries), or if the implementation of `PetscDualSpace` does not support extracting 1624dce8aebaSBarry Smith subspaces, then NULL is returned. 1625dce8aebaSBarry Smith 1626dce8aebaSBarry Smith This does not increment the reference count on the returned dual space, and the user should not destroy it. 1627dce8aebaSBarry Smith 1628dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceGetHeightSubspace()` 162920cf1dd8SToby Isaac @*/ 1630d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetPointSubspace(PetscDualSpace sp, PetscInt point, PetscDualSpace *bdsp) 1631d71ae5a4SJacob Faibussowitsch { 1632b4457527SToby Isaac PetscInt pStart = 0, pEnd = 0, cStart, cEnd; 1633b4457527SToby Isaac DM dm; 163420cf1dd8SToby Isaac 163520cf1dd8SToby Isaac PetscFunctionBegin; 163620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1637064a246eSJacob Faibussowitsch PetscValidPointer(bdsp, 3); 163820cf1dd8SToby Isaac *bdsp = NULL; 1639b4457527SToby Isaac dm = sp->dm; 16409566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 16411dca8a05SBarry Smith PetscCheck(point >= pStart && point <= pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid point"); 16429566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1643b4457527SToby 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 */ 1644b4457527SToby Isaac *bdsp = sp; 16453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1646b4457527SToby Isaac } 1647b4457527SToby Isaac if (!sp->pointSpaces) { 1648b4457527SToby Isaac PetscInt p; 16499566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &(sp->pointSpaces))); 165020cf1dd8SToby Isaac 1651b4457527SToby Isaac for (p = 0; p < pEnd - pStart; p++) { 1652b4457527SToby Isaac if (p + pStart == cStart && cEnd == cStart + 1) continue; 16539566063dSJacob Faibussowitsch if (sp->ops->createpointsubspace) PetscCall((*sp->ops->createpointsubspace)(sp, p + pStart, &(sp->pointSpaces[p]))); 1654b4457527SToby Isaac else if (sp->heightSpaces || sp->ops->createheightsubspace) { 1655b4457527SToby Isaac PetscInt dim, depth, height; 1656b4457527SToby Isaac DMLabel label; 1657b4457527SToby Isaac 16589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &dim)); 16599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 16609566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, p + pStart, &depth)); 166120cf1dd8SToby Isaac height = dim - depth; 16629566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(sp, height, &(sp->pointSpaces[p]))); 16639566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sp->pointSpaces[p])); 166420cf1dd8SToby Isaac } 1665b4457527SToby Isaac } 1666b4457527SToby Isaac } 1667b4457527SToby Isaac *bdsp = sp->pointSpaces[point - pStart]; 16683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 166920cf1dd8SToby Isaac } 167020cf1dd8SToby Isaac 16716f905325SMatthew G. Knepley /*@C 16726f905325SMatthew G. Knepley PetscDualSpaceGetSymmetries - Returns a description of the symmetries of this basis 16736f905325SMatthew G. Knepley 1674*20f4b53cSBarry Smith Not Collective 16756f905325SMatthew G. Knepley 16766f905325SMatthew G. Knepley Input Parameter: 1677dce8aebaSBarry Smith . sp - the `PetscDualSpace` object 16786f905325SMatthew G. Knepley 16796f905325SMatthew G. Knepley Output Parameters: 1680b4457527SToby Isaac + perms - Permutations of the interior degrees of freedom, parameterized by the point orientation 1681b4457527SToby Isaac - flips - Sign reversal of the interior degrees of freedom, parameterized by the point orientation 16826f905325SMatthew G. Knepley 16836f905325SMatthew G. Knepley Level: developer 16846f905325SMatthew G. Knepley 1685dce8aebaSBarry Smith Note: 1686dce8aebaSBarry Smith The permutation and flip arrays are organized in the following way 1687dce8aebaSBarry Smith .vb 1688dce8aebaSBarry Smith perms[p][ornt][dof # on point] = new local dof # 1689dce8aebaSBarry Smith flips[p][ornt][dof # on point] = reversal or not 1690dce8aebaSBarry Smith .ve 1691dce8aebaSBarry Smith 1692dce8aebaSBarry Smith .seealso: `PetscDualSpace` 16936f905325SMatthew G. Knepley @*/ 1694d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetSymmetries(PetscDualSpace sp, const PetscInt ****perms, const PetscScalar ****flips) 1695d71ae5a4SJacob Faibussowitsch { 16966f905325SMatthew G. Knepley PetscFunctionBegin; 16976f905325SMatthew G. Knepley PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 16989371c9d4SSatish Balay if (perms) { 16999371c9d4SSatish Balay PetscValidPointer(perms, 2); 17009371c9d4SSatish Balay *perms = NULL; 17019371c9d4SSatish Balay } 17029371c9d4SSatish Balay if (flips) { 17039371c9d4SSatish Balay PetscValidPointer(flips, 3); 17049371c9d4SSatish Balay *flips = NULL; 17059371c9d4SSatish Balay } 17069566063dSJacob Faibussowitsch if (sp->ops->getsymmetries) PetscCall((sp->ops->getsymmetries)(sp, perms, flips)); 17073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17086f905325SMatthew G. Knepley } 17094bee2e38SMatthew G. Knepley 17104bee2e38SMatthew G. Knepley /*@ 1711b4457527SToby Isaac PetscDualSpaceGetFormDegree - Get the form degree k for the k-form the describes the pushforwards/pullbacks of this 1712b4457527SToby Isaac dual space's functionals. 1713b4457527SToby Isaac 1714b4457527SToby Isaac Input Parameter: 1715dce8aebaSBarry Smith . dsp - The `PetscDualSpace` 1716b4457527SToby Isaac 1717b4457527SToby Isaac Output Parameter: 1718b4457527SToby 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 1719b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1720b4457527SToby 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). 1721b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1722b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1723b4457527SToby Isaac but are stored as 1-forms. 1724b4457527SToby Isaac 1725b4457527SToby Isaac Level: developer 1726b4457527SToby Isaac 1727dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 1728b4457527SToby Isaac @*/ 1729d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetFormDegree(PetscDualSpace dsp, PetscInt *k) 1730d71ae5a4SJacob Faibussowitsch { 1731b4457527SToby Isaac PetscFunctionBeginHot; 1732b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1733dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1734b4457527SToby Isaac *k = dsp->k; 17353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1736b4457527SToby Isaac } 1737b4457527SToby Isaac 1738b4457527SToby Isaac /*@ 1739b4457527SToby Isaac PetscDualSpaceSetFormDegree - Set the form degree k for the k-form the describes the pushforwards/pullbacks of this 1740b4457527SToby Isaac dual space's functionals. 1741b4457527SToby Isaac 1742d8d19677SJose E. Roman Input Parameters: 1743dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 1744b4457527SToby 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 1745b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1746b4457527SToby 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). 1747b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1748b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1749b4457527SToby Isaac but are stored as 1-forms. 1750b4457527SToby Isaac 1751b4457527SToby Isaac Level: developer 1752b4457527SToby Isaac 1753dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDTAltV`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 1754b4457527SToby Isaac @*/ 1755d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceSetFormDegree(PetscDualSpace dsp, PetscInt k) 1756d71ae5a4SJacob Faibussowitsch { 1757b4457527SToby Isaac PetscInt dim; 1758b4457527SToby Isaac 1759b4457527SToby Isaac PetscFunctionBeginHot; 1760b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 176128b400f6SJacob Faibussowitsch PetscCheck(!dsp->setupcalled, PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 1762b4457527SToby Isaac dim = dsp->dm->dim; 17631dca8a05SBarry 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); 1764b4457527SToby Isaac dsp->k = k; 17653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1766b4457527SToby Isaac } 1767b4457527SToby Isaac 1768b4457527SToby Isaac /*@ 17694bee2e38SMatthew G. Knepley PetscDualSpaceGetDeRahm - Get the k-simplex associated with the functionals in this dual space 17704bee2e38SMatthew G. Knepley 17714bee2e38SMatthew G. Knepley Input Parameter: 1772dce8aebaSBarry Smith . dsp - The `PetscDualSpace` 17734bee2e38SMatthew G. Knepley 17744bee2e38SMatthew G. Knepley Output Parameter: 17754bee2e38SMatthew G. Knepley . k - The simplex dimension 17764bee2e38SMatthew G. Knepley 1777a4ce7ad1SMatthew G. Knepley Level: developer 17784bee2e38SMatthew G. Knepley 1779dce8aebaSBarry Smith Note: 1780dce8aebaSBarry Smith Currently supported values are 1781dce8aebaSBarry Smith .vb 1782dce8aebaSBarry Smith 0: These are H_1 methods that only transform coordinates 1783dce8aebaSBarry Smith 1: These are Hcurl methods that transform functions using the covariant Piola transform (COVARIANT_PIOLA_TRANSFORM) 1784dce8aebaSBarry Smith 2: These are the same as 1 1785dce8aebaSBarry Smith 3: These are Hdiv methods that transform functions using the contravariant Piola transform (CONTRAVARIANT_PIOLA_TRANSFORM) 1786dce8aebaSBarry Smith .ve 17874bee2e38SMatthew G. Knepley 1788dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceTransformType` 17894bee2e38SMatthew G. Knepley @*/ 1790d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceGetDeRahm(PetscDualSpace dsp, PetscInt *k) 1791d71ae5a4SJacob Faibussowitsch { 1792b4457527SToby Isaac PetscInt dim; 1793b4457527SToby Isaac 17944bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 17954bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1796dadcf809SJacob Faibussowitsch PetscValidIntPointer(k, 2); 1797b4457527SToby Isaac dim = dsp->dm->dim; 1798b4457527SToby Isaac if (!dsp->k) *k = IDENTITY_TRANSFORM; 1799b4457527SToby Isaac else if (dsp->k == 1) *k = COVARIANT_PIOLA_TRANSFORM; 1800b4457527SToby Isaac else if (dsp->k == -(dim - 1)) *k = CONTRAVARIANT_PIOLA_TRANSFORM; 1801b4457527SToby Isaac else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unsupported transformation"); 18023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18034bee2e38SMatthew G. Knepley } 18044bee2e38SMatthew G. Knepley 18054bee2e38SMatthew G. Knepley /*@C 18064bee2e38SMatthew G. Knepley PetscDualSpaceTransform - Transform the function values 18074bee2e38SMatthew G. Knepley 18084bee2e38SMatthew G. Knepley Input Parameters: 1809dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 18104bee2e38SMatthew G. Knepley . trans - The type of transform 18114bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18124bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18134bee2e38SMatthew G. Knepley . Nv - The number of function samples 18144bee2e38SMatthew G. Knepley . Nc - The number of function components 18154bee2e38SMatthew G. Knepley - vals - The function values 18164bee2e38SMatthew G. Knepley 18174bee2e38SMatthew G. Knepley Output Parameter: 18184bee2e38SMatthew G. Knepley . vals - The transformed function values 18194bee2e38SMatthew G. Knepley 1820a4ce7ad1SMatthew G. Knepley Level: intermediate 18214bee2e38SMatthew G. Knepley 1822dce8aebaSBarry Smith Note: 1823dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18242edcad52SToby Isaac 1825dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransformGradient()`, `PetscDualSpaceTransformHessian()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 18264bee2e38SMatthew G. Knepley @*/ 1827d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransform(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 1828d71ae5a4SJacob Faibussowitsch { 1829b4457527SToby Isaac PetscReal Jstar[9] = {0}; 1830b4457527SToby Isaac PetscInt dim, v, c, Nk; 18314bee2e38SMatthew G. Knepley 18324bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18334bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18344bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1835dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 1836b4457527SToby Isaac /* TODO: not handling dimEmbed != dim right now */ 18372ae266adSMatthew G. Knepley dim = dsp->dm->dim; 1838b4457527SToby Isaac /* No change needed for 0-forms */ 18393ba16761SJacob Faibussowitsch if (!dsp->k) PetscFunctionReturn(PETSC_SUCCESS); 18409566063dSJacob Faibussowitsch PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(dsp->k), &Nk)); 1841b4457527SToby Isaac /* TODO: use fegeom->isAffine */ 18429566063dSJacob Faibussowitsch PetscCall(PetscDTAltVPullbackMatrix(dim, dim, isInverse ? fegeom->J : fegeom->invJ, dsp->k, Jstar)); 18434bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1844b4457527SToby Isaac switch (Nk) { 1845b4457527SToby Isaac case 1: 1846b4457527SToby Isaac for (c = 0; c < Nc; c++) vals[v * Nc + c] *= Jstar[0]; 18474bee2e38SMatthew G. Knepley break; 1848b4457527SToby Isaac case 2: 1849b4457527SToby Isaac for (c = 0; c < Nc; c += 2) DMPlex_Mult2DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]); 18504bee2e38SMatthew G. Knepley break; 1851b4457527SToby Isaac case 3: 1852b4457527SToby Isaac for (c = 0; c < Nc; c += 3) DMPlex_Mult3DReal_Internal(Jstar, 1, &vals[v * Nc + c], &vals[v * Nc + c]); 1853b4457527SToby Isaac break; 1854d71ae5a4SJacob Faibussowitsch default: 1855d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported form size %" PetscInt_FMT " for transformation", Nk); 1856b4457527SToby Isaac } 18574bee2e38SMatthew G. Knepley } 18583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18594bee2e38SMatthew G. Knepley } 1860b4457527SToby Isaac 18614bee2e38SMatthew G. Knepley /*@C 18624bee2e38SMatthew G. Knepley PetscDualSpaceTransformGradient - Transform the function gradient values 18634bee2e38SMatthew G. Knepley 18644bee2e38SMatthew G. Knepley Input Parameters: 1865dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 18664bee2e38SMatthew G. Knepley . trans - The type of transform 18674bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18684bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18694bee2e38SMatthew G. Knepley . Nv - The number of function gradient samples 18704bee2e38SMatthew G. Knepley . Nc - The number of function components 18714bee2e38SMatthew G. Knepley - vals - The function gradient values 18724bee2e38SMatthew G. Knepley 18734bee2e38SMatthew G. Knepley Output Parameter: 1874f9244615SMatthew G. Knepley . vals - The transformed function gradient values 18754bee2e38SMatthew G. Knepley 1876a4ce7ad1SMatthew G. Knepley Level: intermediate 18774bee2e38SMatthew G. Knepley 1878dce8aebaSBarry Smith Note: 1879dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18802edcad52SToby Isaac 1881dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 18824bee2e38SMatthew G. Knepley @*/ 1883d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransformGradient(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 1884d71ae5a4SJacob Faibussowitsch { 188527f02ce8SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 188627f02ce8SMatthew G. Knepley PetscInt v, c, d; 18874bee2e38SMatthew G. Knepley 18884bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18894bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18904bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 1891dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 189227f02ce8SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 189363a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 189427f02ce8SMatthew G. Knepley #endif 18954bee2e38SMatthew G. Knepley /* Transform gradient */ 189627f02ce8SMatthew G. Knepley if (dim == dE) { 18974bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 18984bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 18999371c9d4SSatish Balay switch (dim) { 1900d71ae5a4SJacob Faibussowitsch case 1: 1901d71ae5a4SJacob Faibussowitsch vals[(v * Nc + c) * dim] *= fegeom->invJ[0]; 1902d71ae5a4SJacob Faibussowitsch break; 1903d71ae5a4SJacob Faibussowitsch case 2: 1904d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]); 1905d71ae5a4SJacob Faibussowitsch break; 1906d71ae5a4SJacob Faibussowitsch case 3: 1907d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, 1, &vals[(v * Nc + c) * dim], &vals[(v * Nc + c) * dim]); 1908d71ae5a4SJacob Faibussowitsch break; 1909d71ae5a4SJacob Faibussowitsch default: 1910d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19114bee2e38SMatthew G. Knepley } 19124bee2e38SMatthew G. Knepley } 19134bee2e38SMatthew G. Knepley } 191427f02ce8SMatthew G. Knepley } else { 191527f02ce8SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1916ad540459SPierre 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]); 191727f02ce8SMatthew G. Knepley } 191827f02ce8SMatthew G. Knepley } 19194bee2e38SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 19203ba16761SJacob Faibussowitsch if (Nc == 1 || Nc != dim) PetscFunctionReturn(PETSC_SUCCESS); 19214bee2e38SMatthew G. Knepley switch (trans) { 1922d71ae5a4SJacob Faibussowitsch case IDENTITY_TRANSFORM: 1923d71ae5a4SJacob Faibussowitsch break; 19244bee2e38SMatthew G. Knepley case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 19254bee2e38SMatthew G. Knepley if (isInverse) { 19264bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19274bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19289371c9d4SSatish Balay switch (dim) { 1929d71ae5a4SJacob Faibussowitsch case 2: 1930d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1931d71ae5a4SJacob Faibussowitsch break; 1932d71ae5a4SJacob Faibussowitsch case 3: 1933d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1934d71ae5a4SJacob Faibussowitsch break; 1935d71ae5a4SJacob Faibussowitsch default: 1936d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19374bee2e38SMatthew G. Knepley } 19384bee2e38SMatthew G. Knepley } 19394bee2e38SMatthew G. Knepley } 19404bee2e38SMatthew G. Knepley } else { 19414bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19424bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19439371c9d4SSatish Balay switch (dim) { 1944d71ae5a4SJacob Faibussowitsch case 2: 1945d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1946d71ae5a4SJacob Faibussowitsch break; 1947d71ae5a4SJacob Faibussowitsch case 3: 1948d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1949d71ae5a4SJacob Faibussowitsch break; 1950d71ae5a4SJacob Faibussowitsch default: 1951d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19524bee2e38SMatthew G. Knepley } 19534bee2e38SMatthew G. Knepley } 19544bee2e38SMatthew G. Knepley } 19554bee2e38SMatthew G. Knepley } 19564bee2e38SMatthew G. Knepley break; 19574bee2e38SMatthew G. Knepley case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 19584bee2e38SMatthew G. Knepley if (isInverse) { 19594bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19604bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19619371c9d4SSatish Balay switch (dim) { 1962d71ae5a4SJacob Faibussowitsch case 2: 1963d71ae5a4SJacob Faibussowitsch DMPlex_Mult2DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1964d71ae5a4SJacob Faibussowitsch break; 1965d71ae5a4SJacob Faibussowitsch case 3: 1966d71ae5a4SJacob Faibussowitsch DMPlex_Mult3DReal_Internal(fegeom->invJ, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1967d71ae5a4SJacob Faibussowitsch break; 1968d71ae5a4SJacob Faibussowitsch default: 1969d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19704bee2e38SMatthew G. Knepley } 19714bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] *= fegeom->detJ[0]; 19724bee2e38SMatthew G. Knepley } 19734bee2e38SMatthew G. Knepley } 19744bee2e38SMatthew G. Knepley } else { 19754bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19764bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19779371c9d4SSatish Balay switch (dim) { 1978d71ae5a4SJacob Faibussowitsch case 2: 1979d71ae5a4SJacob Faibussowitsch DMPlex_Mult2DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1980d71ae5a4SJacob Faibussowitsch break; 1981d71ae5a4SJacob Faibussowitsch case 3: 1982d71ae5a4SJacob Faibussowitsch DMPlex_Mult3DReal_Internal(fegeom->J, dim, &vals[v * Nc * dim + d], &vals[v * Nc * dim + d]); 1983d71ae5a4SJacob Faibussowitsch break; 1984d71ae5a4SJacob Faibussowitsch default: 1985d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 19864bee2e38SMatthew G. Knepley } 19874bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v * Nc + c) * dim + d] /= fegeom->detJ[0]; 19884bee2e38SMatthew G. Knepley } 19894bee2e38SMatthew G. Knepley } 19904bee2e38SMatthew G. Knepley } 19914bee2e38SMatthew G. Knepley break; 19924bee2e38SMatthew G. Knepley } 19933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19944bee2e38SMatthew G. Knepley } 19954bee2e38SMatthew G. Knepley 19964bee2e38SMatthew G. Knepley /*@C 1997f9244615SMatthew G. Knepley PetscDualSpaceTransformHessian - Transform the function Hessian values 1998f9244615SMatthew G. Knepley 1999f9244615SMatthew G. Knepley Input Parameters: 2000dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 2001f9244615SMatthew G. Knepley . trans - The type of transform 2002f9244615SMatthew G. Knepley . isInverse - Flag to invert the transform 2003f9244615SMatthew G. Knepley . fegeom - The cell geometry 2004f9244615SMatthew G. Knepley . Nv - The number of function Hessian samples 2005f9244615SMatthew G. Knepley . Nc - The number of function components 2006f9244615SMatthew G. Knepley - vals - The function gradient values 2007f9244615SMatthew G. Knepley 2008f9244615SMatthew G. Knepley Output Parameter: 2009f9244615SMatthew G. Knepley . vals - The transformed function Hessian values 2010f9244615SMatthew G. Knepley 2011f9244615SMatthew G. Knepley Level: intermediate 2012f9244615SMatthew G. Knepley 2013dce8aebaSBarry Smith Note: 2014dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2015f9244615SMatthew G. Knepley 2016dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpaceTransform()`, `PetscDualSpacePullback()`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransformType` 2017f9244615SMatthew G. Knepley @*/ 2018d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpaceTransformHessian(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 2019d71ae5a4SJacob Faibussowitsch { 2020f9244615SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 2021f9244615SMatthew G. Knepley PetscInt v, c; 2022f9244615SMatthew G. Knepley 2023f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2024f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2025f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 4); 2026dadcf809SJacob Faibussowitsch PetscValidScalarPointer(vals, 7); 2027f9244615SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 202863a3b9bcSJacob Faibussowitsch PetscCheck(dE > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %" PetscInt_FMT, dE); 2029f9244615SMatthew G. Knepley #endif 2030f9244615SMatthew G. Knepley /* Transform Hessian: J^{-T}_{ik} J^{-T}_{jl} H(f)_{kl} = J^{-T}_{ik} H(f)_{kl} J^{-1}_{lj} */ 2031f9244615SMatthew G. Knepley if (dim == dE) { 2032f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2033f9244615SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 20349371c9d4SSatish Balay switch (dim) { 2035d71ae5a4SJacob Faibussowitsch case 1: 2036d71ae5a4SJacob Faibussowitsch vals[(v * Nc + c) * dim * dim] *= PetscSqr(fegeom->invJ[0]); 2037d71ae5a4SJacob Faibussowitsch break; 2038d71ae5a4SJacob Faibussowitsch case 2: 2039d71ae5a4SJacob Faibussowitsch DMPlex_PTAP2DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]); 2040d71ae5a4SJacob Faibussowitsch break; 2041d71ae5a4SJacob Faibussowitsch case 3: 2042d71ae5a4SJacob Faibussowitsch DMPlex_PTAP3DReal_Internal(fegeom->invJ, &vals[(v * Nc + c) * dim * dim], &vals[(v * Nc + c) * dim * dim]); 2043d71ae5a4SJacob Faibussowitsch break; 2044d71ae5a4SJacob Faibussowitsch default: 2045d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %" PetscInt_FMT " for transformation", dim); 2046f9244615SMatthew G. Knepley } 2047f9244615SMatthew G. Knepley } 2048f9244615SMatthew G. Knepley } 2049f9244615SMatthew G. Knepley } else { 2050f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2051ad540459SPierre 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]); 2052f9244615SMatthew G. Knepley } 2053f9244615SMatthew G. Knepley } 2054f9244615SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 20553ba16761SJacob Faibussowitsch if (Nc == 1 || Nc != dim) PetscFunctionReturn(PETSC_SUCCESS); 2056f9244615SMatthew G. Knepley switch (trans) { 2057d71ae5a4SJacob Faibussowitsch case IDENTITY_TRANSFORM: 2058d71ae5a4SJacob Faibussowitsch break; 2059d71ae5a4SJacob Faibussowitsch case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 2060d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2061d71ae5a4SJacob Faibussowitsch case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 2062d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2063f9244615SMatthew G. Knepley } 20643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2065f9244615SMatthew G. Knepley } 2066f9244615SMatthew G. Knepley 2067f9244615SMatthew G. Knepley /*@C 20684bee2e38SMatthew 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. 20694bee2e38SMatthew G. Knepley 20704bee2e38SMatthew G. Knepley Input Parameters: 2071dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 20724bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 20734bee2e38SMatthew G. Knepley . Nq - The number of function samples 20744bee2e38SMatthew G. Knepley . Nc - The number of function components 20754bee2e38SMatthew G. Knepley - pointEval - The function values 20764bee2e38SMatthew G. Knepley 20774bee2e38SMatthew G. Knepley Output Parameter: 20784bee2e38SMatthew G. Knepley . pointEval - The transformed function values 20794bee2e38SMatthew G. Knepley 20804bee2e38SMatthew G. Knepley Level: advanced 20814bee2e38SMatthew G. Knepley 2082dce8aebaSBarry Smith Notes: 2083dce8aebaSBarry 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. 20844bee2e38SMatthew G. Knepley 2085da81f932SPierre Jolivet This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 20862edcad52SToby Isaac 2087dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 20884bee2e38SMatthew G. Knepley @*/ 2089d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePullback(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2090d71ae5a4SJacob Faibussowitsch { 20914bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2092b4457527SToby Isaac PetscInt k; 20934bee2e38SMatthew G. Knepley 20944bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 20954bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 20964bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2097dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 20984bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 20994bee2e38SMatthew G. Knepley This determines their transformation properties. */ 21009566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 21019371c9d4SSatish Balay switch (k) { 2102d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2103d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2104d71ae5a4SJacob Faibussowitsch break; 2105d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2106d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2107d71ae5a4SJacob Faibussowitsch break; 2108b4457527SToby Isaac case 2: 2109d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2110d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2111d71ae5a4SJacob Faibussowitsch break; 2112d71ae5a4SJacob Faibussowitsch default: 2113d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 21144bee2e38SMatthew G. Knepley } 21159566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_TRUE, fegeom, Nq, Nc, pointEval)); 21163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21174bee2e38SMatthew G. Knepley } 21184bee2e38SMatthew G. Knepley 21194bee2e38SMatthew G. Knepley /*@C 21204bee2e38SMatthew 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. 21214bee2e38SMatthew G. Knepley 21224bee2e38SMatthew G. Knepley Input Parameters: 2123dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 21244bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21254bee2e38SMatthew G. Knepley . Nq - The number of function samples 21264bee2e38SMatthew G. Knepley . Nc - The number of function components 21274bee2e38SMatthew G. Knepley - pointEval - The function values 21284bee2e38SMatthew G. Knepley 21294bee2e38SMatthew G. Knepley Output Parameter: 21304bee2e38SMatthew G. Knepley . pointEval - The transformed function values 21314bee2e38SMatthew G. Knepley 21324bee2e38SMatthew G. Knepley Level: advanced 21334bee2e38SMatthew G. Knepley 2134dce8aebaSBarry Smith Notes: 2135dce8aebaSBarry 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. 21364bee2e38SMatthew G. Knepley 2137dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21382edcad52SToby Isaac 2139dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 21404bee2e38SMatthew G. Knepley @*/ 2141d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforward(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2142d71ae5a4SJacob Faibussowitsch { 21434bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2144b4457527SToby Isaac PetscInt k; 21454bee2e38SMatthew G. Knepley 21464bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21474bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 21484bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2149dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 21504bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 21514bee2e38SMatthew G. Knepley This determines their transformation properties. */ 21529566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 21539371c9d4SSatish Balay switch (k) { 2154d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2155d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2156d71ae5a4SJacob Faibussowitsch break; 2157d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2158d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2159d71ae5a4SJacob Faibussowitsch break; 2160b4457527SToby Isaac case 2: 2161d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2162d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2163d71ae5a4SJacob Faibussowitsch break; 2164d71ae5a4SJacob Faibussowitsch default: 2165d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 21664bee2e38SMatthew G. Knepley } 21679566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransform(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 21683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21694bee2e38SMatthew G. Knepley } 21704bee2e38SMatthew G. Knepley 21714bee2e38SMatthew G. Knepley /*@C 21724bee2e38SMatthew 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. 21734bee2e38SMatthew G. Knepley 21744bee2e38SMatthew G. Knepley Input Parameters: 2175dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 21764bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21774bee2e38SMatthew G. Knepley . Nq - The number of function gradient samples 21784bee2e38SMatthew G. Knepley . Nc - The number of function components 21794bee2e38SMatthew G. Knepley - pointEval - The function gradient values 21804bee2e38SMatthew G. Knepley 21814bee2e38SMatthew G. Knepley Output Parameter: 21824bee2e38SMatthew G. Knepley . pointEval - The transformed function gradient values 21834bee2e38SMatthew G. Knepley 21844bee2e38SMatthew G. Knepley Level: advanced 21854bee2e38SMatthew G. Knepley 2186dce8aebaSBarry Smith Notes: 2187dce8aebaSBarry 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. 21884bee2e38SMatthew G. Knepley 2189dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21902edcad52SToby Isaac 2191dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2192dc0529c6SBarry Smith @*/ 2193d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforwardGradient(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2194d71ae5a4SJacob Faibussowitsch { 21954bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2196b4457527SToby Isaac PetscInt k; 21974bee2e38SMatthew G. Knepley 21984bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21994bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 22004bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2201dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 22024bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 22034bee2e38SMatthew G. Knepley This determines their transformation properties. */ 22049566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 22059371c9d4SSatish Balay switch (k) { 2206d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2207d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2208d71ae5a4SJacob Faibussowitsch break; 2209d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2210d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2211d71ae5a4SJacob Faibussowitsch break; 2212b4457527SToby Isaac case 2: 2213d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2214d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2215d71ae5a4SJacob Faibussowitsch break; 2216d71ae5a4SJacob Faibussowitsch default: 2217d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 22184bee2e38SMatthew G. Knepley } 22199566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformGradient(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 22203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22214bee2e38SMatthew G. Knepley } 2222f9244615SMatthew G. Knepley 2223f9244615SMatthew G. Knepley /*@C 2224f9244615SMatthew 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. 2225f9244615SMatthew G. Knepley 2226f9244615SMatthew G. Knepley Input Parameters: 2227dce8aebaSBarry Smith + dsp - The `PetscDualSpace` 2228f9244615SMatthew G. Knepley . fegeom - The geometry for this cell 2229f9244615SMatthew G. Knepley . Nq - The number of function Hessian samples 2230f9244615SMatthew G. Knepley . Nc - The number of function components 2231f9244615SMatthew G. Knepley - pointEval - The function gradient values 2232f9244615SMatthew G. Knepley 2233f9244615SMatthew G. Knepley Output Parameter: 2234f9244615SMatthew G. Knepley . pointEval - The transformed function Hessian values 2235f9244615SMatthew G. Knepley 2236f9244615SMatthew G. Knepley Level: advanced 2237f9244615SMatthew G. Knepley 2238dce8aebaSBarry Smith Notes: 2239dce8aebaSBarry 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. 2240f9244615SMatthew G. Knepley 2241dce8aebaSBarry Smith This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2242f9244615SMatthew G. Knepley 2243dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscDualSpacePushforward()`, `PPetscDualSpacePullback()`, `PetscDualSpaceTransform()`, `PetscDualSpaceGetDeRahm()` 2244f9244615SMatthew G. Knepley @*/ 2245d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDualSpacePushforwardHessian(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2246d71ae5a4SJacob Faibussowitsch { 2247f9244615SMatthew G. Knepley PetscDualSpaceTransformType trans; 2248f9244615SMatthew G. Knepley PetscInt k; 2249f9244615SMatthew G. Knepley 2250f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2251f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2252f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2253dadcf809SJacob Faibussowitsch PetscValidScalarPointer(pointEval, 5); 2254f9244615SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 2255f9244615SMatthew G. Knepley This determines their transformation properties. */ 22569566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDeRahm(dsp, &k)); 22579371c9d4SSatish Balay switch (k) { 2258d71ae5a4SJacob Faibussowitsch case 0: /* H^1 point evaluations */ 2259d71ae5a4SJacob Faibussowitsch trans = IDENTITY_TRANSFORM; 2260d71ae5a4SJacob Faibussowitsch break; 2261d71ae5a4SJacob Faibussowitsch case 1: /* Hcurl preserves tangential edge traces */ 2262d71ae5a4SJacob Faibussowitsch trans = COVARIANT_PIOLA_TRANSFORM; 2263d71ae5a4SJacob Faibussowitsch break; 2264f9244615SMatthew G. Knepley case 2: 2265d71ae5a4SJacob Faibussowitsch case 3: /* Hdiv preserve normal traces */ 2266d71ae5a4SJacob Faibussowitsch trans = CONTRAVARIANT_PIOLA_TRANSFORM; 2267d71ae5a4SJacob Faibussowitsch break; 2268d71ae5a4SJacob Faibussowitsch default: 2269d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %" PetscInt_FMT " for transformation", k); 2270f9244615SMatthew G. Knepley } 22719566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceTransformHessian(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 22723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2273f9244615SMatthew G. Knepley } 2274