120cf1dd8SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/ 220cf1dd8SToby Isaac #include <petscdmplex.h> 320cf1dd8SToby Isaac 420cf1dd8SToby Isaac PetscClassId PETSCDUALSPACE_CLASSID = 0; 520cf1dd8SToby Isaac 6ead873ccSMatthew G. Knepley PetscLogEvent PETSCDUALSPACE_SetUp; 7ead873ccSMatthew G. Knepley 820cf1dd8SToby Isaac PetscFunctionList PetscDualSpaceList = NULL; 920cf1dd8SToby Isaac PetscBool PetscDualSpaceRegisterAllCalled = PETSC_FALSE; 1020cf1dd8SToby Isaac 116f905325SMatthew G. Knepley /* 126f905325SMatthew G. Knepley PetscDualSpaceLatticePointLexicographic_Internal - Returns all tuples of size 'len' with nonnegative integers that sum up to at most 'max'. 136f905325SMatthew G. Knepley Ordering is lexicographic with lowest index as least significant in ordering. 14b4457527SToby Isaac e.g. for len == 2 and max == 2, this will return, in order, {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {0,2}. 156f905325SMatthew G. Knepley 166f905325SMatthew G. Knepley Input Parameters: 176f905325SMatthew G. Knepley + len - The length of the tuple 186f905325SMatthew G. Knepley . max - The maximum sum 196f905325SMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 206f905325SMatthew G. Knepley 216f905325SMatthew G. Knepley Output Parameter: 226f905325SMatthew G. Knepley . tup - A tuple of len integers whos sum is at most 'max' 236f905325SMatthew G. Knepley 246f905325SMatthew G. Knepley Level: developer 256f905325SMatthew G. Knepley 266f905325SMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal() 276f905325SMatthew G. Knepley */ 286f905325SMatthew G. Knepley PetscErrorCode PetscDualSpaceLatticePointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) 296f905325SMatthew G. Knepley { 306f905325SMatthew G. Knepley PetscFunctionBegin; 316f905325SMatthew G. Knepley while (len--) { 326f905325SMatthew G. Knepley max -= tup[len]; 336f905325SMatthew G. Knepley if (!max) { 346f905325SMatthew G. Knepley tup[len] = 0; 356f905325SMatthew G. Knepley break; 366f905325SMatthew G. Knepley } 376f905325SMatthew G. Knepley } 386f905325SMatthew G. Knepley tup[++len]++; 396f905325SMatthew G. Knepley PetscFunctionReturn(0); 406f905325SMatthew G. Knepley } 416f905325SMatthew G. Knepley 426f905325SMatthew G. Knepley /* 436f905325SMatthew G. Knepley PetscDualSpaceTensorPointLexicographic_Internal - Returns all tuples of size 'len' with nonnegative integers that are all less than or equal to 'max'. 446f905325SMatthew G. Knepley Ordering is lexicographic with lowest index as least significant in ordering. 456f905325SMatthew G. Knepley e.g. for len == 2 and max == 2, this will return, in order, {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0,2}, {1,2}, {2,2}. 466f905325SMatthew G. Knepley 476f905325SMatthew G. Knepley Input Parameters: 486f905325SMatthew G. Knepley + len - The length of the tuple 496f905325SMatthew G. Knepley . max - The maximum value 506f905325SMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 516f905325SMatthew G. Knepley 526f905325SMatthew G. Knepley Output Parameter: 536f905325SMatthew G. Knepley . tup - A tuple of len integers whos sum is at most 'max' 546f905325SMatthew G. Knepley 556f905325SMatthew G. Knepley Level: developer 566f905325SMatthew G. Knepley 576f905325SMatthew G. Knepley .seealso: PetscDualSpaceLatticePointLexicographic_Internal() 586f905325SMatthew G. Knepley */ 596f905325SMatthew G. Knepley PetscErrorCode PetscDualSpaceTensorPointLexicographic_Internal(PetscInt len, PetscInt max, PetscInt tup[]) 606f905325SMatthew G. Knepley { 616f905325SMatthew G. Knepley PetscInt i; 626f905325SMatthew G. Knepley 636f905325SMatthew G. Knepley PetscFunctionBegin; 646f905325SMatthew G. Knepley for (i = 0; i < len; i++) { 656f905325SMatthew G. Knepley if (tup[i] < max) { 666f905325SMatthew G. Knepley break; 676f905325SMatthew G. Knepley } else { 686f905325SMatthew G. Knepley tup[i] = 0; 696f905325SMatthew G. Knepley } 706f905325SMatthew G. Knepley } 716f905325SMatthew G. Knepley tup[i]++; 726f905325SMatthew G. Knepley PetscFunctionReturn(0); 736f905325SMatthew G. Knepley } 746f905325SMatthew G. Knepley 7520cf1dd8SToby Isaac /*@C 7620cf1dd8SToby Isaac PetscDualSpaceRegister - Adds a new PetscDualSpace implementation 7720cf1dd8SToby Isaac 7820cf1dd8SToby Isaac Not Collective 7920cf1dd8SToby Isaac 8020cf1dd8SToby Isaac Input Parameters: 8120cf1dd8SToby Isaac + name - The name of a new user-defined creation routine 8220cf1dd8SToby Isaac - create_func - The creation routine itself 8320cf1dd8SToby Isaac 8420cf1dd8SToby Isaac Notes: 8520cf1dd8SToby Isaac PetscDualSpaceRegister() may be called multiple times to add several user-defined PetscDualSpaces 8620cf1dd8SToby Isaac 8720cf1dd8SToby Isaac Sample usage: 8820cf1dd8SToby Isaac .vb 8920cf1dd8SToby Isaac PetscDualSpaceRegister("my_space", MyPetscDualSpaceCreate); 9020cf1dd8SToby Isaac .ve 9120cf1dd8SToby Isaac 9220cf1dd8SToby Isaac Then, your PetscDualSpace type can be chosen with the procedural interface via 9320cf1dd8SToby Isaac .vb 9420cf1dd8SToby Isaac PetscDualSpaceCreate(MPI_Comm, PetscDualSpace *); 9520cf1dd8SToby Isaac PetscDualSpaceSetType(PetscDualSpace, "my_dual_space"); 9620cf1dd8SToby Isaac .ve 9720cf1dd8SToby Isaac or at runtime via the option 9820cf1dd8SToby Isaac .vb 9920cf1dd8SToby Isaac -petscdualspace_type my_dual_space 10020cf1dd8SToby Isaac .ve 10120cf1dd8SToby Isaac 10220cf1dd8SToby Isaac Level: advanced 10320cf1dd8SToby Isaac 10420cf1dd8SToby Isaac .seealso: PetscDualSpaceRegisterAll(), PetscDualSpaceRegisterDestroy() 10520cf1dd8SToby Isaac 10620cf1dd8SToby Isaac @*/ 10720cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceRegister(const char sname[], PetscErrorCode (*function)(PetscDualSpace)) 10820cf1dd8SToby Isaac { 10920cf1dd8SToby Isaac PetscFunctionBegin; 1105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFunctionListAdd(&PetscDualSpaceList, sname, function)); 11120cf1dd8SToby Isaac PetscFunctionReturn(0); 11220cf1dd8SToby Isaac } 11320cf1dd8SToby Isaac 11420cf1dd8SToby Isaac /*@C 11520cf1dd8SToby Isaac PetscDualSpaceSetType - Builds a particular PetscDualSpace 11620cf1dd8SToby Isaac 117d083f849SBarry Smith Collective on sp 11820cf1dd8SToby Isaac 11920cf1dd8SToby Isaac Input Parameters: 12020cf1dd8SToby Isaac + sp - The PetscDualSpace object 12120cf1dd8SToby Isaac - name - The kind of space 12220cf1dd8SToby Isaac 12320cf1dd8SToby Isaac Options Database Key: 12420cf1dd8SToby Isaac . -petscdualspace_type <type> - Sets the PetscDualSpace type; use -help for a list of available types 12520cf1dd8SToby Isaac 12620cf1dd8SToby Isaac Level: intermediate 12720cf1dd8SToby Isaac 12820cf1dd8SToby Isaac .seealso: PetscDualSpaceGetType(), PetscDualSpaceCreate() 12920cf1dd8SToby Isaac @*/ 13020cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetType(PetscDualSpace sp, PetscDualSpaceType name) 13120cf1dd8SToby Isaac { 13220cf1dd8SToby Isaac PetscErrorCode (*r)(PetscDualSpace); 13320cf1dd8SToby Isaac PetscBool match; 13420cf1dd8SToby Isaac 13520cf1dd8SToby Isaac PetscFunctionBegin; 13620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) sp, name, &match)); 13820cf1dd8SToby Isaac if (match) PetscFunctionReturn(0); 13920cf1dd8SToby Isaac 1405f80ce2aSJacob Faibussowitsch if (!PetscDualSpaceRegisterAllCalled) CHKERRQ(PetscDualSpaceRegisterAll()); 1415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFunctionListFind(PetscDualSpaceList, name, &r)); 142*28b400f6SJacob Faibussowitsch PetscCheck(r,PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDualSpace type: %s", name); 14320cf1dd8SToby Isaac 14420cf1dd8SToby Isaac if (sp->ops->destroy) { 1455f80ce2aSJacob Faibussowitsch CHKERRQ((*sp->ops->destroy)(sp)); 14620cf1dd8SToby Isaac sp->ops->destroy = NULL; 14720cf1dd8SToby Isaac } 1485f80ce2aSJacob Faibussowitsch CHKERRQ((*r)(sp)); 1495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectChangeTypeName((PetscObject) sp, name)); 15020cf1dd8SToby Isaac PetscFunctionReturn(0); 15120cf1dd8SToby Isaac } 15220cf1dd8SToby Isaac 15320cf1dd8SToby Isaac /*@C 15420cf1dd8SToby Isaac PetscDualSpaceGetType - Gets the PetscDualSpace type name (as a string) from the object. 15520cf1dd8SToby Isaac 15620cf1dd8SToby Isaac Not Collective 15720cf1dd8SToby Isaac 15820cf1dd8SToby Isaac Input Parameter: 15920cf1dd8SToby Isaac . sp - The PetscDualSpace 16020cf1dd8SToby Isaac 16120cf1dd8SToby Isaac Output Parameter: 16220cf1dd8SToby Isaac . name - The PetscDualSpace type name 16320cf1dd8SToby Isaac 16420cf1dd8SToby Isaac Level: intermediate 16520cf1dd8SToby Isaac 16620cf1dd8SToby Isaac .seealso: PetscDualSpaceSetType(), PetscDualSpaceCreate() 16720cf1dd8SToby Isaac @*/ 16820cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetType(PetscDualSpace sp, PetscDualSpaceType *name) 16920cf1dd8SToby Isaac { 17020cf1dd8SToby Isaac PetscFunctionBegin; 17120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 17220cf1dd8SToby Isaac PetscValidPointer(name, 2); 17320cf1dd8SToby Isaac if (!PetscDualSpaceRegisterAllCalled) { 1745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceRegisterAll()); 17520cf1dd8SToby Isaac } 17620cf1dd8SToby Isaac *name = ((PetscObject) sp)->type_name; 17720cf1dd8SToby Isaac PetscFunctionReturn(0); 17820cf1dd8SToby Isaac } 17920cf1dd8SToby Isaac 180221d6281SMatthew G. Knepley static PetscErrorCode PetscDualSpaceView_ASCII(PetscDualSpace sp, PetscViewer v) 181221d6281SMatthew G. Knepley { 182221d6281SMatthew G. Knepley PetscViewerFormat format; 183221d6281SMatthew G. Knepley PetscInt pdim, f; 184221d6281SMatthew G. Knepley 185221d6281SMatthew G. Knepley PetscFunctionBegin; 1865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDimension(sp, &pdim)); 1875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectPrintClassNamePrefixType((PetscObject) sp, v)); 1885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushTab(v)); 189b4457527SToby Isaac if (sp->k) { 1905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(v, "Dual space for %D-forms %swith %D components, size %D\n", PetscAbsInt(sp->k), sp->k < 0 ? "(stored in dual form) ": "", sp->Nc, pdim)); 191b4457527SToby Isaac } else { 1925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(v, "Dual space with %D components, size %D\n", sp->Nc, pdim)); 193b4457527SToby Isaac } 1945f80ce2aSJacob Faibussowitsch if (sp->ops->view) CHKERRQ((*sp->ops->view)(sp, v)); 1955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetFormat(v, &format)); 196221d6281SMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushTab(v)); 198221d6281SMatthew G. Knepley for (f = 0; f < pdim; ++f) { 1995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(v, "Dual basis vector %D\n", f)); 2005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushTab(v)); 2015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureView(sp->functional[f], v)); 2025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopTab(v)); 203221d6281SMatthew G. Knepley } 2045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopTab(v)); 205221d6281SMatthew G. Knepley } 2065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopTab(v)); 207221d6281SMatthew G. Knepley PetscFunctionReturn(0); 208221d6281SMatthew G. Knepley } 209221d6281SMatthew G. Knepley 210fe2efc57SMark /*@C 211fe2efc57SMark PetscDualSpaceViewFromOptions - View from Options 212fe2efc57SMark 213fe2efc57SMark Collective on PetscDualSpace 214fe2efc57SMark 215fe2efc57SMark Input Parameters: 216fe2efc57SMark + A - the PetscDualSpace object 217736c3998SJose E. Roman . obj - Optional object, proivides prefix 218736c3998SJose E. Roman - name - command line option 219fe2efc57SMark 220fe2efc57SMark Level: intermediate 221fe2efc57SMark .seealso: PetscDualSpace, PetscDualSpaceView(), PetscObjectViewFromOptions(), PetscDualSpaceCreate() 222fe2efc57SMark @*/ 223fe2efc57SMark PetscErrorCode PetscDualSpaceViewFromOptions(PetscDualSpace A,PetscObject obj,const char name[]) 224fe2efc57SMark { 225fe2efc57SMark PetscFunctionBegin; 226fe2efc57SMark PetscValidHeaderSpecific(A,PETSCDUALSPACE_CLASSID,1); 2275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectViewFromOptions((PetscObject)A,obj,name)); 228fe2efc57SMark PetscFunctionReturn(0); 229fe2efc57SMark } 230fe2efc57SMark 23120cf1dd8SToby Isaac /*@ 23220cf1dd8SToby Isaac PetscDualSpaceView - Views a PetscDualSpace 23320cf1dd8SToby Isaac 234d083f849SBarry Smith Collective on sp 23520cf1dd8SToby Isaac 236d8d19677SJose E. Roman Input Parameters: 23720cf1dd8SToby Isaac + sp - the PetscDualSpace object to view 23820cf1dd8SToby Isaac - v - the viewer 23920cf1dd8SToby Isaac 240a4ce7ad1SMatthew G. Knepley Level: beginner 24120cf1dd8SToby Isaac 242fe2efc57SMark .seealso PetscDualSpaceDestroy(), PetscDualSpace 24320cf1dd8SToby Isaac @*/ 24420cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceView(PetscDualSpace sp, PetscViewer v) 24520cf1dd8SToby Isaac { 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); 2515f80ce2aSJacob Faibussowitsch if (!v) CHKERRQ(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) sp), &v)); 2525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii)); 2535f80ce2aSJacob Faibussowitsch if (iascii) CHKERRQ(PetscDualSpaceView_ASCII(sp, v)); 25420cf1dd8SToby Isaac PetscFunctionReturn(0); 25520cf1dd8SToby Isaac } 25620cf1dd8SToby Isaac 25720cf1dd8SToby Isaac /*@ 25820cf1dd8SToby Isaac PetscDualSpaceSetFromOptions - sets parameters in a PetscDualSpace from the options database 25920cf1dd8SToby Isaac 260d083f849SBarry Smith Collective on sp 26120cf1dd8SToby Isaac 26220cf1dd8SToby Isaac Input Parameter: 26320cf1dd8SToby Isaac . sp - the PetscDualSpace object to set options for 26420cf1dd8SToby Isaac 26520cf1dd8SToby Isaac Options Database: 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 2698f2aacc6SMatthew G. Knepley - -petscdualspace_refcell <celltype> - Reference cell type name 27020cf1dd8SToby Isaac 271a4ce7ad1SMatthew G. Knepley Level: intermediate 27220cf1dd8SToby Isaac 273fe2efc57SMark .seealso PetscDualSpaceView(), PetscDualSpace, PetscObjectSetFromOptions() 27420cf1dd8SToby Isaac @*/ 27520cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetFromOptions(PetscDualSpace sp) 27620cf1dd8SToby Isaac { 2772df84da0SMatthew G. Knepley DMPolytopeType refCell = DM_POLYTOPE_TRIANGLE; 27820cf1dd8SToby Isaac const char *defaultType; 27920cf1dd8SToby Isaac char name[256]; 280f783ec47SMatthew G. Knepley PetscBool flg; 28120cf1dd8SToby Isaac PetscErrorCode ierr; 28220cf1dd8SToby Isaac 28320cf1dd8SToby Isaac PetscFunctionBegin; 28420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 28520cf1dd8SToby Isaac if (!((PetscObject) sp)->type_name) { 28620cf1dd8SToby Isaac defaultType = PETSCDUALSPACELAGRANGE; 28720cf1dd8SToby Isaac } else { 28820cf1dd8SToby Isaac defaultType = ((PetscObject) sp)->type_name; 28920cf1dd8SToby Isaac } 2905f80ce2aSJacob Faibussowitsch if (!PetscSpaceRegisterAllCalled) CHKERRQ(PetscSpaceRegisterAll()); 29120cf1dd8SToby Isaac 29220cf1dd8SToby Isaac ierr = PetscObjectOptionsBegin((PetscObject) sp);CHKERRQ(ierr); 2935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsFList("-petscdualspace_type", "Dual space", "PetscDualSpaceSetType", PetscDualSpaceList, defaultType, name, 256, &flg)); 29420cf1dd8SToby Isaac if (flg) { 2955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSetType(sp, name)); 29620cf1dd8SToby Isaac } else if (!((PetscObject) sp)->type_name) { 2975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSetType(sp, defaultType)); 29820cf1dd8SToby Isaac } 2995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-petscdualspace_order", "The approximation order", "PetscDualSpaceSetOrder", sp->order, &sp->order, NULL,0)); 3005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-petscdualspace_form_degree", "The form degree of the dofs", "PetscDualSpaceSetFormDegree", sp->k, &sp->k, NULL)); 3015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBoundedInt("-petscdualspace_components", "The number of components", "PetscDualSpaceSetNumComponents", sp->Nc, &sp->Nc, NULL,1)); 30220cf1dd8SToby Isaac if (sp->ops->setfromoptions) { 3035f80ce2aSJacob Faibussowitsch CHKERRQ((*sp->ops->setfromoptions)(PetscOptionsObject,sp)); 30420cf1dd8SToby Isaac } 3055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnum("-petscdualspace_refcell", "Reference cell shape", "PetscDualSpaceSetReferenceCell", DMPolytopeTypes, (PetscEnum) refCell, (PetscEnum *) &refCell, &flg)); 306063ee4adSMatthew G. Knepley if (flg) { 307063ee4adSMatthew G. Knepley DM K; 308063ee4adSMatthew G. Knepley 3095f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateReferenceCell(PETSC_COMM_SELF, refCell, &K)); 3105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSetDM(sp, K)); 3115f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&K)); 312063ee4adSMatthew G. Knepley } 313063ee4adSMatthew G. Knepley 31420cf1dd8SToby Isaac /* process any options handlers added with PetscObjectAddOptionsHandler() */ 3155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) sp)); 31620cf1dd8SToby Isaac ierr = PetscOptionsEnd();CHKERRQ(ierr); 317063ee4adSMatthew G. Knepley sp->setfromoptionscalled = PETSC_TRUE; 31820cf1dd8SToby Isaac PetscFunctionReturn(0); 31920cf1dd8SToby Isaac } 32020cf1dd8SToby Isaac 32120cf1dd8SToby Isaac /*@ 32220cf1dd8SToby Isaac PetscDualSpaceSetUp - Construct a basis for the PetscDualSpace 32320cf1dd8SToby Isaac 324d083f849SBarry Smith Collective on sp 32520cf1dd8SToby Isaac 32620cf1dd8SToby Isaac Input Parameter: 32720cf1dd8SToby Isaac . sp - the PetscDualSpace object to setup 32820cf1dd8SToby Isaac 329a4ce7ad1SMatthew G. Knepley Level: intermediate 33020cf1dd8SToby Isaac 331fe2efc57SMark .seealso PetscDualSpaceView(), PetscDualSpaceDestroy(), PetscDualSpace 33220cf1dd8SToby Isaac @*/ 33320cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetUp(PetscDualSpace sp) 33420cf1dd8SToby Isaac { 33520cf1dd8SToby Isaac PetscFunctionBegin; 33620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 33720cf1dd8SToby Isaac if (sp->setupcalled) PetscFunctionReturn(0); 3385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 33920cf1dd8SToby Isaac sp->setupcalled = PETSC_TRUE; 3405f80ce2aSJacob Faibussowitsch if (sp->ops->setup) CHKERRQ((*sp->ops->setup)(sp)); 3415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PETSCDUALSPACE_SetUp, sp, 0, 0, 0)); 3425f80ce2aSJacob Faibussowitsch if (sp->setfromoptionscalled) CHKERRQ(PetscDualSpaceViewFromOptions(sp, NULL, "-petscdualspace_view")); 34320cf1dd8SToby Isaac PetscFunctionReturn(0); 34420cf1dd8SToby Isaac } 34520cf1dd8SToby Isaac 346b4457527SToby Isaac static PetscErrorCode PetscDualSpaceClearDMData_Internal(PetscDualSpace sp, DM dm) 347b4457527SToby Isaac { 348b4457527SToby Isaac PetscInt pStart = -1, pEnd = -1, depth = -1; 349b4457527SToby Isaac 350b4457527SToby Isaac PetscFunctionBegin; 351b4457527SToby Isaac if (!dm) PetscFunctionReturn(0); 3525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 3535f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 354b4457527SToby Isaac 355b4457527SToby Isaac if (sp->pointSpaces) { 356b4457527SToby Isaac PetscInt i; 357b4457527SToby Isaac 358b4457527SToby Isaac for (i = 0; i < pEnd - pStart; i++) { 3595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceDestroy(&(sp->pointSpaces[i]))); 360b4457527SToby Isaac } 361b4457527SToby Isaac } 3625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(sp->pointSpaces)); 363b4457527SToby Isaac 364b4457527SToby Isaac if (sp->heightSpaces) { 365b4457527SToby Isaac PetscInt i; 366b4457527SToby Isaac 367b4457527SToby Isaac for (i = 0; i <= depth; i++) { 3685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceDestroy(&(sp->heightSpaces[i]))); 369b4457527SToby Isaac } 370b4457527SToby Isaac } 3715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(sp->heightSpaces)); 372b4457527SToby Isaac 3735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&(sp->pointSection))); 3745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureDestroy(&(sp->intNodes))); 3755f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&(sp->intDofValues))); 3765f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&(sp->intNodeValues))); 3775f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&(sp->intMat))); 3785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureDestroy(&(sp->allNodes))); 3795f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&(sp->allDofValues))); 3805f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&(sp->allNodeValues))); 3815f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&(sp->allMat))); 3825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(sp->numDof)); 383b4457527SToby Isaac PetscFunctionReturn(0); 384b4457527SToby Isaac } 385b4457527SToby Isaac 38620cf1dd8SToby Isaac /*@ 38720cf1dd8SToby Isaac PetscDualSpaceDestroy - Destroys a PetscDualSpace object 38820cf1dd8SToby Isaac 389d083f849SBarry Smith Collective on sp 39020cf1dd8SToby Isaac 39120cf1dd8SToby Isaac Input Parameter: 39220cf1dd8SToby Isaac . sp - the PetscDualSpace object to destroy 39320cf1dd8SToby Isaac 394a4ce7ad1SMatthew G. Knepley Level: beginner 39520cf1dd8SToby Isaac 396fe2efc57SMark .seealso PetscDualSpaceView(), PetscDualSpace(), PetscDualSpaceCreate() 39720cf1dd8SToby Isaac @*/ 39820cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceDestroy(PetscDualSpace *sp) 39920cf1dd8SToby Isaac { 40020cf1dd8SToby Isaac PetscInt dim, f; 401b4457527SToby Isaac DM dm; 40220cf1dd8SToby Isaac 40320cf1dd8SToby Isaac PetscFunctionBegin; 40420cf1dd8SToby Isaac if (!*sp) PetscFunctionReturn(0); 40520cf1dd8SToby Isaac PetscValidHeaderSpecific((*sp), PETSCDUALSPACE_CLASSID, 1); 40620cf1dd8SToby Isaac 407ea78f98cSLisandro Dalcin if (--((PetscObject)(*sp))->refct > 0) {*sp = NULL; PetscFunctionReturn(0);} 40820cf1dd8SToby Isaac ((PetscObject) (*sp))->refct = 0; 40920cf1dd8SToby Isaac 4105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDimension(*sp, &dim)); 411b4457527SToby Isaac dm = (*sp)->dm; 412b4457527SToby Isaac 4135f80ce2aSJacob Faibussowitsch if ((*sp)->ops->destroy) CHKERRQ((*(*sp)->ops->destroy)(*sp)); 4145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceClearDMData_Internal(*sp, dm)); 415b4457527SToby Isaac 41620cf1dd8SToby Isaac for (f = 0; f < dim; ++f) { 4175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureDestroy(&(*sp)->functional[f])); 41820cf1dd8SToby Isaac } 4195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*sp)->functional)); 4205f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&(*sp)->dm)); 4215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHeaderDestroy(sp)); 42220cf1dd8SToby Isaac PetscFunctionReturn(0); 42320cf1dd8SToby Isaac } 42420cf1dd8SToby Isaac 42520cf1dd8SToby Isaac /*@ 42620cf1dd8SToby Isaac PetscDualSpaceCreate - Creates an empty PetscDualSpace object. The type can then be set with PetscDualSpaceSetType(). 42720cf1dd8SToby Isaac 428d083f849SBarry Smith Collective 42920cf1dd8SToby Isaac 43020cf1dd8SToby Isaac Input Parameter: 43120cf1dd8SToby Isaac . comm - The communicator for the PetscDualSpace object 43220cf1dd8SToby Isaac 43320cf1dd8SToby Isaac Output Parameter: 43420cf1dd8SToby Isaac . sp - The PetscDualSpace object 43520cf1dd8SToby Isaac 43620cf1dd8SToby Isaac Level: beginner 43720cf1dd8SToby Isaac 43820cf1dd8SToby Isaac .seealso: PetscDualSpaceSetType(), PETSCDUALSPACELAGRANGE 43920cf1dd8SToby Isaac @*/ 44020cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceCreate(MPI_Comm comm, PetscDualSpace *sp) 44120cf1dd8SToby Isaac { 44220cf1dd8SToby Isaac PetscDualSpace s; 44320cf1dd8SToby Isaac 44420cf1dd8SToby Isaac PetscFunctionBegin; 44520cf1dd8SToby Isaac PetscValidPointer(sp, 2); 4465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCitationsRegister(FECitation,&FEcite)); 44720cf1dd8SToby Isaac *sp = NULL; 4485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEInitializePackage()); 44920cf1dd8SToby Isaac 4505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHeaderCreate(s, PETSCDUALSPACE_CLASSID, "PetscDualSpace", "Dual Space", "PetscDualSpace", comm, PetscDualSpaceDestroy, PetscDualSpaceView)); 45120cf1dd8SToby Isaac 45220cf1dd8SToby Isaac s->order = 0; 45320cf1dd8SToby Isaac s->Nc = 1; 4544bee2e38SMatthew G. Knepley s->k = 0; 455b4457527SToby Isaac s->spdim = -1; 456b4457527SToby Isaac s->spintdim = -1; 457b4457527SToby Isaac s->uniform = PETSC_TRUE; 45820cf1dd8SToby Isaac s->setupcalled = PETSC_FALSE; 45920cf1dd8SToby Isaac 46020cf1dd8SToby Isaac *sp = s; 46120cf1dd8SToby Isaac PetscFunctionReturn(0); 46220cf1dd8SToby Isaac } 46320cf1dd8SToby Isaac 46420cf1dd8SToby Isaac /*@ 46520cf1dd8SToby Isaac PetscDualSpaceDuplicate - Creates a duplicate PetscDualSpace object, however it is not setup. 46620cf1dd8SToby Isaac 467d083f849SBarry Smith Collective on sp 46820cf1dd8SToby Isaac 46920cf1dd8SToby Isaac Input Parameter: 47020cf1dd8SToby Isaac . sp - The original PetscDualSpace 47120cf1dd8SToby Isaac 47220cf1dd8SToby Isaac Output Parameter: 47320cf1dd8SToby Isaac . spNew - The duplicate PetscDualSpace 47420cf1dd8SToby Isaac 47520cf1dd8SToby Isaac Level: beginner 47620cf1dd8SToby Isaac 47720cf1dd8SToby Isaac .seealso: PetscDualSpaceCreate(), PetscDualSpaceSetType() 47820cf1dd8SToby Isaac @*/ 47920cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceDuplicate(PetscDualSpace sp, PetscDualSpace *spNew) 48020cf1dd8SToby Isaac { 481b4457527SToby Isaac DM dm; 482b4457527SToby Isaac PetscDualSpaceType type; 483b4457527SToby Isaac const char *name; 48420cf1dd8SToby Isaac 48520cf1dd8SToby Isaac PetscFunctionBegin; 48620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 48720cf1dd8SToby Isaac PetscValidPointer(spNew, 2); 4885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceCreate(PetscObjectComm((PetscObject)sp), spNew)); 4895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) sp, &name)); 4905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) *spNew, name)); 4915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetType(sp, &type)); 4925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSetType(*spNew, type)); 4935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDM(sp, &dm)); 4945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSetDM(*spNew, dm)); 495b4457527SToby Isaac 496b4457527SToby Isaac (*spNew)->order = sp->order; 497b4457527SToby Isaac (*spNew)->k = sp->k; 498b4457527SToby Isaac (*spNew)->Nc = sp->Nc; 499b4457527SToby Isaac (*spNew)->uniform = sp->uniform; 5005f80ce2aSJacob Faibussowitsch if (sp->ops->duplicate) CHKERRQ((*sp->ops->duplicate)(sp, *spNew)); 50120cf1dd8SToby Isaac PetscFunctionReturn(0); 50220cf1dd8SToby Isaac } 50320cf1dd8SToby Isaac 50420cf1dd8SToby Isaac /*@ 50520cf1dd8SToby Isaac PetscDualSpaceGetDM - Get the DM representing the reference cell 50620cf1dd8SToby Isaac 50720cf1dd8SToby Isaac Not collective 50820cf1dd8SToby Isaac 50920cf1dd8SToby Isaac Input Parameter: 51020cf1dd8SToby Isaac . sp - The PetscDualSpace 51120cf1dd8SToby Isaac 51220cf1dd8SToby Isaac Output Parameter: 51320cf1dd8SToby Isaac . dm - The reference cell 51420cf1dd8SToby Isaac 51520cf1dd8SToby Isaac Level: intermediate 51620cf1dd8SToby Isaac 51720cf1dd8SToby Isaac .seealso: PetscDualSpaceSetDM(), PetscDualSpaceCreate() 51820cf1dd8SToby Isaac @*/ 51920cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetDM(PetscDualSpace sp, DM *dm) 52020cf1dd8SToby Isaac { 52120cf1dd8SToby Isaac PetscFunctionBegin; 52220cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 52320cf1dd8SToby Isaac PetscValidPointer(dm, 2); 52420cf1dd8SToby Isaac *dm = sp->dm; 52520cf1dd8SToby Isaac PetscFunctionReturn(0); 52620cf1dd8SToby Isaac } 52720cf1dd8SToby Isaac 52820cf1dd8SToby Isaac /*@ 52920cf1dd8SToby Isaac PetscDualSpaceSetDM - Get the DM representing the reference cell 53020cf1dd8SToby Isaac 53120cf1dd8SToby Isaac Not collective 53220cf1dd8SToby Isaac 53320cf1dd8SToby Isaac Input Parameters: 53420cf1dd8SToby Isaac + sp - The PetscDualSpace 53520cf1dd8SToby Isaac - dm - The reference cell 53620cf1dd8SToby Isaac 53720cf1dd8SToby Isaac Level: intermediate 53820cf1dd8SToby Isaac 53920cf1dd8SToby Isaac .seealso: PetscDualSpaceGetDM(), PetscDualSpaceCreate() 54020cf1dd8SToby Isaac @*/ 54120cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetDM(PetscDualSpace sp, DM dm) 54220cf1dd8SToby Isaac { 54320cf1dd8SToby Isaac PetscFunctionBegin; 54420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 54520cf1dd8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 546*28b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled,PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change DM after dualspace is set up"); 5475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) dm)); 548b4457527SToby Isaac if (sp->dm && sp->dm != dm) { 5495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceClearDMData_Internal(sp, sp->dm)); 550b4457527SToby Isaac } 5515f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&sp->dm)); 55220cf1dd8SToby Isaac sp->dm = dm; 55320cf1dd8SToby Isaac PetscFunctionReturn(0); 55420cf1dd8SToby Isaac } 55520cf1dd8SToby Isaac 55620cf1dd8SToby Isaac /*@ 55720cf1dd8SToby Isaac PetscDualSpaceGetOrder - Get the order of the dual space 55820cf1dd8SToby Isaac 55920cf1dd8SToby Isaac Not collective 56020cf1dd8SToby Isaac 56120cf1dd8SToby Isaac Input Parameter: 56220cf1dd8SToby Isaac . sp - The PetscDualSpace 56320cf1dd8SToby Isaac 56420cf1dd8SToby Isaac Output Parameter: 56520cf1dd8SToby Isaac . order - The order 56620cf1dd8SToby Isaac 56720cf1dd8SToby Isaac Level: intermediate 56820cf1dd8SToby Isaac 56920cf1dd8SToby Isaac .seealso: PetscDualSpaceSetOrder(), PetscDualSpaceCreate() 57020cf1dd8SToby Isaac @*/ 57120cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetOrder(PetscDualSpace sp, PetscInt *order) 57220cf1dd8SToby Isaac { 57320cf1dd8SToby Isaac PetscFunctionBegin; 57420cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 57520cf1dd8SToby Isaac PetscValidPointer(order, 2); 57620cf1dd8SToby Isaac *order = sp->order; 57720cf1dd8SToby Isaac PetscFunctionReturn(0); 57820cf1dd8SToby Isaac } 57920cf1dd8SToby Isaac 58020cf1dd8SToby Isaac /*@ 58120cf1dd8SToby Isaac PetscDualSpaceSetOrder - Set the order of the dual space 58220cf1dd8SToby Isaac 58320cf1dd8SToby Isaac Not collective 58420cf1dd8SToby Isaac 58520cf1dd8SToby Isaac Input Parameters: 58620cf1dd8SToby Isaac + sp - The PetscDualSpace 58720cf1dd8SToby Isaac - order - The order 58820cf1dd8SToby Isaac 58920cf1dd8SToby Isaac Level: intermediate 59020cf1dd8SToby Isaac 59120cf1dd8SToby Isaac .seealso: PetscDualSpaceGetOrder(), PetscDualSpaceCreate() 59220cf1dd8SToby Isaac @*/ 59320cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetOrder(PetscDualSpace sp, PetscInt order) 59420cf1dd8SToby Isaac { 59520cf1dd8SToby Isaac PetscFunctionBegin; 59620cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 597*28b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled,PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change order after dualspace is set up"); 59820cf1dd8SToby Isaac sp->order = order; 59920cf1dd8SToby Isaac PetscFunctionReturn(0); 60020cf1dd8SToby Isaac } 60120cf1dd8SToby Isaac 60220cf1dd8SToby Isaac /*@ 60320cf1dd8SToby Isaac PetscDualSpaceGetNumComponents - Return the number of components for this space 60420cf1dd8SToby Isaac 60520cf1dd8SToby Isaac Input Parameter: 60620cf1dd8SToby Isaac . sp - The PetscDualSpace 60720cf1dd8SToby Isaac 60820cf1dd8SToby Isaac Output Parameter: 60920cf1dd8SToby Isaac . Nc - The number of components 61020cf1dd8SToby Isaac 61120cf1dd8SToby Isaac Note: A vector space, for example, will have d components, where d is the spatial dimension 61220cf1dd8SToby Isaac 61320cf1dd8SToby Isaac Level: intermediate 61420cf1dd8SToby Isaac 61520cf1dd8SToby Isaac .seealso: PetscDualSpaceSetNumComponents(), PetscDualSpaceGetDimension(), PetscDualSpaceCreate(), PetscDualSpace 61620cf1dd8SToby Isaac @*/ 61720cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetNumComponents(PetscDualSpace sp, PetscInt *Nc) 61820cf1dd8SToby Isaac { 61920cf1dd8SToby Isaac PetscFunctionBegin; 62020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 62120cf1dd8SToby Isaac PetscValidPointer(Nc, 2); 62220cf1dd8SToby Isaac *Nc = sp->Nc; 62320cf1dd8SToby Isaac PetscFunctionReturn(0); 62420cf1dd8SToby Isaac } 62520cf1dd8SToby Isaac 62620cf1dd8SToby Isaac /*@ 62720cf1dd8SToby Isaac PetscDualSpaceSetNumComponents - Set the number of components for this space 62820cf1dd8SToby Isaac 62920cf1dd8SToby Isaac Input Parameters: 63020cf1dd8SToby Isaac + sp - The PetscDualSpace 63120cf1dd8SToby Isaac - order - The number of components 63220cf1dd8SToby Isaac 63320cf1dd8SToby Isaac Level: intermediate 63420cf1dd8SToby Isaac 63520cf1dd8SToby Isaac .seealso: PetscDualSpaceGetNumComponents(), PetscDualSpaceCreate(), PetscDualSpace 63620cf1dd8SToby Isaac @*/ 63720cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceSetNumComponents(PetscDualSpace sp, PetscInt Nc) 63820cf1dd8SToby Isaac { 63920cf1dd8SToby Isaac PetscFunctionBegin; 64020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 641*28b400f6SJacob Faibussowitsch PetscCheck(!sp->setupcalled,PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 64220cf1dd8SToby Isaac sp->Nc = Nc; 64320cf1dd8SToby Isaac PetscFunctionReturn(0); 64420cf1dd8SToby Isaac } 64520cf1dd8SToby Isaac 64620cf1dd8SToby Isaac /*@ 64720cf1dd8SToby Isaac PetscDualSpaceGetFunctional - Get the i-th basis functional in the dual space 64820cf1dd8SToby Isaac 64920cf1dd8SToby Isaac Not collective 65020cf1dd8SToby Isaac 65120cf1dd8SToby Isaac Input Parameters: 65220cf1dd8SToby Isaac + sp - The PetscDualSpace 65320cf1dd8SToby Isaac - i - The basis number 65420cf1dd8SToby Isaac 65520cf1dd8SToby Isaac Output Parameter: 65620cf1dd8SToby Isaac . functional - The basis functional 65720cf1dd8SToby Isaac 65820cf1dd8SToby Isaac Level: intermediate 65920cf1dd8SToby Isaac 66020cf1dd8SToby Isaac .seealso: PetscDualSpaceGetDimension(), PetscDualSpaceCreate() 66120cf1dd8SToby Isaac @*/ 66220cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetFunctional(PetscDualSpace sp, PetscInt i, PetscQuadrature *functional) 66320cf1dd8SToby Isaac { 66420cf1dd8SToby Isaac PetscInt dim; 66520cf1dd8SToby Isaac 66620cf1dd8SToby Isaac PetscFunctionBegin; 66720cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 66820cf1dd8SToby Isaac PetscValidPointer(functional, 3); 6695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDimension(sp, &dim)); 6702c71b3e2SJacob Faibussowitsch PetscCheckFalse((i < 0) || (i >= dim),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Functional index %d must be in [0, %d)", i, dim); 67120cf1dd8SToby Isaac *functional = sp->functional[i]; 67220cf1dd8SToby Isaac PetscFunctionReturn(0); 67320cf1dd8SToby Isaac } 67420cf1dd8SToby Isaac 67520cf1dd8SToby Isaac /*@ 67620cf1dd8SToby Isaac PetscDualSpaceGetDimension - Get the dimension of the dual space, i.e. the number of basis functionals 67720cf1dd8SToby Isaac 67820cf1dd8SToby Isaac Not collective 67920cf1dd8SToby Isaac 68020cf1dd8SToby Isaac Input Parameter: 68120cf1dd8SToby Isaac . sp - The PetscDualSpace 68220cf1dd8SToby Isaac 68320cf1dd8SToby Isaac Output Parameter: 68420cf1dd8SToby Isaac . dim - The dimension 68520cf1dd8SToby Isaac 68620cf1dd8SToby Isaac Level: intermediate 68720cf1dd8SToby Isaac 68820cf1dd8SToby Isaac .seealso: PetscDualSpaceGetFunctional(), PetscDualSpaceCreate() 68920cf1dd8SToby Isaac @*/ 69020cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetDimension(PetscDualSpace sp, PetscInt *dim) 69120cf1dd8SToby Isaac { 69220cf1dd8SToby Isaac PetscFunctionBegin; 69320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 69420cf1dd8SToby Isaac PetscValidPointer(dim, 2); 695b4457527SToby Isaac if (sp->spdim < 0) { 696b4457527SToby Isaac PetscSection section; 697b4457527SToby Isaac 6985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetSection(sp, §ion)); 699b4457527SToby Isaac if (section) { 7005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(section, &(sp->spdim))); 701b4457527SToby Isaac } else sp->spdim = 0; 702b4457527SToby Isaac } 703b4457527SToby Isaac *dim = sp->spdim; 70420cf1dd8SToby Isaac PetscFunctionReturn(0); 70520cf1dd8SToby Isaac } 70620cf1dd8SToby Isaac 707b4457527SToby Isaac /*@ 708b4457527SToby 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 709b4457527SToby Isaac 710b4457527SToby Isaac Not collective 711b4457527SToby Isaac 712b4457527SToby Isaac Input Parameter: 713b4457527SToby Isaac . sp - The PetscDualSpace 714b4457527SToby Isaac 715b4457527SToby Isaac Output Parameter: 716b4457527SToby Isaac . dim - The dimension 717b4457527SToby Isaac 718b4457527SToby Isaac Level: intermediate 719b4457527SToby Isaac 720b4457527SToby Isaac .seealso: PetscDualSpaceGetFunctional(), PetscDualSpaceCreate() 721b4457527SToby Isaac @*/ 722b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetInteriorDimension(PetscDualSpace sp, PetscInt *intdim) 723b4457527SToby Isaac { 724b4457527SToby Isaac PetscFunctionBegin; 725b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 726b4457527SToby Isaac PetscValidPointer(intdim, 2); 727b4457527SToby Isaac if (sp->spintdim < 0) { 728b4457527SToby Isaac PetscSection section; 729b4457527SToby Isaac 7305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetSection(sp, §ion)); 731b4457527SToby Isaac if (section) { 7325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstrainedStorageSize(section, &(sp->spintdim))); 733b4457527SToby Isaac } else sp->spintdim = 0; 734b4457527SToby Isaac } 735b4457527SToby Isaac *intdim = sp->spintdim; 736b4457527SToby Isaac PetscFunctionReturn(0); 737b4457527SToby Isaac } 738b4457527SToby Isaac 739b4457527SToby Isaac /*@ 740b4457527SToby Isaac PetscDualSpaceGetUniform - Whether this dual space is uniform 741b4457527SToby Isaac 742b4457527SToby Isaac Not collective 743b4457527SToby Isaac 744b4457527SToby Isaac Input Parameters: 745b4457527SToby Isaac . sp - A dual space 746b4457527SToby Isaac 747b4457527SToby Isaac Output Parameters: 748b4457527SToby Isaac . uniform - PETSC_TRUE if (a) the dual space is the same for each point in a stratum of the reference DMPlex, and 749b4457527SToby Isaac (b) every symmetry of each point in the reference DMPlex is also a symmetry of the point's dual space. 750b4457527SToby Isaac 751b4457527SToby Isaac Level: advanced 752b4457527SToby Isaac 753b4457527SToby Isaac Note: all of the usual spaces on simplex or tensor-product elements will be uniform, only reference cells 754b4457527SToby Isaac with non-uniform strata (like trianguar-prisms) or anisotropic hp dual spaces will not be uniform. 755b4457527SToby Isaac 756b4457527SToby Isaac .seealso: PetscDualSpaceGetPointSubspace(), PetscDualSpaceGetSymmetries() 757b4457527SToby Isaac @*/ 758b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetUniform(PetscDualSpace sp, PetscBool *uniform) 759b4457527SToby Isaac { 760b4457527SToby Isaac PetscFunctionBegin; 761b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 762b4457527SToby Isaac PetscValidPointer(uniform, 2); 763b4457527SToby Isaac *uniform = sp->uniform; 764b4457527SToby Isaac PetscFunctionReturn(0); 765b4457527SToby Isaac } 766b4457527SToby Isaac 76720cf1dd8SToby Isaac /*@C 76820cf1dd8SToby Isaac PetscDualSpaceGetNumDof - Get the number of degrees of freedom for each spatial (topological) dimension 76920cf1dd8SToby Isaac 77020cf1dd8SToby Isaac Not collective 77120cf1dd8SToby Isaac 77220cf1dd8SToby Isaac Input Parameter: 77320cf1dd8SToby Isaac . sp - The PetscDualSpace 77420cf1dd8SToby Isaac 77520cf1dd8SToby Isaac Output Parameter: 77620cf1dd8SToby Isaac . numDof - An array of length dim+1 which holds the number of dofs for each dimension 77720cf1dd8SToby Isaac 77820cf1dd8SToby Isaac Level: intermediate 77920cf1dd8SToby Isaac 78020cf1dd8SToby Isaac .seealso: PetscDualSpaceGetFunctional(), PetscDualSpaceCreate() 78120cf1dd8SToby Isaac @*/ 78220cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetNumDof(PetscDualSpace sp, const PetscInt **numDof) 78320cf1dd8SToby Isaac { 78420cf1dd8SToby Isaac PetscFunctionBegin; 78520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 78620cf1dd8SToby Isaac PetscValidPointer(numDof, 2); 787*28b400f6SJacob 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"); 788b4457527SToby Isaac if (!sp->numDof) { 789b4457527SToby Isaac DM dm; 790b4457527SToby Isaac PetscInt depth, d; 791b4457527SToby Isaac PetscSection section; 792b4457527SToby Isaac 7935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDM(sp, &dm)); 7945f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 7955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(depth+1,&(sp->numDof))); 7965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetSection(sp, §ion)); 797b4457527SToby Isaac for (d = 0; d <= depth; d++) { 798b4457527SToby Isaac PetscInt dStart, dEnd; 799b4457527SToby Isaac 8005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd)); 801b4457527SToby Isaac if (dEnd <= dStart) continue; 8025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, dStart, &(sp->numDof[d]))); 803b4457527SToby Isaac 804b4457527SToby Isaac } 805b4457527SToby Isaac } 806b4457527SToby Isaac *numDof = sp->numDof; 8072c71b3e2SJacob Faibussowitsch PetscCheckFalse(!*numDof,PetscObjectComm((PetscObject) sp), PETSC_ERR_LIB, "Empty numDof[] returned from dual space implementation"); 80820cf1dd8SToby Isaac PetscFunctionReturn(0); 80920cf1dd8SToby Isaac } 81020cf1dd8SToby Isaac 811b4457527SToby Isaac /* create the section of the right size and set a permutation for topological ordering */ 812b4457527SToby Isaac PetscErrorCode PetscDualSpaceSectionCreate_Internal(PetscDualSpace sp, PetscSection *topSection) 813b4457527SToby Isaac { 814b4457527SToby Isaac DM dm; 815b4457527SToby Isaac PetscInt pStart, pEnd, cStart, cEnd, c, depth, count, i; 816b4457527SToby Isaac PetscInt *seen, *perm; 817b4457527SToby Isaac PetscSection section; 818b4457527SToby Isaac 819b4457527SToby Isaac PetscFunctionBegin; 820b4457527SToby Isaac dm = sp->dm; 8215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PETSC_COMM_SELF, §ion)); 8225f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 8235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(section, pStart, pEnd)); 8245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(pEnd - pStart, &seen)); 8255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd - pStart, &perm)); 8265f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 8275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 828b4457527SToby Isaac for (c = cStart, count = 0; c < cEnd; c++) { 829b4457527SToby Isaac PetscInt closureSize = -1, e; 830b4457527SToby Isaac PetscInt *closure = NULL; 831b4457527SToby Isaac 832b4457527SToby Isaac perm[count++] = c; 833b4457527SToby Isaac seen[c-pStart] = 1; 8345f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 835b4457527SToby Isaac for (e = 0; e < closureSize; e++) { 836b4457527SToby Isaac PetscInt point = closure[2*e]; 837b4457527SToby Isaac 838b4457527SToby Isaac if (seen[point-pStart]) continue; 839b4457527SToby Isaac perm[count++] = point; 840b4457527SToby Isaac seen[point-pStart] = 1; 841b4457527SToby Isaac } 8425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 843b4457527SToby Isaac } 8442c71b3e2SJacob Faibussowitsch PetscCheckFalse(count != pEnd - pStart,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad topological ordering"); 845b4457527SToby Isaac for (i = 0; i < pEnd - pStart; i++) if (perm[i] != i) break; 846b4457527SToby Isaac if (i < pEnd - pStart) { 847b4457527SToby Isaac IS permIS; 848b4457527SToby Isaac 8495f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF, pEnd - pStart, perm, PETSC_OWN_POINTER, &permIS)); 8505f80ce2aSJacob Faibussowitsch CHKERRQ(ISSetPermutation(permIS)); 8515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetPermutation(section, permIS)); 8525f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&permIS)); 853b4457527SToby Isaac } else { 8545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(perm)); 855b4457527SToby Isaac } 8565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(seen)); 857b4457527SToby Isaac *topSection = section; 858b4457527SToby Isaac PetscFunctionReturn(0); 859b4457527SToby Isaac } 860b4457527SToby Isaac 861b4457527SToby Isaac /* mark boundary points and set up */ 862b4457527SToby Isaac PetscErrorCode PetscDualSpaceSectionSetUp_Internal(PetscDualSpace sp, PetscSection section) 863b4457527SToby Isaac { 864b4457527SToby Isaac DM dm; 865b4457527SToby Isaac DMLabel boundary; 866b4457527SToby Isaac PetscInt pStart, pEnd, p; 867b4457527SToby Isaac 868b4457527SToby Isaac PetscFunctionBegin; 869b4457527SToby Isaac dm = sp->dm; 8705f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelCreate(PETSC_COMM_SELF,"boundary",&boundary)); 8715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDM(sp,&dm)); 8725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMarkBoundaryFaces(dm,1,boundary)); 8735f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLabelComplete(dm,boundary)); 8745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 875b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 876b4457527SToby Isaac PetscInt bval; 877b4457527SToby Isaac 8785f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(boundary, p, &bval)); 879b4457527SToby Isaac if (bval == 1) { 880b4457527SToby Isaac PetscInt dof; 881b4457527SToby Isaac 8825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, p, &dof)); 8835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetConstraintDof(section, p, dof)); 884b4457527SToby Isaac } 885b4457527SToby Isaac } 8865f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelDestroy(&boundary)); 8875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(section)); 888b4457527SToby Isaac PetscFunctionReturn(0); 889b4457527SToby Isaac } 890b4457527SToby Isaac 891a4ce7ad1SMatthew G. Knepley /*@ 892b4457527SToby Isaac PetscDualSpaceGetSection - Create a PetscSection over the reference cell with the layout from this space 893a4ce7ad1SMatthew G. Knepley 894a4ce7ad1SMatthew G. Knepley Collective on sp 895a4ce7ad1SMatthew G. Knepley 896a4ce7ad1SMatthew G. Knepley Input Parameters: 897f0fc11ceSJed Brown . sp - The PetscDualSpace 898a4ce7ad1SMatthew G. Knepley 899a4ce7ad1SMatthew G. Knepley Output Parameter: 900a4ce7ad1SMatthew G. Knepley . section - The section 901a4ce7ad1SMatthew G. Knepley 902a4ce7ad1SMatthew G. Knepley Level: advanced 903a4ce7ad1SMatthew G. Knepley 904a4ce7ad1SMatthew G. Knepley .seealso: PetscDualSpaceCreate(), DMPLEX 905a4ce7ad1SMatthew G. Knepley @*/ 906b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetSection(PetscDualSpace sp, PetscSection *section) 90720cf1dd8SToby Isaac { 908b4457527SToby Isaac PetscInt pStart, pEnd, p; 909b4457527SToby Isaac 910b4457527SToby Isaac PetscFunctionBegin; 911b4457527SToby Isaac if (!sp->pointSection) { 912b4457527SToby Isaac /* mark the boundary */ 9135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSectionCreate_Internal(sp, &(sp->pointSection))); 9145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(sp->dm,&pStart,&pEnd)); 915b4457527SToby Isaac for (p = pStart; p < pEnd; p++) { 916b4457527SToby Isaac PetscDualSpace psp; 917b4457527SToby Isaac 9185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetPointSubspace(sp, p, &psp)); 919b4457527SToby Isaac if (psp) { 920b4457527SToby Isaac PetscInt dof; 921b4457527SToby Isaac 9225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetInteriorDimension(psp, &dof)); 9235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetDof(sp->pointSection,p,dof)); 924b4457527SToby Isaac } 925b4457527SToby Isaac } 9265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceSectionSetUp_Internal(sp,sp->pointSection)); 927b4457527SToby Isaac } 928b4457527SToby Isaac *section = sp->pointSection; 929b4457527SToby Isaac PetscFunctionReturn(0); 930b4457527SToby Isaac } 931b4457527SToby Isaac 932b4457527SToby Isaac /* this assumes that all of the point dual spaces store their interior dofs first, which is true when the point DMs 933b4457527SToby Isaac * have one cell */ 934b4457527SToby Isaac PetscErrorCode PetscDualSpacePushForwardSubspaces_Internal(PetscDualSpace sp, PetscInt sStart, PetscInt sEnd) 935b4457527SToby Isaac { 936b4457527SToby Isaac PetscReal *sv0, *v0, *J; 937b4457527SToby Isaac PetscSection section; 938b4457527SToby Isaac PetscInt dim, s, k; 93920cf1dd8SToby Isaac DM dm; 94020cf1dd8SToby Isaac 94120cf1dd8SToby Isaac PetscFunctionBegin; 9425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDM(sp, &dm)); 9435f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 9445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetSection(sp, §ion)); 9455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(dim, &v0, dim, &sv0, dim*dim, &J)); 9465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFormDegree(sp, &k)); 947b4457527SToby Isaac for (s = sStart; s < sEnd; s++) { 948b4457527SToby Isaac PetscReal detJ, hdetJ; 949b4457527SToby Isaac PetscDualSpace ssp; 950b4457527SToby Isaac PetscInt dof, off, f, sdim; 951b4457527SToby Isaac PetscInt i, j; 952b4457527SToby Isaac DM sdm; 95320cf1dd8SToby Isaac 9545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetPointSubspace(sp, s, &ssp)); 955b4457527SToby Isaac if (!ssp) continue; 9565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, s, &dof)); 9575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, s, &off)); 958b4457527SToby Isaac /* get the first vertex of the reference cell */ 9595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDM(ssp, &sdm)); 9605f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(sdm, &sdim)); 9615f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryAffineFEM(sdm, 0, sv0, NULL, NULL, &hdetJ)); 9625f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryAffineFEM(dm, s, v0, J, NULL, &detJ)); 963b4457527SToby Isaac /* compactify Jacobian */ 964b4457527SToby Isaac for (i = 0; i < dim; i++) for (j = 0; j < sdim; j++) J[i* sdim + j] = J[i * dim + j]; 965b4457527SToby Isaac for (f = 0; f < dof; f++) { 966b4457527SToby Isaac PetscQuadrature fn; 96720cf1dd8SToby Isaac 9685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFunctional(ssp, f, &fn)); 9695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadraturePushForward(fn, dim, sv0, v0, J, k, &(sp->functional[off+f]))); 97020cf1dd8SToby Isaac } 97120cf1dd8SToby Isaac } 9725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(v0, sv0, J)); 97320cf1dd8SToby Isaac PetscFunctionReturn(0); 97420cf1dd8SToby Isaac } 97520cf1dd8SToby Isaac 97620cf1dd8SToby Isaac /*@C 97720cf1dd8SToby Isaac PetscDualSpaceApply - Apply a functional from the dual space basis to an input function 97820cf1dd8SToby Isaac 97920cf1dd8SToby Isaac Input Parameters: 98020cf1dd8SToby Isaac + sp - The PetscDualSpace object 98120cf1dd8SToby Isaac . f - The basis functional index 98220cf1dd8SToby Isaac . time - The time 98320cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian) (or evaluated at the coordinates of the functional) 98420cf1dd8SToby Isaac . numComp - The number of components for the function 98520cf1dd8SToby Isaac . func - The input function 98620cf1dd8SToby Isaac - ctx - A context for the function 98720cf1dd8SToby Isaac 98820cf1dd8SToby Isaac Output Parameter: 98920cf1dd8SToby Isaac . value - numComp output values 99020cf1dd8SToby Isaac 99120cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 99220cf1dd8SToby Isaac 99320cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 99420cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 99520cf1dd8SToby Isaac 996a4ce7ad1SMatthew G. Knepley Level: beginner 99720cf1dd8SToby Isaac 99820cf1dd8SToby Isaac .seealso: PetscDualSpaceCreate() 99920cf1dd8SToby Isaac @*/ 100020cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceApply(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFEGeom *cgeom, PetscInt numComp, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void *ctx, PetscScalar *value) 100120cf1dd8SToby Isaac { 100220cf1dd8SToby Isaac PetscFunctionBegin; 100320cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 100420cf1dd8SToby Isaac PetscValidPointer(cgeom, 4); 100520cf1dd8SToby Isaac PetscValidPointer(value, 8); 10065f80ce2aSJacob Faibussowitsch CHKERRQ((*sp->ops->apply)(sp, f, time, cgeom, numComp, func, ctx, value)); 100720cf1dd8SToby Isaac PetscFunctionReturn(0); 100820cf1dd8SToby Isaac } 100920cf1dd8SToby Isaac 101020cf1dd8SToby Isaac /*@C 1011b4457527SToby Isaac PetscDualSpaceApplyAll - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetAllData() 101220cf1dd8SToby Isaac 101320cf1dd8SToby Isaac Input Parameters: 101420cf1dd8SToby Isaac + sp - The PetscDualSpace object 1015b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetAllData() 101620cf1dd8SToby Isaac 101720cf1dd8SToby Isaac Output Parameter: 101820cf1dd8SToby Isaac . spValue - The values of all dual space functionals 101920cf1dd8SToby Isaac 1020a4ce7ad1SMatthew G. Knepley Level: beginner 102120cf1dd8SToby Isaac 102220cf1dd8SToby Isaac .seealso: PetscDualSpaceCreate() 102320cf1dd8SToby Isaac @*/ 102420cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceApplyAll(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 102520cf1dd8SToby Isaac { 102620cf1dd8SToby Isaac PetscFunctionBegin; 102720cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 10285f80ce2aSJacob Faibussowitsch CHKERRQ((*sp->ops->applyall)(sp, pointEval, spValue)); 102920cf1dd8SToby Isaac PetscFunctionReturn(0); 103020cf1dd8SToby Isaac } 103120cf1dd8SToby Isaac 103220cf1dd8SToby Isaac /*@C 1033b4457527SToby Isaac PetscDualSpaceApplyInterior - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetInteriorData() 1034b4457527SToby Isaac 1035b4457527SToby Isaac Input Parameters: 1036b4457527SToby Isaac + sp - The PetscDualSpace object 1037b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetInteriorData() 1038b4457527SToby Isaac 1039b4457527SToby Isaac Output Parameter: 1040b4457527SToby Isaac . spValue - The values of interior dual space functionals 1041b4457527SToby Isaac 1042b4457527SToby Isaac Level: beginner 1043b4457527SToby Isaac 1044b4457527SToby Isaac .seealso: PetscDualSpaceCreate() 1045b4457527SToby Isaac @*/ 1046b4457527SToby Isaac PetscErrorCode PetscDualSpaceApplyInterior(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1047b4457527SToby Isaac { 1048b4457527SToby Isaac PetscFunctionBegin; 1049b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 10505f80ce2aSJacob Faibussowitsch CHKERRQ((*sp->ops->applyint)(sp, pointEval, spValue)); 1051b4457527SToby Isaac PetscFunctionReturn(0); 1052b4457527SToby Isaac } 1053b4457527SToby Isaac 1054b4457527SToby Isaac /*@C 105520cf1dd8SToby Isaac PetscDualSpaceApplyDefault - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional. 105620cf1dd8SToby Isaac 105720cf1dd8SToby Isaac Input Parameters: 105820cf1dd8SToby Isaac + sp - The PetscDualSpace object 105920cf1dd8SToby Isaac . f - The basis functional index 106020cf1dd8SToby Isaac . time - The time 106120cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we use v0 (the initial vertex) and J (the Jacobian) 106220cf1dd8SToby Isaac . Nc - The number of components for the function 106320cf1dd8SToby Isaac . func - The input function 106420cf1dd8SToby Isaac - ctx - A context for the function 106520cf1dd8SToby Isaac 106620cf1dd8SToby Isaac Output Parameter: 106720cf1dd8SToby Isaac . value - The output value 106820cf1dd8SToby Isaac 106920cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 107020cf1dd8SToby Isaac 107120cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 107220cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 107320cf1dd8SToby Isaac 107420cf1dd8SToby Isaac and the idea is to evaluate the functional as an integral 107520cf1dd8SToby Isaac 107620cf1dd8SToby Isaac $ n(f) = int dx n(x) . f(x) 107720cf1dd8SToby Isaac 107820cf1dd8SToby Isaac where both n and f have Nc components. 107920cf1dd8SToby Isaac 1080a4ce7ad1SMatthew G. Knepley Level: beginner 108120cf1dd8SToby Isaac 108220cf1dd8SToby Isaac .seealso: PetscDualSpaceCreate() 108320cf1dd8SToby Isaac @*/ 108420cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceApplyDefault(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFEGeom *cgeom, PetscInt Nc, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void *ctx, PetscScalar *value) 108520cf1dd8SToby Isaac { 108620cf1dd8SToby Isaac DM dm; 108720cf1dd8SToby Isaac PetscQuadrature n; 108820cf1dd8SToby Isaac const PetscReal *points, *weights; 108920cf1dd8SToby Isaac PetscReal x[3]; 109020cf1dd8SToby Isaac PetscScalar *val; 109120cf1dd8SToby Isaac PetscInt dim, dE, qNc, c, Nq, q; 109220cf1dd8SToby Isaac PetscBool isAffine; 109320cf1dd8SToby Isaac 109420cf1dd8SToby Isaac PetscFunctionBegin; 109520cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1096064a246eSJacob Faibussowitsch PetscValidPointer(value, 8); 10975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDM(sp, &dm)); 10985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFunctional(sp, f, &n)); 10995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureGetData(n, &dim, &qNc, &Nq, &points, &weights)); 11002c71b3e2SJacob Faibussowitsch PetscCheckFalse(dim != cgeom->dim,PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_SIZ, "The quadrature spatial dimension %D != cell geometry dimension %D", dim, cgeom->dim); 11012c71b3e2SJacob Faibussowitsch PetscCheckFalse(qNc != Nc,PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_SIZ, "The quadrature components %D != function components %D", qNc, Nc); 11025f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 110320cf1dd8SToby Isaac *value = 0.0; 110420cf1dd8SToby Isaac isAffine = cgeom->isAffine; 110520cf1dd8SToby Isaac dE = cgeom->dimEmbed; 110620cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 110720cf1dd8SToby Isaac if (isAffine) { 110820cf1dd8SToby Isaac CoordinatesRefToReal(dE, cgeom->dim, cgeom->xi, cgeom->v, cgeom->J, &points[q*dim], x); 11095f80ce2aSJacob Faibussowitsch CHKERRQ((*func)(dE, time, x, Nc, val, ctx)); 111020cf1dd8SToby Isaac } else { 11115f80ce2aSJacob Faibussowitsch CHKERRQ((*func)(dE, time, &cgeom->v[dE*q], Nc, val, ctx)); 111220cf1dd8SToby Isaac } 111320cf1dd8SToby Isaac for (c = 0; c < Nc; ++c) { 111420cf1dd8SToby Isaac *value += val[c]*weights[q*Nc+c]; 111520cf1dd8SToby Isaac } 111620cf1dd8SToby Isaac } 11175f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 111820cf1dd8SToby Isaac PetscFunctionReturn(0); 111920cf1dd8SToby Isaac } 112020cf1dd8SToby Isaac 112120cf1dd8SToby Isaac /*@C 1122b4457527SToby Isaac PetscDualSpaceApplyAllDefault - Apply all functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetAllData() 112320cf1dd8SToby Isaac 112420cf1dd8SToby Isaac Input Parameters: 112520cf1dd8SToby Isaac + sp - The PetscDualSpace object 1126b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetAllData() 112720cf1dd8SToby Isaac 112820cf1dd8SToby Isaac Output Parameter: 112920cf1dd8SToby Isaac . spValue - The values of all dual space functionals 113020cf1dd8SToby Isaac 1131a4ce7ad1SMatthew G. Knepley Level: beginner 113220cf1dd8SToby Isaac 113320cf1dd8SToby Isaac .seealso: PetscDualSpaceCreate() 113420cf1dd8SToby Isaac @*/ 113520cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceApplyAllDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 113620cf1dd8SToby Isaac { 1137b4457527SToby Isaac Vec pointValues, dofValues; 1138b4457527SToby Isaac Mat allMat; 113920cf1dd8SToby Isaac 114020cf1dd8SToby Isaac PetscFunctionBegin; 114120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 114220cf1dd8SToby Isaac PetscValidScalarPointer(pointEval, 2); 1143064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetAllData(sp, NULL, &allMat)); 1145b4457527SToby Isaac if (!(sp->allNodeValues)) { 11465f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(allMat, &(sp->allNodeValues), NULL)); 114720cf1dd8SToby Isaac } 1148b4457527SToby Isaac pointValues = sp->allNodeValues; 1149b4457527SToby Isaac if (!(sp->allDofValues)) { 11505f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(allMat, NULL, &(sp->allDofValues))); 115120cf1dd8SToby Isaac } 1152b4457527SToby Isaac dofValues = sp->allDofValues; 11535f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pointValues, pointEval)); 11545f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(dofValues, spValue)); 11555f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(allMat, pointValues, dofValues)); 11565f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(dofValues)); 11575f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pointValues)); 1158b4457527SToby Isaac PetscFunctionReturn(0); 115920cf1dd8SToby Isaac } 1160b4457527SToby Isaac 1161b4457527SToby Isaac /*@C 1162b4457527SToby Isaac PetscDualSpaceApplyInteriorDefault - Apply interior functionals from the dual space basis to the result of an evaluation at the points returned by PetscDualSpaceGetInteriorData() 1163b4457527SToby Isaac 1164b4457527SToby Isaac Input Parameters: 1165b4457527SToby Isaac + sp - The PetscDualSpace object 1166b4457527SToby Isaac - pointEval - Evaluation at the points returned by PetscDualSpaceGetInteriorData() 1167b4457527SToby Isaac 1168b4457527SToby Isaac Output Parameter: 1169b4457527SToby Isaac . spValue - The values of interior dual space functionals 1170b4457527SToby Isaac 1171b4457527SToby Isaac Level: beginner 1172b4457527SToby Isaac 1173b4457527SToby Isaac .seealso: PetscDualSpaceCreate() 1174b4457527SToby Isaac @*/ 1175b4457527SToby Isaac PetscErrorCode PetscDualSpaceApplyInteriorDefault(PetscDualSpace sp, const PetscScalar *pointEval, PetscScalar *spValue) 1176b4457527SToby Isaac { 1177b4457527SToby Isaac Vec pointValues, dofValues; 1178b4457527SToby Isaac Mat intMat; 1179b4457527SToby Isaac 1180b4457527SToby Isaac PetscFunctionBegin; 1181b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1182b4457527SToby Isaac PetscValidScalarPointer(pointEval, 2); 1183064a246eSJacob Faibussowitsch PetscValidScalarPointer(spValue, 3); 11845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetInteriorData(sp, NULL, &intMat)); 1185b4457527SToby Isaac if (!(sp->intNodeValues)) { 11865f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(intMat, &(sp->intNodeValues), NULL)); 1187b4457527SToby Isaac } 1188b4457527SToby Isaac pointValues = sp->intNodeValues; 1189b4457527SToby Isaac if (!(sp->intDofValues)) { 11905f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(intMat, NULL, &(sp->intDofValues))); 1191b4457527SToby Isaac } 1192b4457527SToby Isaac dofValues = sp->intDofValues; 11935f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(pointValues, pointEval)); 11945f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(dofValues, spValue)); 11955f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(intMat, pointValues, dofValues)); 11965f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(dofValues)); 11975f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(pointValues)); 119820cf1dd8SToby Isaac PetscFunctionReturn(0); 119920cf1dd8SToby Isaac } 120020cf1dd8SToby Isaac 1201a4ce7ad1SMatthew G. Knepley /*@ 1202b4457527SToby Isaac PetscDualSpaceGetAllData - Get all quadrature nodes from this space, and the matrix that sends quadrature node values to degree-of-freedom values 1203a4ce7ad1SMatthew G. Knepley 1204a4ce7ad1SMatthew G. Knepley Input Parameter: 1205a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1206a4ce7ad1SMatthew G. Knepley 1207d8d19677SJose E. Roman Output Parameters: 1208b4457527SToby Isaac + allNodes - A PetscQuadrature object containing all evaluation nodes 1209b4457527SToby Isaac - allMat - A Mat for the node-to-dof transformation 1210a4ce7ad1SMatthew G. Knepley 1211a4ce7ad1SMatthew G. Knepley Level: advanced 1212a4ce7ad1SMatthew G. Knepley 1213a4ce7ad1SMatthew G. Knepley .seealso: PetscDualSpaceCreate() 1214a4ce7ad1SMatthew G. Knepley @*/ 1215b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetAllData(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 121620cf1dd8SToby Isaac { 121720cf1dd8SToby Isaac PetscFunctionBegin; 121820cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1219b4457527SToby Isaac if (allNodes) PetscValidPointer(allNodes,2); 1220b4457527SToby Isaac if (allMat) PetscValidPointer(allMat,3); 1221b4457527SToby Isaac if ((!sp->allNodes || !sp->allMat) && sp->ops->createalldata) { 1222b4457527SToby Isaac PetscQuadrature qpoints; 1223b4457527SToby Isaac Mat amat; 1224b4457527SToby Isaac 12255f80ce2aSJacob Faibussowitsch CHKERRQ((*sp->ops->createalldata)(sp,&qpoints,&amat)); 12265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureDestroy(&(sp->allNodes))); 12275f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&(sp->allMat))); 1228b4457527SToby Isaac sp->allNodes = qpoints; 1229b4457527SToby Isaac sp->allMat = amat; 123020cf1dd8SToby Isaac } 1231b4457527SToby Isaac if (allNodes) *allNodes = sp->allNodes; 1232b4457527SToby Isaac if (allMat) *allMat = sp->allMat; 123320cf1dd8SToby Isaac PetscFunctionReturn(0); 123420cf1dd8SToby Isaac } 123520cf1dd8SToby Isaac 1236a4ce7ad1SMatthew G. Knepley /*@ 1237b4457527SToby Isaac PetscDualSpaceCreateAllDataDefault - Create all evaluation nodes and the node-to-dof matrix by examining functionals 1238a4ce7ad1SMatthew G. Knepley 1239a4ce7ad1SMatthew G. Knepley Input Parameter: 1240a4ce7ad1SMatthew G. Knepley . sp - The dualspace 1241a4ce7ad1SMatthew G. Knepley 1242d8d19677SJose E. Roman Output Parameters: 1243b4457527SToby Isaac + allNodes - A PetscQuadrature object containing all evaluation nodes 1244b4457527SToby Isaac - allMat - A Mat for the node-to-dof transformation 1245a4ce7ad1SMatthew G. Knepley 1246a4ce7ad1SMatthew G. Knepley Level: advanced 1247a4ce7ad1SMatthew G. Knepley 1248a4ce7ad1SMatthew G. Knepley .seealso: PetscDualSpaceCreate() 1249a4ce7ad1SMatthew G. Knepley @*/ 1250b4457527SToby Isaac PetscErrorCode PetscDualSpaceCreateAllDataDefault(PetscDualSpace sp, PetscQuadrature *allNodes, Mat *allMat) 125120cf1dd8SToby Isaac { 125220cf1dd8SToby Isaac PetscInt spdim; 125320cf1dd8SToby Isaac PetscInt numPoints, offset; 125420cf1dd8SToby Isaac PetscReal *points; 125520cf1dd8SToby Isaac PetscInt f, dim; 1256b4457527SToby Isaac PetscInt Nc, nrows, ncols; 1257b4457527SToby Isaac PetscInt maxNumPoints; 125820cf1dd8SToby Isaac PetscQuadrature q; 1259b4457527SToby Isaac Mat A; 126020cf1dd8SToby Isaac 126120cf1dd8SToby Isaac PetscFunctionBegin; 12625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetNumComponents(sp, &Nc)); 12635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDimension(sp,&spdim)); 126420cf1dd8SToby Isaac if (!spdim) { 12655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureCreate(PETSC_COMM_SELF,allNodes)); 12665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureSetData(*allNodes,0,0,0,NULL,NULL)); 126720cf1dd8SToby Isaac } 1268b4457527SToby Isaac nrows = spdim; 12695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFunctional(sp,0,&q)); 12705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureGetData(q,&dim,NULL,&numPoints,NULL,NULL)); 1271b4457527SToby Isaac maxNumPoints = numPoints; 127220cf1dd8SToby Isaac for (f = 1; f < spdim; f++) { 127320cf1dd8SToby Isaac PetscInt Np; 127420cf1dd8SToby Isaac 12755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFunctional(sp,f,&q)); 12765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureGetData(q,NULL,NULL,&Np,NULL,NULL)); 127720cf1dd8SToby Isaac numPoints += Np; 1278b4457527SToby Isaac maxNumPoints = PetscMax(maxNumPoints,Np); 127920cf1dd8SToby Isaac } 1280b4457527SToby Isaac ncols = numPoints * Nc; 12815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(dim*numPoints,&points)); 12825f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqAIJ(PETSC_COMM_SELF, nrows, ncols, maxNumPoints * Nc, NULL, &A)); 128320cf1dd8SToby Isaac for (f = 0, offset = 0; f < spdim; f++) { 1284b4457527SToby Isaac const PetscReal *p, *w; 128520cf1dd8SToby Isaac PetscInt Np, i; 1286b4457527SToby Isaac PetscInt fnc; 128720cf1dd8SToby Isaac 12885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFunctional(sp,f,&q)); 12895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureGetData(q,NULL,&fnc,&Np,&p,&w)); 12902c71b3e2SJacob Faibussowitsch PetscCheckFalse(fnc != Nc,PETSC_COMM_SELF, PETSC_ERR_PLIB, "functional component mismatch"); 1291b4457527SToby Isaac for (i = 0; i < Np * dim; i++) { 1292b4457527SToby Isaac points[offset* dim + i] = p[i]; 1293b4457527SToby Isaac } 1294b4457527SToby Isaac for (i = 0; i < Np * Nc; i++) { 12955f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(A, f, offset * Nc, w[i], INSERT_VALUES)); 1296b4457527SToby Isaac } 1297b4457527SToby Isaac offset += Np; 1298b4457527SToby Isaac } 12995f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 13005f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 13015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureCreate(PETSC_COMM_SELF,allNodes)); 13025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureSetData(*allNodes,dim,0,numPoints,points,NULL)); 1303b4457527SToby Isaac *allMat = A; 1304b4457527SToby Isaac PetscFunctionReturn(0); 1305b4457527SToby Isaac } 1306b4457527SToby Isaac 1307b4457527SToby Isaac /*@ 1308b4457527SToby Isaac PetscDualSpaceGetInteriorData - Get all quadrature points necessary to compute the interior degrees of freedom from 1309b4457527SToby Isaac this space, as well as the matrix that computes the degrees of freedom from the quadrature values. Degrees of 1310b4457527SToby Isaac freedom are interior degrees of freedom if they belong (by PetscDualSpaceGetSection()) to interior points in the 1311b4457527SToby Isaac reference DMPlex: complementary boundary degrees of freedom are marked as constrained in the section returned by 1312b4457527SToby Isaac PetscDualSpaceGetSection()). 1313b4457527SToby Isaac 1314b4457527SToby Isaac Input Parameter: 1315b4457527SToby Isaac . sp - The dualspace 1316b4457527SToby Isaac 1317d8d19677SJose E. Roman Output Parameters: 1318b4457527SToby Isaac + intNodes - A PetscQuadrature object containing all evaluation points needed to evaluate interior degrees of freedom 1319b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1320b4457527SToby Isaac the size of the constrained layout (PetscSectionGetConstrainStorageSize()) of the dual space section, 1321b4457527SToby Isaac npoints is the number of points in intNodes and nc is PetscDualSpaceGetNumComponents(). 1322b4457527SToby Isaac 1323b4457527SToby Isaac Level: advanced 1324b4457527SToby Isaac 1325b4457527SToby Isaac .seealso: PetscDualSpaceCreate(), PetscDualSpaceGetDimension(), PetscDualSpaceGetNumComponents(), PetscQuadratureGetData() 1326b4457527SToby Isaac @*/ 1327b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetInteriorData(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1328b4457527SToby Isaac { 1329b4457527SToby Isaac PetscFunctionBegin; 1330b4457527SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1331b4457527SToby Isaac if (intNodes) PetscValidPointer(intNodes,2); 1332b4457527SToby Isaac if (intMat) PetscValidPointer(intMat,3); 1333b4457527SToby Isaac if ((!sp->intNodes || !sp->intMat) && sp->ops->createintdata) { 1334b4457527SToby Isaac PetscQuadrature qpoints; 1335b4457527SToby Isaac Mat imat; 1336b4457527SToby Isaac 13375f80ce2aSJacob Faibussowitsch CHKERRQ((*sp->ops->createintdata)(sp,&qpoints,&imat)); 13385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureDestroy(&(sp->intNodes))); 13395f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&(sp->intMat))); 1340b4457527SToby Isaac sp->intNodes = qpoints; 1341b4457527SToby Isaac sp->intMat = imat; 1342b4457527SToby Isaac } 1343b4457527SToby Isaac if (intNodes) *intNodes = sp->intNodes; 1344b4457527SToby Isaac if (intMat) *intMat = sp->intMat; 1345b4457527SToby Isaac PetscFunctionReturn(0); 1346b4457527SToby Isaac } 1347b4457527SToby Isaac 1348b4457527SToby Isaac /*@ 1349b4457527SToby Isaac PetscDualSpaceCreateInteriorDataDefault - Create quadrature points by examining interior functionals and create the matrix mapping quadrature point values to interior dual space values 1350b4457527SToby Isaac 1351b4457527SToby Isaac Input Parameter: 1352b4457527SToby Isaac . sp - The dualspace 1353b4457527SToby Isaac 1354d8d19677SJose E. Roman Output Parameters: 1355b4457527SToby Isaac + intNodes - A PetscQuadrature object containing all evaluation points needed to evaluate interior degrees of freedom 1356b4457527SToby Isaac - intMat - A matrix that computes dual space values from point values: size [spdim0 x (npoints * nc)], where spdim0 is 1357b4457527SToby Isaac the size of the constrained layout (PetscSectionGetConstrainStorageSize()) of the dual space section, 1358b4457527SToby Isaac npoints is the number of points in allNodes and nc is PetscDualSpaceGetNumComponents(). 1359b4457527SToby Isaac 1360b4457527SToby Isaac Level: advanced 1361b4457527SToby Isaac 1362b4457527SToby Isaac .seealso: PetscDualSpaceCreate(), PetscDualSpaceGetInteriorData() 1363b4457527SToby Isaac @*/ 1364b4457527SToby Isaac PetscErrorCode PetscDualSpaceCreateInteriorDataDefault(PetscDualSpace sp, PetscQuadrature *intNodes, Mat *intMat) 1365b4457527SToby Isaac { 1366b4457527SToby Isaac DM dm; 1367b4457527SToby Isaac PetscInt spdim0; 1368b4457527SToby Isaac PetscInt Nc; 1369b4457527SToby Isaac PetscInt pStart, pEnd, p, f; 1370b4457527SToby Isaac PetscSection section; 1371b4457527SToby Isaac PetscInt numPoints, offset, matoffset; 1372b4457527SToby Isaac PetscReal *points; 1373b4457527SToby Isaac PetscInt dim; 1374b4457527SToby Isaac PetscInt *nnz; 1375b4457527SToby Isaac PetscQuadrature q; 1376b4457527SToby Isaac Mat imat; 1377b4457527SToby Isaac 1378b4457527SToby Isaac PetscFunctionBegin; 1379b4457527SToby Isaac PetscValidHeaderSpecific(sp,PETSCDUALSPACE_CLASSID,1); 13805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetSection(sp, §ion)); 13815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstrainedStorageSize(section, &spdim0)); 1382b4457527SToby Isaac if (!spdim0) { 1383b4457527SToby Isaac *intNodes = NULL; 1384b4457527SToby Isaac *intMat = NULL; 1385b4457527SToby Isaac PetscFunctionReturn(0); 1386b4457527SToby Isaac } 13875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetNumComponents(sp, &Nc)); 13885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(section, &pStart, &pEnd)); 13895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDM(sp, &dm)); 13905f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 13915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(spdim0, &nnz)); 1392b4457527SToby Isaac for (p = pStart, f = 0, numPoints = 0; p < pEnd; p++) { 1393b4457527SToby Isaac PetscInt dof, cdof, off, d; 1394b4457527SToby Isaac 13955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, p, &dof)); 13965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(section, p, &cdof)); 1397b4457527SToby Isaac if (!(dof - cdof)) continue; 13985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, p, &off)); 1399b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1400b4457527SToby Isaac PetscInt Np; 1401b4457527SToby Isaac 14025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFunctional(sp,off,&q)); 14035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureGetData(q,NULL,NULL,&Np,NULL,NULL)); 1404b4457527SToby Isaac nnz[f] = Np * Nc; 1405b4457527SToby Isaac numPoints += Np; 1406b4457527SToby Isaac } 1407b4457527SToby Isaac } 14085f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqAIJ(PETSC_COMM_SELF, spdim0, numPoints * Nc, 0, nnz, &imat)); 14095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(nnz)); 14105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(dim*numPoints,&points)); 1411b4457527SToby Isaac for (p = pStart, f = 0, offset = 0, matoffset = 0; p < pEnd; p++) { 1412b4457527SToby Isaac PetscInt dof, cdof, off, d; 1413b4457527SToby Isaac 14145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, p, &dof)); 14155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetConstraintDof(section, p, &cdof)); 1416b4457527SToby Isaac if (!(dof - cdof)) continue; 14175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, p, &off)); 1418b4457527SToby Isaac for (d = 0; d < dof; d++, off++, f++) { 1419b4457527SToby Isaac const PetscReal *p; 1420b4457527SToby Isaac const PetscReal *w; 1421b4457527SToby Isaac PetscInt Np, i; 1422b4457527SToby Isaac 14235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFunctional(sp,off,&q)); 14245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureGetData(q,NULL,NULL,&Np,&p,&w)); 142520cf1dd8SToby Isaac for (i = 0; i < Np * dim; i++) { 142620cf1dd8SToby Isaac points[offset + i] = p[i]; 142720cf1dd8SToby Isaac } 1428b4457527SToby Isaac for (i = 0; i < Np * Nc; i++) { 14295f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValue(imat, f, matoffset + i, w[i],INSERT_VALUES)); 143020cf1dd8SToby Isaac } 1431b4457527SToby Isaac offset += Np * dim; 1432b4457527SToby Isaac matoffset += Np * Nc; 1433b4457527SToby Isaac } 1434b4457527SToby Isaac } 14355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureCreate(PETSC_COMM_SELF,intNodes)); 14365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureSetData(*intNodes,dim,0,numPoints,points,NULL)); 14375f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(imat, MAT_FINAL_ASSEMBLY)); 14385f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(imat, MAT_FINAL_ASSEMBLY)); 1439b4457527SToby Isaac *intMat = imat; 144020cf1dd8SToby Isaac PetscFunctionReturn(0); 144120cf1dd8SToby Isaac } 144220cf1dd8SToby Isaac 14434f9ab2b4SJed Brown /*@ 14444f9ab2b4SJed Brown PetscDualSpaceEqual - Determine if a dual space is equivalent 14454f9ab2b4SJed Brown 14464f9ab2b4SJed Brown Input Parameters: 14474f9ab2b4SJed Brown + A - A PetscDualSpace object 14484f9ab2b4SJed Brown - B - Another PetscDualSpace object 14494f9ab2b4SJed Brown 14504f9ab2b4SJed Brown Output Parameter: 14514f9ab2b4SJed Brown . equal - PETSC_TRUE if the dual spaces are equivalent 14524f9ab2b4SJed Brown 14534f9ab2b4SJed Brown Level: advanced 14544f9ab2b4SJed Brown 14554f9ab2b4SJed Brown .seealso: PetscDualSpaceCreate() 14564f9ab2b4SJed Brown @*/ 14574f9ab2b4SJed Brown PetscErrorCode PetscDualSpaceEqual(PetscDualSpace A, PetscDualSpace B, PetscBool *equal) 14584f9ab2b4SJed Brown { 14594f9ab2b4SJed Brown PetscInt sizeA, sizeB, dimA, dimB; 14604f9ab2b4SJed Brown const PetscInt *dofA, *dofB; 14614f9ab2b4SJed Brown PetscQuadrature quadA, quadB; 14624f9ab2b4SJed Brown Mat matA, matB; 14634f9ab2b4SJed Brown 14644f9ab2b4SJed Brown PetscFunctionBegin; 14654f9ab2b4SJed Brown PetscValidHeaderSpecific(A,PETSCDUALSPACE_CLASSID,1); 14664f9ab2b4SJed Brown PetscValidHeaderSpecific(B,PETSCDUALSPACE_CLASSID,2); 14674f9ab2b4SJed Brown PetscValidBoolPointer(equal,3); 14684f9ab2b4SJed Brown *equal = PETSC_FALSE; 14695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDimension(A, &sizeA)); 14705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDimension(B, &sizeB)); 14714f9ab2b4SJed Brown if (sizeB != sizeA) { 14724f9ab2b4SJed Brown PetscFunctionReturn(0); 14734f9ab2b4SJed Brown } 14745f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(A->dm, &dimA)); 14755f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(B->dm, &dimB)); 14764f9ab2b4SJed Brown if (dimA != dimB) { 14774f9ab2b4SJed Brown PetscFunctionReturn(0); 14784f9ab2b4SJed Brown } 14794f9ab2b4SJed Brown 14805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetNumDof(A, &dofA)); 14815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetNumDof(B, &dofB)); 14824f9ab2b4SJed Brown for (PetscInt d=0; d<dimA; d++) { 14834f9ab2b4SJed Brown if (dofA[d] != dofB[d]) { 14844f9ab2b4SJed Brown PetscFunctionReturn(0); 14854f9ab2b4SJed Brown } 14864f9ab2b4SJed Brown } 14874f9ab2b4SJed Brown 14885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetInteriorData(A, &quadA, &matA)); 14895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetInteriorData(B, &quadB, &matB)); 14904f9ab2b4SJed Brown if (!quadA && !quadB) { 14914f9ab2b4SJed Brown *equal = PETSC_TRUE; 14924f9ab2b4SJed Brown } else if (quadA && quadB) { 14935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureEqual(quadA, quadB, equal)); 14944f9ab2b4SJed Brown if (*equal == PETSC_FALSE) PetscFunctionReturn(0); 14954f9ab2b4SJed Brown if (!matA && !matB) PetscFunctionReturn(0); 14965f80ce2aSJacob Faibussowitsch if (matA && matB) CHKERRQ(MatEqual(matA, matB, equal)); 14974f9ab2b4SJed Brown else *equal = PETSC_FALSE; 14984f9ab2b4SJed Brown } 14994f9ab2b4SJed Brown PetscFunctionReturn(0); 15004f9ab2b4SJed Brown } 15014f9ab2b4SJed Brown 150220cf1dd8SToby Isaac /*@C 150320cf1dd8SToby Isaac PetscDualSpaceApplyFVM - Apply a functional from the dual space basis to an input function by assuming a point evaluation functional at the cell centroid. 150420cf1dd8SToby Isaac 150520cf1dd8SToby Isaac Input Parameters: 150620cf1dd8SToby Isaac + sp - The PetscDualSpace object 150720cf1dd8SToby Isaac . f - The basis functional index 150820cf1dd8SToby Isaac . time - The time 150920cf1dd8SToby Isaac . cgeom - A context with geometric information for this cell, we currently just use the centroid 151020cf1dd8SToby Isaac . Nc - The number of components for the function 151120cf1dd8SToby Isaac . func - The input function 151220cf1dd8SToby Isaac - ctx - A context for the function 151320cf1dd8SToby Isaac 151420cf1dd8SToby Isaac Output Parameter: 151520cf1dd8SToby Isaac . value - The output value (scalar) 151620cf1dd8SToby Isaac 151720cf1dd8SToby Isaac Note: The calling sequence for the callback func is given by: 151820cf1dd8SToby Isaac 151920cf1dd8SToby Isaac $ func(PetscInt dim, PetscReal time, const PetscReal x[], 152020cf1dd8SToby Isaac $ PetscInt numComponents, PetscScalar values[], void *ctx) 152120cf1dd8SToby Isaac 152220cf1dd8SToby Isaac and the idea is to evaluate the functional as an integral 152320cf1dd8SToby Isaac 152420cf1dd8SToby Isaac $ n(f) = int dx n(x) . f(x) 152520cf1dd8SToby Isaac 152620cf1dd8SToby Isaac where both n and f have Nc components. 152720cf1dd8SToby Isaac 1528a4ce7ad1SMatthew G. Knepley Level: beginner 152920cf1dd8SToby Isaac 153020cf1dd8SToby Isaac .seealso: PetscDualSpaceCreate() 153120cf1dd8SToby Isaac @*/ 153220cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceApplyFVM(PetscDualSpace sp, PetscInt f, PetscReal time, PetscFVCellGeom *cgeom, PetscInt Nc, PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void *ctx, PetscScalar *value) 153320cf1dd8SToby Isaac { 153420cf1dd8SToby Isaac DM dm; 153520cf1dd8SToby Isaac PetscQuadrature n; 153620cf1dd8SToby Isaac const PetscReal *points, *weights; 153720cf1dd8SToby Isaac PetscScalar *val; 153820cf1dd8SToby Isaac PetscInt dimEmbed, qNc, c, Nq, q; 153920cf1dd8SToby Isaac 154020cf1dd8SToby Isaac PetscFunctionBegin; 154120cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1542064a246eSJacob Faibussowitsch PetscValidPointer(value, 8); 15435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDM(sp, &dm)); 15445f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &dimEmbed)); 15455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetFunctional(sp, f, &n)); 15465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscQuadratureGetData(n, NULL, &qNc, &Nq, &points, &weights)); 15472c71b3e2SJacob Faibussowitsch PetscCheckFalse(qNc != Nc,PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_SIZ, "The quadrature components %D != function components %D", qNc, Nc); 15485f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetWorkArray(dm, Nc, MPIU_SCALAR, &val)); 154920cf1dd8SToby Isaac *value = 0.; 155020cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 15515f80ce2aSJacob Faibussowitsch CHKERRQ((*func)(dimEmbed, time, cgeom->centroid, Nc, val, ctx)); 155220cf1dd8SToby Isaac for (c = 0; c < Nc; ++c) { 155320cf1dd8SToby Isaac *value += val[c]*weights[q*Nc+c]; 155420cf1dd8SToby Isaac } 155520cf1dd8SToby Isaac } 15565f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreWorkArray(dm, Nc, MPIU_SCALAR, &val)); 155720cf1dd8SToby Isaac PetscFunctionReturn(0); 155820cf1dd8SToby Isaac } 155920cf1dd8SToby Isaac 156020cf1dd8SToby Isaac /*@ 156120cf1dd8SToby Isaac PetscDualSpaceGetHeightSubspace - Get the subset of the dual space basis that is supported on a mesh point of a 156220cf1dd8SToby Isaac given height. This assumes that the reference cell is symmetric over points of this height. 156320cf1dd8SToby Isaac 156420cf1dd8SToby Isaac If the dual space is not defined on mesh points of the given height (e.g. if the space is discontinuous and 156520cf1dd8SToby Isaac pointwise values are not defined on the element boundaries), or if the implementation of PetscDualSpace does not 156620cf1dd8SToby Isaac support extracting subspaces, then NULL is returned. 156720cf1dd8SToby Isaac 156820cf1dd8SToby Isaac This does not increment the reference count on the returned dual space, and the user should not destroy it. 156920cf1dd8SToby Isaac 157020cf1dd8SToby Isaac Not collective 157120cf1dd8SToby Isaac 157220cf1dd8SToby Isaac Input Parameters: 157320cf1dd8SToby Isaac + sp - the PetscDualSpace object 157420cf1dd8SToby Isaac - height - the height of the mesh point for which the subspace is desired 157520cf1dd8SToby Isaac 157620cf1dd8SToby Isaac Output Parameter: 157720cf1dd8SToby Isaac . subsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 157820cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 157920cf1dd8SToby Isaac 158020cf1dd8SToby Isaac Level: advanced 158120cf1dd8SToby Isaac 158220cf1dd8SToby Isaac .seealso: PetscSpaceGetHeightSubspace(), PetscDualSpace 158320cf1dd8SToby Isaac @*/ 158420cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetHeightSubspace(PetscDualSpace sp, PetscInt height, PetscDualSpace *subsp) 158520cf1dd8SToby Isaac { 1586b4457527SToby Isaac PetscInt depth = -1, cStart, cEnd; 1587b4457527SToby Isaac DM dm; 158820cf1dd8SToby Isaac 158920cf1dd8SToby Isaac PetscFunctionBegin; 159020cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1591064a246eSJacob Faibussowitsch PetscValidPointer(subsp,3); 15922c71b3e2SJacob Faibussowitsch PetscCheckFalse(!(sp->uniform),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "A non-uniform dual space does not have a single dual space at each height"); 159320cf1dd8SToby Isaac *subsp = NULL; 1594b4457527SToby Isaac dm = sp->dm; 15955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 15962c71b3e2SJacob Faibussowitsch PetscCheckFalse(height < 0 || height > depth,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid height"); 15975f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm,0,&cStart,&cEnd)); 1598b4457527SToby Isaac if (height == 0 && cEnd == cStart + 1) { 1599b4457527SToby Isaac *subsp = sp; 1600b4457527SToby Isaac PetscFunctionReturn(0); 1601b4457527SToby Isaac } 1602b4457527SToby Isaac if (!sp->heightSpaces) { 1603b4457527SToby Isaac PetscInt h; 16045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(depth+1, &(sp->heightSpaces))); 1605b4457527SToby Isaac 1606b4457527SToby Isaac for (h = 0; h <= depth; h++) { 1607b4457527SToby Isaac if (h == 0 && cEnd == cStart + 1) continue; 16085f80ce2aSJacob Faibussowitsch if (sp->ops->createheightsubspace) CHKERRQ((*sp->ops->createheightsubspace)(sp,height,&(sp->heightSpaces[h]))); 1609b4457527SToby Isaac else if (sp->pointSpaces) { 1610b4457527SToby Isaac PetscInt hStart, hEnd; 1611b4457527SToby Isaac 16125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm,h,&hStart,&hEnd)); 1613b4457527SToby Isaac if (hEnd > hStart) { 1614665f567fSMatthew G. Knepley const char *name; 1615665f567fSMatthew G. Knepley 16165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)(sp->pointSpaces[hStart]))); 1617665f567fSMatthew G. Knepley if (sp->pointSpaces[hStart]) { 16185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) sp, &name)); 16195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) sp->pointSpaces[hStart], name)); 1620665f567fSMatthew G. Knepley } 1621b4457527SToby Isaac sp->heightSpaces[h] = sp->pointSpaces[hStart]; 1622b4457527SToby Isaac } 1623b4457527SToby Isaac } 1624b4457527SToby Isaac } 1625b4457527SToby Isaac } 1626b4457527SToby Isaac *subsp = sp->heightSpaces[height]; 162720cf1dd8SToby Isaac PetscFunctionReturn(0); 162820cf1dd8SToby Isaac } 162920cf1dd8SToby Isaac 163020cf1dd8SToby Isaac /*@ 163120cf1dd8SToby Isaac PetscDualSpaceGetPointSubspace - Get the subset of the dual space basis that is supported on a particular mesh point. 163220cf1dd8SToby Isaac 163320cf1dd8SToby Isaac If the dual space is not defined on the mesh point (e.g. if the space is discontinuous and pointwise values are not 163420cf1dd8SToby Isaac defined on the element boundaries), or if the implementation of PetscDualSpace does not support extracting 163520cf1dd8SToby Isaac subspaces, then NULL is returned. 163620cf1dd8SToby Isaac 163720cf1dd8SToby Isaac This does not increment the reference count on the returned dual space, and the user should not destroy it. 163820cf1dd8SToby Isaac 163920cf1dd8SToby Isaac Not collective 164020cf1dd8SToby Isaac 164120cf1dd8SToby Isaac Input Parameters: 164220cf1dd8SToby Isaac + sp - the PetscDualSpace object 164320cf1dd8SToby Isaac - point - the point (in the dual space's DM) for which the subspace is desired 164420cf1dd8SToby Isaac 164520cf1dd8SToby Isaac Output Parameters: 164620cf1dd8SToby Isaac bdsp - the subspace. Note that the functionals in the subspace are with respect to the intrinsic geometry of the 164720cf1dd8SToby Isaac point, which will be of lesser dimension if height > 0. 164820cf1dd8SToby Isaac 164920cf1dd8SToby Isaac Level: advanced 165020cf1dd8SToby Isaac 165120cf1dd8SToby Isaac .seealso: PetscDualSpace 165220cf1dd8SToby Isaac @*/ 165320cf1dd8SToby Isaac PetscErrorCode PetscDualSpaceGetPointSubspace(PetscDualSpace sp, PetscInt point, PetscDualSpace *bdsp) 165420cf1dd8SToby Isaac { 1655b4457527SToby Isaac PetscInt pStart = 0, pEnd = 0, cStart, cEnd; 1656b4457527SToby Isaac DM dm; 165720cf1dd8SToby Isaac 165820cf1dd8SToby Isaac PetscFunctionBegin; 165920cf1dd8SToby Isaac PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 1660064a246eSJacob Faibussowitsch PetscValidPointer(bdsp,3); 166120cf1dd8SToby Isaac *bdsp = NULL; 1662b4457527SToby Isaac dm = sp->dm; 16635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 16642c71b3e2SJacob Faibussowitsch PetscCheckFalse(point < pStart || point > pEnd,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid point"); 16655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetHeightStratum(dm,0,&cStart,&cEnd)); 1666b4457527SToby Isaac if (point == cStart && cEnd == cStart + 1) { /* the dual space is only equivalent to the dual space on a cell if the reference mesh has just one cell */ 1667b4457527SToby Isaac *bdsp = sp; 1668b4457527SToby Isaac PetscFunctionReturn(0); 1669b4457527SToby Isaac } 1670b4457527SToby Isaac if (!sp->pointSpaces) { 1671b4457527SToby Isaac PetscInt p; 16725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(pEnd - pStart, &(sp->pointSpaces))); 167320cf1dd8SToby Isaac 1674b4457527SToby Isaac for (p = 0; p < pEnd - pStart; p++) { 1675b4457527SToby Isaac if (p + pStart == cStart && cEnd == cStart + 1) continue; 16765f80ce2aSJacob Faibussowitsch if (sp->ops->createpointsubspace) CHKERRQ((*sp->ops->createpointsubspace)(sp,p+pStart,&(sp->pointSpaces[p]))); 1677b4457527SToby Isaac else if (sp->heightSpaces || sp->ops->createheightsubspace) { 1678b4457527SToby Isaac PetscInt dim, depth, height; 1679b4457527SToby Isaac DMLabel label; 1680b4457527SToby Isaac 16815f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm,&dim)); 16825f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthLabel(dm,&label)); 16835f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetValue(label,p+pStart,&depth)); 168420cf1dd8SToby Isaac height = dim - depth; 16855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetHeightSubspace(sp, height, &(sp->pointSpaces[p]))); 16865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)sp->pointSpaces[p])); 168720cf1dd8SToby Isaac } 1688b4457527SToby Isaac } 1689b4457527SToby Isaac } 1690b4457527SToby Isaac *bdsp = sp->pointSpaces[point - pStart]; 169120cf1dd8SToby Isaac PetscFunctionReturn(0); 169220cf1dd8SToby Isaac } 169320cf1dd8SToby Isaac 16946f905325SMatthew G. Knepley /*@C 16956f905325SMatthew G. Knepley PetscDualSpaceGetSymmetries - Returns a description of the symmetries of this basis 16966f905325SMatthew G. Knepley 16976f905325SMatthew G. Knepley Not collective 16986f905325SMatthew G. Knepley 16996f905325SMatthew G. Knepley Input Parameter: 17006f905325SMatthew G. Knepley . sp - the PetscDualSpace object 17016f905325SMatthew G. Knepley 17026f905325SMatthew G. Knepley Output Parameters: 1703b4457527SToby Isaac + perms - Permutations of the interior degrees of freedom, parameterized by the point orientation 1704b4457527SToby Isaac - flips - Sign reversal of the interior degrees of freedom, parameterized by the point orientation 17056f905325SMatthew G. Knepley 17066f905325SMatthew G. Knepley Note: The permutation and flip arrays are organized in the following way 17076f905325SMatthew G. Knepley $ perms[p][ornt][dof # on point] = new local dof # 17086f905325SMatthew G. Knepley $ flips[p][ornt][dof # on point] = reversal or not 17096f905325SMatthew G. Knepley 17106f905325SMatthew G. Knepley Level: developer 17116f905325SMatthew G. Knepley 17126f905325SMatthew G. Knepley @*/ 17136f905325SMatthew G. Knepley PetscErrorCode PetscDualSpaceGetSymmetries(PetscDualSpace sp, const PetscInt ****perms, const PetscScalar ****flips) 17146f905325SMatthew G. Knepley { 17156f905325SMatthew G. Knepley PetscFunctionBegin; 17166f905325SMatthew G. Knepley PetscValidHeaderSpecific(sp,PETSCDUALSPACE_CLASSID,1); 17176f905325SMatthew G. Knepley if (perms) {PetscValidPointer(perms,2); *perms = NULL;} 17186f905325SMatthew G. Knepley if (flips) {PetscValidPointer(flips,3); *flips = NULL;} 17195f80ce2aSJacob Faibussowitsch if (sp->ops->getsymmetries) CHKERRQ((sp->ops->getsymmetries)(sp,perms,flips)); 17206f905325SMatthew G. Knepley PetscFunctionReturn(0); 17216f905325SMatthew G. Knepley } 17224bee2e38SMatthew G. Knepley 17234bee2e38SMatthew G. Knepley /*@ 1724b4457527SToby Isaac PetscDualSpaceGetFormDegree - Get the form degree k for the k-form the describes the pushforwards/pullbacks of this 1725b4457527SToby Isaac dual space's functionals. 1726b4457527SToby Isaac 1727b4457527SToby Isaac Input Parameter: 1728b4457527SToby Isaac . dsp - The PetscDualSpace 1729b4457527SToby Isaac 1730b4457527SToby Isaac Output Parameter: 1731b4457527SToby Isaac . k - The *signed* degree k of the k. If k >= 0, this means that the degrees of freedom are k-forms, and are stored 1732b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1733b4457527SToby Isaac the 1-form basis in 3-D is (dx, dy, dz), and the 2-form basis in 3-D is (dx wedge dy, dx wedge dz, dy wedge dz). 1734b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1735b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1736b4457527SToby Isaac but are stored as 1-forms. 1737b4457527SToby Isaac 1738b4457527SToby Isaac Level: developer 1739b4457527SToby Isaac 1740b4457527SToby Isaac .seealso: PetscDTAltV, PetscDualSpacePullback(), PetscDualSpacePushforward(), PetscDualSpaceTransform(), PetscDualSpaceTransformType 1741b4457527SToby Isaac @*/ 1742b4457527SToby Isaac PetscErrorCode PetscDualSpaceGetFormDegree(PetscDualSpace dsp, PetscInt *k) 1743b4457527SToby Isaac { 1744b4457527SToby Isaac PetscFunctionBeginHot; 1745b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1746b4457527SToby Isaac PetscValidPointer(k, 2); 1747b4457527SToby Isaac *k = dsp->k; 1748b4457527SToby Isaac PetscFunctionReturn(0); 1749b4457527SToby Isaac } 1750b4457527SToby Isaac 1751b4457527SToby Isaac /*@ 1752b4457527SToby Isaac PetscDualSpaceSetFormDegree - Set the form degree k for the k-form the describes the pushforwards/pullbacks of this 1753b4457527SToby Isaac dual space's functionals. 1754b4457527SToby Isaac 1755d8d19677SJose E. Roman Input Parameters: 1756b4457527SToby Isaac + dsp - The PetscDualSpace 1757b4457527SToby Isaac - k - The *signed* degree k of the k. If k >= 0, this means that the degrees of freedom are k-forms, and are stored 1758b4457527SToby Isaac in lexicographic order according to the basis of k-forms constructed from the wedge product of 1-forms. So for example, 1759b4457527SToby Isaac the 1-form basis in 3-D is (dx, dy, dz), and the 2-form basis in 3-D is (dx wedge dy, dx wedge dz, dy wedge dz). 1760b4457527SToby Isaac If k < 0, this means that the degrees transform as k-forms, but are stored as (N-k) forms according to the 1761b4457527SToby Isaac Hodge star map. So for example if k = -2 and N = 3, this means that the degrees of freedom transform as 2-forms 1762b4457527SToby Isaac but are stored as 1-forms. 1763b4457527SToby Isaac 1764b4457527SToby Isaac Level: developer 1765b4457527SToby Isaac 1766b4457527SToby Isaac .seealso: PetscDTAltV, PetscDualSpacePullback(), PetscDualSpacePushforward(), PetscDualSpaceTransform(), PetscDualSpaceTransformType 1767b4457527SToby Isaac @*/ 1768b4457527SToby Isaac PetscErrorCode PetscDualSpaceSetFormDegree(PetscDualSpace dsp, PetscInt k) 1769b4457527SToby Isaac { 1770b4457527SToby Isaac PetscInt dim; 1771b4457527SToby Isaac 1772b4457527SToby Isaac PetscFunctionBeginHot; 1773b4457527SToby Isaac PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 1774*28b400f6SJacob Faibussowitsch PetscCheck(!dsp->setupcalled,PetscObjectComm((PetscObject)dsp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of components after dualspace is set up"); 1775b4457527SToby Isaac dim = dsp->dm->dim; 17762c71b3e2SJacob Faibussowitsch PetscCheckFalse(k < -dim || k > dim,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unsupported %D-form on %D-dimensional reference cell", PetscAbsInt(k), dim); 1777b4457527SToby Isaac dsp->k = k; 1778b4457527SToby Isaac PetscFunctionReturn(0); 1779b4457527SToby Isaac } 1780b4457527SToby Isaac 1781b4457527SToby Isaac /*@ 17824bee2e38SMatthew G. Knepley PetscDualSpaceGetDeRahm - Get the k-simplex associated with the functionals in this dual space 17834bee2e38SMatthew G. Knepley 17844bee2e38SMatthew G. Knepley Input Parameter: 17854bee2e38SMatthew G. Knepley . dsp - The PetscDualSpace 17864bee2e38SMatthew G. Knepley 17874bee2e38SMatthew G. Knepley Output Parameter: 17884bee2e38SMatthew G. Knepley . k - The simplex dimension 17894bee2e38SMatthew G. Knepley 1790a4ce7ad1SMatthew G. Knepley Level: developer 17914bee2e38SMatthew G. Knepley 17924bee2e38SMatthew G. Knepley Note: Currently supported values are 17934bee2e38SMatthew G. Knepley $ 0: These are H_1 methods that only transform coordinates 17944bee2e38SMatthew G. Knepley $ 1: These are Hcurl methods that transform functions using the covariant Piola transform (COVARIANT_PIOLA_TRANSFORM) 17954bee2e38SMatthew G. Knepley $ 2: These are the same as 1 17964bee2e38SMatthew G. Knepley $ 3: These are Hdiv methods that transform functions using the contravariant Piola transform (CONTRAVARIANT_PIOLA_TRANSFORM) 17974bee2e38SMatthew G. Knepley 17984bee2e38SMatthew G. Knepley .seealso: PetscDualSpacePullback(), PetscDualSpacePushforward(), PetscDualSpaceTransform(), PetscDualSpaceTransformType 17994bee2e38SMatthew G. Knepley @*/ 18004bee2e38SMatthew G. Knepley PetscErrorCode PetscDualSpaceGetDeRahm(PetscDualSpace dsp, PetscInt *k) 18014bee2e38SMatthew G. Knepley { 1802b4457527SToby Isaac PetscInt dim; 1803b4457527SToby Isaac 18044bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18054bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18064bee2e38SMatthew G. Knepley PetscValidPointer(k, 2); 1807b4457527SToby Isaac dim = dsp->dm->dim; 1808b4457527SToby Isaac if (!dsp->k) *k = IDENTITY_TRANSFORM; 1809b4457527SToby Isaac else if (dsp->k == 1) *k = COVARIANT_PIOLA_TRANSFORM; 1810b4457527SToby Isaac else if (dsp->k == -(dim - 1)) *k = CONTRAVARIANT_PIOLA_TRANSFORM; 1811b4457527SToby Isaac else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unsupported transformation"); 18124bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 18134bee2e38SMatthew G. Knepley } 18144bee2e38SMatthew G. Knepley 18154bee2e38SMatthew G. Knepley /*@C 18164bee2e38SMatthew G. Knepley PetscDualSpaceTransform - Transform the function values 18174bee2e38SMatthew G. Knepley 18184bee2e38SMatthew G. Knepley Input Parameters: 18194bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 18204bee2e38SMatthew G. Knepley . trans - The type of transform 18214bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18224bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18234bee2e38SMatthew G. Knepley . Nv - The number of function samples 18244bee2e38SMatthew G. Knepley . Nc - The number of function components 18254bee2e38SMatthew G. Knepley - vals - The function values 18264bee2e38SMatthew G. Knepley 18274bee2e38SMatthew G. Knepley Output Parameter: 18284bee2e38SMatthew G. Knepley . vals - The transformed function values 18294bee2e38SMatthew G. Knepley 1830a4ce7ad1SMatthew G. Knepley Level: intermediate 18314bee2e38SMatthew G. Knepley 1832f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18332edcad52SToby Isaac 1834f9244615SMatthew G. Knepley .seealso: PetscDualSpaceTransformGradient(), PetscDualSpaceTransformHessian(), PetscDualSpacePullback(), PetscDualSpacePushforward(), PetscDualSpaceTransformType 18354bee2e38SMatthew G. Knepley @*/ 18364bee2e38SMatthew G. Knepley PetscErrorCode PetscDualSpaceTransform(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 18374bee2e38SMatthew G. Knepley { 1838b4457527SToby Isaac PetscReal Jstar[9] = {0}; 1839b4457527SToby Isaac PetscInt dim, v, c, Nk; 18404bee2e38SMatthew G. Knepley 18414bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18424bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18434bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 18444bee2e38SMatthew G. Knepley PetscValidPointer(vals, 7); 1845b4457527SToby Isaac /* TODO: not handling dimEmbed != dim right now */ 18462ae266adSMatthew G. Knepley dim = dsp->dm->dim; 1847b4457527SToby Isaac /* No change needed for 0-forms */ 1848b4457527SToby Isaac if (!dsp->k) PetscFunctionReturn(0); 18495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDTBinomialInt(dim, PetscAbsInt(dsp->k), &Nk)); 1850b4457527SToby Isaac /* TODO: use fegeom->isAffine */ 18515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDTAltVPullbackMatrix(dim, dim, isInverse ? fegeom->J : fegeom->invJ, dsp->k, Jstar)); 18524bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1853b4457527SToby Isaac switch (Nk) { 1854b4457527SToby Isaac case 1: 1855b4457527SToby Isaac for (c = 0; c < Nc; c++) vals[v*Nc + c] *= Jstar[0]; 18564bee2e38SMatthew G. Knepley break; 1857b4457527SToby Isaac case 2: 1858b4457527SToby Isaac for (c = 0; c < Nc; c += 2) DMPlex_Mult2DReal_Internal(Jstar, 1, &vals[v*Nc + c], &vals[v*Nc + c]); 18594bee2e38SMatthew G. Knepley break; 1860b4457527SToby Isaac case 3: 1861b4457527SToby Isaac for (c = 0; c < Nc; c += 3) DMPlex_Mult3DReal_Internal(Jstar, 1, &vals[v*Nc + c], &vals[v*Nc + c]); 1862b4457527SToby Isaac break; 186398921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported form size %D for transformation", Nk); 1864b4457527SToby Isaac } 18654bee2e38SMatthew G. Knepley } 18664bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 18674bee2e38SMatthew G. Knepley } 1868b4457527SToby Isaac 18694bee2e38SMatthew G. Knepley /*@C 18704bee2e38SMatthew G. Knepley PetscDualSpaceTransformGradient - Transform the function gradient values 18714bee2e38SMatthew G. Knepley 18724bee2e38SMatthew G. Knepley Input Parameters: 18734bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 18744bee2e38SMatthew G. Knepley . trans - The type of transform 18754bee2e38SMatthew G. Knepley . isInverse - Flag to invert the transform 18764bee2e38SMatthew G. Knepley . fegeom - The cell geometry 18774bee2e38SMatthew G. Knepley . Nv - The number of function gradient samples 18784bee2e38SMatthew G. Knepley . Nc - The number of function components 18794bee2e38SMatthew G. Knepley - vals - The function gradient values 18804bee2e38SMatthew G. Knepley 18814bee2e38SMatthew G. Knepley Output Parameter: 1882f9244615SMatthew G. Knepley . vals - The transformed function gradient values 18834bee2e38SMatthew G. Knepley 1884a4ce7ad1SMatthew G. Knepley Level: intermediate 18854bee2e38SMatthew G. Knepley 1886f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 18872edcad52SToby Isaac 1888625e0966SMatthew G. Knepley .seealso: PetscDualSpaceTransform(), PetscDualSpacePullback(), PetscDualSpacePushforward(), PetscDualSpaceTransformType 18894bee2e38SMatthew G. Knepley @*/ 18904bee2e38SMatthew G. Knepley PetscErrorCode PetscDualSpaceTransformGradient(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 18914bee2e38SMatthew G. Knepley { 189227f02ce8SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 189327f02ce8SMatthew G. Knepley PetscInt v, c, d; 18944bee2e38SMatthew G. Knepley 18954bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 18964bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 18974bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 4); 18984bee2e38SMatthew G. Knepley PetscValidPointer(vals, 7); 189927f02ce8SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 19002c71b3e2SJacob Faibussowitsch PetscCheckFalse(dE <= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %D", dE); 190127f02ce8SMatthew G. Knepley #endif 19024bee2e38SMatthew G. Knepley /* Transform gradient */ 190327f02ce8SMatthew G. Knepley if (dim == dE) { 19044bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19054bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 19064bee2e38SMatthew G. Knepley switch (dim) 19074bee2e38SMatthew G. Knepley { 1908100a78e1SStefano Zampini case 1: vals[(v*Nc+c)*dim] *= fegeom->invJ[0];break; 19096142fa51SMatthew G. Knepley case 2: DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, 1, &vals[(v*Nc+c)*dim], &vals[(v*Nc+c)*dim]);break; 19106142fa51SMatthew G. Knepley case 3: DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, 1, &vals[(v*Nc+c)*dim], &vals[(v*Nc+c)*dim]);break; 191198921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %D for transformation", dim); 19124bee2e38SMatthew G. Knepley } 19134bee2e38SMatthew G. Knepley } 19144bee2e38SMatthew G. Knepley } 191527f02ce8SMatthew G. Knepley } else { 191627f02ce8SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 191727f02ce8SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 191827f02ce8SMatthew G. Knepley DMPlex_MultTransposeReal_Internal(fegeom->invJ, dim, dE, 1, &vals[(v*Nc+c)*dE], &vals[(v*Nc+c)*dE]); 191927f02ce8SMatthew G. Knepley } 192027f02ce8SMatthew G. Knepley } 192127f02ce8SMatthew G. Knepley } 19224bee2e38SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 19234bee2e38SMatthew G. Knepley if (Nc == 1 || Nc != dim) PetscFunctionReturn(0); 19244bee2e38SMatthew G. Knepley switch (trans) { 19254bee2e38SMatthew G. Knepley case IDENTITY_TRANSFORM: break; 19264bee2e38SMatthew G. Knepley case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 19274bee2e38SMatthew G. Knepley if (isInverse) { 19284bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19294bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19304bee2e38SMatthew G. Knepley switch (dim) 19314bee2e38SMatthew G. Knepley { 19326142fa51SMatthew G. Knepley case 2: DMPlex_MultTranspose2DReal_Internal(fegeom->J, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 19336142fa51SMatthew G. Knepley case 3: DMPlex_MultTranspose3DReal_Internal(fegeom->J, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 193498921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %D for transformation", dim); 19354bee2e38SMatthew G. Knepley } 19364bee2e38SMatthew G. Knepley } 19374bee2e38SMatthew G. Knepley } 19384bee2e38SMatthew G. Knepley } else { 19394bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19404bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19414bee2e38SMatthew G. Knepley switch (dim) 19424bee2e38SMatthew G. Knepley { 19436142fa51SMatthew G. Knepley case 2: DMPlex_MultTranspose2DReal_Internal(fegeom->invJ, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 19446142fa51SMatthew G. Knepley case 3: DMPlex_MultTranspose3DReal_Internal(fegeom->invJ, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 194598921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %D for transformation", dim); 19464bee2e38SMatthew G. Knepley } 19474bee2e38SMatthew G. Knepley } 19484bee2e38SMatthew G. Knepley } 19494bee2e38SMatthew G. Knepley } 19504bee2e38SMatthew G. Knepley break; 19514bee2e38SMatthew G. Knepley case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 19524bee2e38SMatthew G. Knepley if (isInverse) { 19534bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19544bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19554bee2e38SMatthew G. Knepley switch (dim) 19564bee2e38SMatthew G. Knepley { 19576142fa51SMatthew G. Knepley case 2: DMPlex_Mult2DReal_Internal(fegeom->invJ, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 19586142fa51SMatthew G. Knepley case 3: DMPlex_Mult3DReal_Internal(fegeom->invJ, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 195998921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %D for transformation", dim); 19604bee2e38SMatthew G. Knepley } 19614bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v*Nc+c)*dim+d] *= fegeom->detJ[0]; 19624bee2e38SMatthew G. Knepley } 19634bee2e38SMatthew G. Knepley } 19644bee2e38SMatthew G. Knepley } else { 19654bee2e38SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 19664bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19674bee2e38SMatthew G. Knepley switch (dim) 19684bee2e38SMatthew G. Knepley { 19696142fa51SMatthew G. Knepley case 2: DMPlex_Mult2DReal_Internal(fegeom->J, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 19706142fa51SMatthew G. Knepley case 3: DMPlex_Mult3DReal_Internal(fegeom->J, dim, &vals[v*Nc*dim+d], &vals[v*Nc*dim+d]);break; 197198921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %D for transformation", dim); 19724bee2e38SMatthew G. Knepley } 19734bee2e38SMatthew G. Knepley for (c = 0; c < Nc; ++c) vals[(v*Nc+c)*dim+d] /= fegeom->detJ[0]; 19744bee2e38SMatthew G. Knepley } 19754bee2e38SMatthew G. Knepley } 19764bee2e38SMatthew G. Knepley } 19774bee2e38SMatthew G. Knepley break; 19784bee2e38SMatthew G. Knepley } 19794bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 19804bee2e38SMatthew G. Knepley } 19814bee2e38SMatthew G. Knepley 19824bee2e38SMatthew G. Knepley /*@C 1983f9244615SMatthew G. Knepley PetscDualSpaceTransformHessian - Transform the function Hessian values 1984f9244615SMatthew G. Knepley 1985f9244615SMatthew G. Knepley Input Parameters: 1986f9244615SMatthew G. Knepley + dsp - The PetscDualSpace 1987f9244615SMatthew G. Knepley . trans - The type of transform 1988f9244615SMatthew G. Knepley . isInverse - Flag to invert the transform 1989f9244615SMatthew G. Knepley . fegeom - The cell geometry 1990f9244615SMatthew G. Knepley . Nv - The number of function Hessian samples 1991f9244615SMatthew G. Knepley . Nc - The number of function components 1992f9244615SMatthew G. Knepley - vals - The function gradient values 1993f9244615SMatthew G. Knepley 1994f9244615SMatthew G. Knepley Output Parameter: 1995f9244615SMatthew G. Knepley . vals - The transformed function Hessian values 1996f9244615SMatthew G. Knepley 1997f9244615SMatthew G. Knepley Level: intermediate 1998f9244615SMatthew G. Knepley 1999f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2000f9244615SMatthew G. Knepley 2001f9244615SMatthew G. Knepley .seealso: PetscDualSpaceTransform(), PetscDualSpacePullback(), PetscDualSpacePushforward(), PetscDualSpaceTransformType 2002f9244615SMatthew G. Knepley @*/ 2003f9244615SMatthew G. Knepley PetscErrorCode PetscDualSpaceTransformHessian(PetscDualSpace dsp, PetscDualSpaceTransformType trans, PetscBool isInverse, PetscFEGeom *fegeom, PetscInt Nv, PetscInt Nc, PetscScalar vals[]) 2004f9244615SMatthew G. Knepley { 2005f9244615SMatthew G. Knepley const PetscInt dim = dsp->dm->dim, dE = fegeom->dimEmbed; 2006f9244615SMatthew G. Knepley PetscInt v, c; 2007f9244615SMatthew G. Knepley 2008f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2009f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2010f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 4); 2011f9244615SMatthew G. Knepley PetscValidPointer(vals, 7); 2012f9244615SMatthew G. Knepley #ifdef PETSC_USE_DEBUG 20132c71b3e2SJacob Faibussowitsch PetscCheckFalse(dE <= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid embedding dimension %D", dE); 2014f9244615SMatthew G. Knepley #endif 2015f9244615SMatthew G. Knepley /* Transform Hessian: J^{-T}_{ik} J^{-T}_{jl} H(f)_{kl} = J^{-T}_{ik} H(f)_{kl} J^{-1}_{lj} */ 2016f9244615SMatthew G. Knepley if (dim == dE) { 2017f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2018f9244615SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 2019f9244615SMatthew G. Knepley switch (dim) 2020f9244615SMatthew G. Knepley { 2021f9244615SMatthew G. Knepley case 1: vals[(v*Nc+c)*dim*dim] *= PetscSqr(fegeom->invJ[0]);break; 2022f9244615SMatthew G. Knepley case 2: DMPlex_PTAP2DReal_Internal(fegeom->invJ, &vals[(v*Nc+c)*dim*dim], &vals[(v*Nc+c)*dim*dim]);break; 2023f9244615SMatthew G. Knepley case 3: DMPlex_PTAP3DReal_Internal(fegeom->invJ, &vals[(v*Nc+c)*dim*dim], &vals[(v*Nc+c)*dim*dim]);break; 202498921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dim %D for transformation", dim); 2025f9244615SMatthew G. Knepley } 2026f9244615SMatthew G. Knepley } 2027f9244615SMatthew G. Knepley } 2028f9244615SMatthew G. Knepley } else { 2029f9244615SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 2030f9244615SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 2031f9244615SMatthew G. Knepley DMPlex_PTAPReal_Internal(fegeom->invJ, dim, dE, &vals[(v*Nc+c)*dE*dE], &vals[(v*Nc+c)*dE*dE]); 2032f9244615SMatthew G. Knepley } 2033f9244615SMatthew G. Knepley } 2034f9244615SMatthew G. Knepley } 2035f9244615SMatthew G. Knepley /* Assume its a vector, otherwise assume its a bunch of scalars */ 2036f9244615SMatthew G. Knepley if (Nc == 1 || Nc != dim) PetscFunctionReturn(0); 2037f9244615SMatthew G. Knepley switch (trans) { 2038f9244615SMatthew G. Knepley case IDENTITY_TRANSFORM: break; 2039f9244615SMatthew G. Knepley case COVARIANT_PIOLA_TRANSFORM: /* Covariant Piola mapping $\sigma^*(F) = J^{-T} F \circ \phi^{-1)$ */ 2040f9244615SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2041f9244615SMatthew G. Knepley case CONTRAVARIANT_PIOLA_TRANSFORM: /* Contravariant Piola mapping $\sigma^*(F) = \frac{1}{|\det J|} J F \circ \phi^{-1}$ */ 2042f9244615SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Piola mapping for Hessians not yet supported"); 2043f9244615SMatthew G. Knepley } 2044f9244615SMatthew G. Knepley PetscFunctionReturn(0); 2045f9244615SMatthew G. Knepley } 2046f9244615SMatthew G. Knepley 2047f9244615SMatthew G. Knepley /*@C 20484bee2e38SMatthew G. Knepley PetscDualSpacePullback - Transform the given functional so that it operates on real space, rather than the reference element. Operationally, this means that we map the function evaluations depending on continuity requirements of our finite element method. 20494bee2e38SMatthew G. Knepley 20504bee2e38SMatthew G. Knepley Input Parameters: 20514bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 20524bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 20534bee2e38SMatthew G. Knepley . Nq - The number of function samples 20544bee2e38SMatthew G. Knepley . Nc - The number of function components 20554bee2e38SMatthew G. Knepley - pointEval - The function values 20564bee2e38SMatthew G. Knepley 20574bee2e38SMatthew G. Knepley Output Parameter: 20584bee2e38SMatthew G. Knepley . pointEval - The transformed function values 20594bee2e38SMatthew G. Knepley 20604bee2e38SMatthew G. Knepley Level: advanced 20614bee2e38SMatthew G. Knepley 20624bee2e38SMatthew G. Knepley Note: Functions transform in a complementary way (pushforward) to functionals, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex. 20634bee2e38SMatthew G. Knepley 20642edcad52SToby Isaac Note: This only handles tranformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 20652edcad52SToby Isaac 20664bee2e38SMatthew G. Knepley .seealso: PetscDualSpacePushforward(), PetscDualSpaceTransform(), PetscDualSpaceGetDeRahm() 20674bee2e38SMatthew G. Knepley @*/ 20682edcad52SToby Isaac PetscErrorCode PetscDualSpacePullback(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 20694bee2e38SMatthew G. Knepley { 20704bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2071b4457527SToby Isaac PetscInt k; 20724bee2e38SMatthew G. Knepley 20734bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 20744bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 20754bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 20762edcad52SToby Isaac PetscValidPointer(pointEval, 5); 20774bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 20784bee2e38SMatthew G. Knepley This determines their transformation properties. */ 20795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDeRahm(dsp, &k)); 2080b4457527SToby Isaac switch (k) 20814bee2e38SMatthew G. Knepley { 20824bee2e38SMatthew G. Knepley case 0: /* H^1 point evaluations */ 20834bee2e38SMatthew G. Knepley trans = IDENTITY_TRANSFORM;break; 20844bee2e38SMatthew G. Knepley case 1: /* Hcurl preserves tangential edge traces */ 20854bee2e38SMatthew G. Knepley trans = COVARIANT_PIOLA_TRANSFORM;break; 2086b4457527SToby Isaac case 2: 20874bee2e38SMatthew G. Knepley case 3: /* Hdiv preserve normal traces */ 20884bee2e38SMatthew G. Knepley trans = CONTRAVARIANT_PIOLA_TRANSFORM;break; 208998921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %D for transformation", k); 20904bee2e38SMatthew G. Knepley } 20915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceTransform(dsp, trans, PETSC_TRUE, fegeom, Nq, Nc, pointEval)); 20924bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 20934bee2e38SMatthew G. Knepley } 20944bee2e38SMatthew G. Knepley 20954bee2e38SMatthew G. Knepley /*@C 20964bee2e38SMatthew G. Knepley PetscDualSpacePushforward - Transform the given function so that it operates on real space, rather than the reference element. Operationally, this means that we map the function evaluations depending on continuity requirements of our finite element method. 20974bee2e38SMatthew G. Knepley 20984bee2e38SMatthew G. Knepley Input Parameters: 20994bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 21004bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21014bee2e38SMatthew G. Knepley . Nq - The number of function samples 21024bee2e38SMatthew G. Knepley . Nc - The number of function components 21034bee2e38SMatthew G. Knepley - pointEval - The function values 21044bee2e38SMatthew G. Knepley 21054bee2e38SMatthew G. Knepley Output Parameter: 21064bee2e38SMatthew G. Knepley . pointEval - The transformed function values 21074bee2e38SMatthew G. Knepley 21084bee2e38SMatthew G. Knepley Level: advanced 21094bee2e38SMatthew G. Knepley 21104bee2e38SMatthew G. Knepley Note: Functionals transform in a complementary way (pullback) to functions, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex. 21114bee2e38SMatthew G. Knepley 2112f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21132edcad52SToby Isaac 21144bee2e38SMatthew G. Knepley .seealso: PetscDualSpacePullback(), PetscDualSpaceTransform(), PetscDualSpaceGetDeRahm() 21154bee2e38SMatthew G. Knepley @*/ 21162edcad52SToby Isaac PetscErrorCode PetscDualSpacePushforward(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 21174bee2e38SMatthew G. Knepley { 21184bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2119b4457527SToby Isaac PetscInt k; 21204bee2e38SMatthew G. Knepley 21214bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21224bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 21234bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 21242edcad52SToby Isaac PetscValidPointer(pointEval, 5); 21254bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 21264bee2e38SMatthew G. Knepley This determines their transformation properties. */ 21275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDeRahm(dsp, &k)); 2128b4457527SToby Isaac switch (k) 21294bee2e38SMatthew G. Knepley { 21304bee2e38SMatthew G. Knepley case 0: /* H^1 point evaluations */ 21314bee2e38SMatthew G. Knepley trans = IDENTITY_TRANSFORM;break; 21324bee2e38SMatthew G. Knepley case 1: /* Hcurl preserves tangential edge traces */ 21334bee2e38SMatthew G. Knepley trans = COVARIANT_PIOLA_TRANSFORM;break; 2134b4457527SToby Isaac case 2: 21354bee2e38SMatthew G. Knepley case 3: /* Hdiv preserve normal traces */ 21364bee2e38SMatthew G. Knepley trans = CONTRAVARIANT_PIOLA_TRANSFORM;break; 213798921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %D for transformation", k); 21384bee2e38SMatthew G. Knepley } 21395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceTransform(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 21404bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 21414bee2e38SMatthew G. Knepley } 21424bee2e38SMatthew G. Knepley 21434bee2e38SMatthew G. Knepley /*@C 21444bee2e38SMatthew G. Knepley PetscDualSpacePushforwardGradient - Transform the given function gradient so that it operates on real space, rather than the reference element. Operationally, this means that we map the function evaluations depending on continuity requirements of our finite element method. 21454bee2e38SMatthew G. Knepley 21464bee2e38SMatthew G. Knepley Input Parameters: 21474bee2e38SMatthew G. Knepley + dsp - The PetscDualSpace 21484bee2e38SMatthew G. Knepley . fegeom - The geometry for this cell 21494bee2e38SMatthew G. Knepley . Nq - The number of function gradient samples 21504bee2e38SMatthew G. Knepley . Nc - The number of function components 21514bee2e38SMatthew G. Knepley - pointEval - The function gradient values 21524bee2e38SMatthew G. Knepley 21534bee2e38SMatthew G. Knepley Output Parameter: 21544bee2e38SMatthew G. Knepley . pointEval - The transformed function gradient values 21554bee2e38SMatthew G. Knepley 21564bee2e38SMatthew G. Knepley Level: advanced 21574bee2e38SMatthew G. Knepley 21584bee2e38SMatthew G. Knepley Note: Functionals transform in a complementary way (pullback) to functions, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex. 21594bee2e38SMatthew G. Knepley 2160f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 21612edcad52SToby Isaac 21624bee2e38SMatthew G. Knepley .seealso: PetscDualSpacePushforward(), PPetscDualSpacePullback(), PetscDualSpaceTransform(), PetscDualSpaceGetDeRahm() 2163dc0529c6SBarry Smith @*/ 21642edcad52SToby Isaac PetscErrorCode PetscDualSpacePushforwardGradient(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 21654bee2e38SMatthew G. Knepley { 21664bee2e38SMatthew G. Knepley PetscDualSpaceTransformType trans; 2167b4457527SToby Isaac PetscInt k; 21684bee2e38SMatthew G. Knepley 21694bee2e38SMatthew G. Knepley PetscFunctionBeginHot; 21704bee2e38SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 21714bee2e38SMatthew G. Knepley PetscValidPointer(fegeom, 2); 21722edcad52SToby Isaac PetscValidPointer(pointEval, 5); 21734bee2e38SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 21744bee2e38SMatthew G. Knepley This determines their transformation properties. */ 21755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDeRahm(dsp, &k)); 2176b4457527SToby Isaac switch (k) 21774bee2e38SMatthew G. Knepley { 21784bee2e38SMatthew G. Knepley case 0: /* H^1 point evaluations */ 21794bee2e38SMatthew G. Knepley trans = IDENTITY_TRANSFORM;break; 21804bee2e38SMatthew G. Knepley case 1: /* Hcurl preserves tangential edge traces */ 21814bee2e38SMatthew G. Knepley trans = COVARIANT_PIOLA_TRANSFORM;break; 2182b4457527SToby Isaac case 2: 21834bee2e38SMatthew G. Knepley case 3: /* Hdiv preserve normal traces */ 21844bee2e38SMatthew G. Knepley trans = CONTRAVARIANT_PIOLA_TRANSFORM;break; 218598921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %D for transformation", k); 21864bee2e38SMatthew G. Knepley } 21875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceTransformGradient(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 21884bee2e38SMatthew G. Knepley PetscFunctionReturn(0); 21894bee2e38SMatthew G. Knepley } 2190f9244615SMatthew G. Knepley 2191f9244615SMatthew G. Knepley /*@C 2192f9244615SMatthew G. Knepley PetscDualSpacePushforwardHessian - Transform the given function Hessian so that it operates on real space, rather than the reference element. Operationally, this means that we map the function evaluations depending on continuity requirements of our finite element method. 2193f9244615SMatthew G. Knepley 2194f9244615SMatthew G. Knepley Input Parameters: 2195f9244615SMatthew G. Knepley + dsp - The PetscDualSpace 2196f9244615SMatthew G. Knepley . fegeom - The geometry for this cell 2197f9244615SMatthew G. Knepley . Nq - The number of function Hessian samples 2198f9244615SMatthew G. Knepley . Nc - The number of function components 2199f9244615SMatthew G. Knepley - pointEval - The function gradient values 2200f9244615SMatthew G. Knepley 2201f9244615SMatthew G. Knepley Output Parameter: 2202f9244615SMatthew G. Knepley . pointEval - The transformed function Hessian values 2203f9244615SMatthew G. Knepley 2204f9244615SMatthew G. Knepley Level: advanced 2205f9244615SMatthew G. Knepley 2206f9244615SMatthew G. Knepley Note: Functionals transform in a complementary way (pullback) to functions, so that the scalar product is invariant. The type of transform is dependent on the associated k-simplex from the DeRahm complex. 2207f9244615SMatthew G. Knepley 2208f9244615SMatthew G. Knepley Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension. 2209f9244615SMatthew G. Knepley 2210f9244615SMatthew G. Knepley .seealso: PetscDualSpacePushforward(), PPetscDualSpacePullback(), PetscDualSpaceTransform(), PetscDualSpaceGetDeRahm() 2211f9244615SMatthew G. Knepley @*/ 2212f9244615SMatthew G. Knepley PetscErrorCode PetscDualSpacePushforwardHessian(PetscDualSpace dsp, PetscFEGeom *fegeom, PetscInt Nq, PetscInt Nc, PetscScalar pointEval[]) 2213f9244615SMatthew G. Knepley { 2214f9244615SMatthew G. Knepley PetscDualSpaceTransformType trans; 2215f9244615SMatthew G. Knepley PetscInt k; 2216f9244615SMatthew G. Knepley 2217f9244615SMatthew G. Knepley PetscFunctionBeginHot; 2218f9244615SMatthew G. Knepley PetscValidHeaderSpecific(dsp, PETSCDUALSPACE_CLASSID, 1); 2219f9244615SMatthew G. Knepley PetscValidPointer(fegeom, 2); 2220f9244615SMatthew G. Knepley PetscValidPointer(pointEval, 5); 2221f9244615SMatthew G. Knepley /* The dualspace dofs correspond to some simplex in the DeRahm complex, which we label by k. 2222f9244615SMatthew G. Knepley This determines their transformation properties. */ 22235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceGetDeRahm(dsp, &k)); 2224f9244615SMatthew G. Knepley switch (k) 2225f9244615SMatthew G. Knepley { 2226f9244615SMatthew G. Knepley case 0: /* H^1 point evaluations */ 2227f9244615SMatthew G. Knepley trans = IDENTITY_TRANSFORM;break; 2228f9244615SMatthew G. Knepley case 1: /* Hcurl preserves tangential edge traces */ 2229f9244615SMatthew G. Knepley trans = COVARIANT_PIOLA_TRANSFORM;break; 2230f9244615SMatthew G. Knepley case 2: 2231f9244615SMatthew G. Knepley case 3: /* Hdiv preserve normal traces */ 2232f9244615SMatthew G. Knepley trans = CONTRAVARIANT_PIOLA_TRANSFORM;break; 223398921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dsp), PETSC_ERR_ARG_OUTOFRANGE, "Unsupported simplex dim %D for transformation", k); 2234f9244615SMatthew G. Knepley } 22355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDualSpaceTransformHessian(dsp, trans, PETSC_FALSE, fegeom, Nq, Nc, pointEval)); 2236f9244615SMatthew G. Knepley PetscFunctionReturn(0); 2237f9244615SMatthew G. Knepley } 2238