1 #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/ 2 #include <petscdmplex.h> 3 4 typedef struct { 5 PetscInt dummy; 6 } PetscDualSpace_Refined; 7 8 /*@ 9 PetscDualSpaceRefinedSetCellSpaces - Set the dual spaces for the closures of each of the cells 10 in the multicell DM of a PetscDualSpace 11 12 Collective on PetscDualSpace 13 14 Input Parameters: 15 + sp - a PetscDualSpace 16 - cellSpaces - one PetscDualSpace for each of the cells. The reference count of each cell space will be incremented, 17 so the user is still responsible for these spaces afterwards 18 19 Level: intermediate 20 21 .seealso: PetscFERefine() 22 @*/ 23 PetscErrorCode PetscDualSpaceRefinedSetCellSpaces(PetscDualSpace sp, const PetscDualSpace cellSpaces[]) 24 { 25 PetscErrorCode ierr; 26 27 PetscFunctionBegin; 28 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 29 PetscValidPointer(cellSpaces,2); 30 if (sp->setupcalled) SETERRQ(PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change cell spaces after setup is called"); 31 ierr = PetscTryMethod(sp, "PetscDualSpaceRefinedSetCellSpaces_C", (PetscDualSpace,const PetscDualSpace []),(sp,cellSpaces));CHKERRQ(ierr); 32 PetscFunctionReturn(0); 33 } 34 35 static PetscErrorCode PetscDualSpaceRefinedSetCellSpaces_Refined(PetscDualSpace sp, const PetscDualSpace cellSpaces[]) 36 { 37 DM dm; 38 PetscInt pStart, pEnd; 39 PetscInt cStart, cEnd, c; 40 PetscErrorCode ierr; 41 42 PetscFunctionBegin; 43 dm = sp->dm; 44 if (!dm) SETERRQ(PetscObjectComm((PetscObject) sp), PETSC_ERR_ARG_WRONGSTATE, "PetscDualSpace must have a DM (PetscDualSpaceSetDM()) before calling PetscDualSpaceRefinedSetCellSpaces"); 45 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 46 if (!sp->pointSpaces) { 47 48 ierr = PetscCalloc1(pEnd-pStart,&(sp->pointSpaces));CHKERRQ(ierr); 49 } 50 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 51 for (c = 0; c < cEnd - cStart; c++) { 52 ierr = PetscObjectReference((PetscObject)cellSpaces[c]);CHKERRQ(ierr); 53 ierr = PetscDualSpaceDestroy(&(sp->pointSpaces[c + cStart - pStart]));CHKERRQ(ierr); 54 sp->pointSpaces[c+cStart-pStart] = cellSpaces[c]; 55 } 56 PetscFunctionReturn(0); 57 } 58 59 static PetscErrorCode PetscDualSpaceDestroy_Refined(PetscDualSpace sp) 60 { 61 PetscDualSpace_Refined *ref = (PetscDualSpace_Refined *) sp->data; 62 PetscErrorCode ierr; 63 64 PetscFunctionBegin; 65 ierr = PetscObjectComposeFunction((PetscObject) sp, "PetscDualSpaceRefinedSetCellSpaces_C", NULL);CHKERRQ(ierr); 66 ierr = PetscFree(ref);CHKERRQ(ierr); 67 PetscFunctionReturn(0); 68 } 69 70 static PetscErrorCode PetscDualSpaceSetUp_Refined(PetscDualSpace sp) 71 { 72 PetscInt pStart, pEnd, depth; 73 PetscInt cStart, cEnd, c, spdim; 74 PetscInt h; 75 DM dm; 76 PetscSection section; 77 PetscErrorCode ierr; 78 79 PetscFunctionBegin; 80 ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr); 81 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 82 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 83 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 84 for (c = cStart; c < cEnd; c++) { 85 if (sp->pointSpaces[c-pStart]) { 86 PetscInt ccStart, ccEnd; 87 if (sp->pointSpaces[c-pStart]->k != sp->k) SETERRQ(PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_INCOMP, "All cell spaces must have the same form degree as the refined dual space"); 88 if (sp->pointSpaces[c-pStart]->Nc != sp->Nc) SETERRQ(PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_INCOMP, "All cell spaces must have the same number of components as the refined dual space"); 89 ierr = DMPlexGetHeightStratum(sp->pointSpaces[c-pStart]->dm, 0, &ccStart, &ccEnd);CHKERRQ(ierr); 90 if (ccEnd - ccStart != 1) SETERRQ(PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_INCOMP, "All cell spaces must have a single cell themselves"); 91 } 92 } 93 for (c = cStart; c < cEnd; c++) { 94 if (sp->pointSpaces[c-pStart]) { 95 PetscBool cUniform; 96 97 ierr = PetscDualSpaceGetUniform(sp->pointSpaces[c-pStart],&cUniform);CHKERRQ(ierr); 98 if (!cUniform) break; 99 } 100 if ((c > cStart) && sp->pointSpaces[c-pStart] != sp->pointSpaces[c-1-pStart]) break; 101 } 102 if (c < cEnd) sp->uniform = PETSC_FALSE; 103 for (h = 0; h < depth; h++) { 104 PetscInt hStart, hEnd; 105 106 ierr = DMPlexGetHeightStratum(dm, h, &hStart, &hEnd);CHKERRQ(ierr); 107 for (c = hStart; c < hEnd; c++) { 108 PetscInt coneSize, e; 109 PetscDualSpace cspace = sp->pointSpaces[c-pStart]; 110 const PetscInt *cone; 111 const PetscInt *refCone; 112 113 if (!cspace) continue; 114 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 115 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 116 ierr = DMPlexGetCone(cspace->dm, 0, &refCone);CHKERRQ(ierr); 117 for (e = 0; e < coneSize; e++) { 118 PetscInt point = cone[e]; 119 PetscInt refpoint = refCone[e]; 120 PetscDualSpace espace; 121 122 ierr = PetscDualSpaceGetPointSubspace(cspace,refpoint,&espace);CHKERRQ(ierr); 123 if (sp->pointSpaces[point-pStart] == NULL) { 124 ierr = PetscObjectReference((PetscObject)espace);CHKERRQ(ierr); 125 sp->pointSpaces[point-pStart] = espace; 126 } 127 } 128 } 129 } 130 ierr = PetscDualSpaceGetSection(sp, §ion);CHKERRQ(ierr); 131 ierr = PetscDualSpaceGetDimension(sp, &spdim);CHKERRQ(ierr); 132 ierr = PetscMalloc1(spdim, &(sp->functional));CHKERRQ(ierr); 133 ierr = PetscDualSpacePushForwardSubspaces_Internal(sp, pStart, pEnd);CHKERRQ(ierr); 134 PetscFunctionReturn(0); 135 } 136 137 static PetscErrorCode PetscDualSpaceRefinedView_Ascii(PetscDualSpace sp, PetscViewer viewer) 138 { 139 PetscErrorCode ierr; 140 141 PetscFunctionBegin; 142 if (sp->dm && sp->pointSpaces) { 143 PetscInt pStart, pEnd; 144 PetscInt cStart, cEnd, c; 145 146 ierr = DMPlexGetChart(sp->dm, &pStart, &pEnd);CHKERRQ(ierr); 147 ierr = DMPlexGetHeightStratum(sp->dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 148 ierr = PetscViewerASCIIPrintf(viewer, "Refined dual space:\n");CHKERRQ(ierr); 149 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 150 for (c = cStart; c < cEnd; c++) { 151 if (!sp->pointSpaces[c-pStart]) { 152 ierr = PetscViewerASCIIPrintf(viewer, "Cell space %D not set yet\n", c);CHKERRQ(ierr); 153 } else { 154 ierr = PetscViewerASCIIPrintf(viewer, "Cell space %D:ot set yet\n", c);CHKERRQ(ierr); 155 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 156 ierr = PetscDualSpaceView(sp->pointSpaces[c-pStart],viewer);CHKERRQ(ierr); 157 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 158 } 159 } 160 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 161 } else { 162 ierr = PetscViewerASCIIPrintf(viewer, "Refined dual space: (cell spaces not set yet)\n");CHKERRQ(ierr); 163 } 164 PetscFunctionReturn(0); 165 } 166 167 static PetscErrorCode PetscDualSpaceView_Refined(PetscDualSpace sp, PetscViewer viewer) 168 { 169 PetscBool iascii; 170 PetscErrorCode ierr; 171 172 PetscFunctionBegin; 173 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 174 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 175 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 176 if (iascii) {ierr = PetscDualSpaceRefinedView_Ascii(sp, viewer);CHKERRQ(ierr);} 177 PetscFunctionReturn(0); 178 } 179 180 static PetscErrorCode PetscDualSpaceInitialize_Refined(PetscDualSpace sp) 181 { 182 PetscFunctionBegin; 183 sp->ops->destroy = PetscDualSpaceDestroy_Refined; 184 sp->ops->view = PetscDualSpaceView_Refined; 185 sp->ops->setfromoptions = NULL; 186 sp->ops->duplicate = NULL; 187 sp->ops->setup = PetscDualSpaceSetUp_Refined; 188 sp->ops->createheightsubspace = NULL; 189 sp->ops->createpointsubspace = NULL; 190 sp->ops->getsymmetries = NULL; 191 sp->ops->apply = PetscDualSpaceApplyDefault; 192 sp->ops->applyall = PetscDualSpaceApplyAllDefault; 193 sp->ops->applyint = PetscDualSpaceApplyInteriorDefault; 194 sp->ops->createalldata = PetscDualSpaceCreateAllDataDefault; 195 sp->ops->createintdata = PetscDualSpaceCreateInteriorDataDefault; 196 PetscFunctionReturn(0); 197 } 198 199 /*MC 200 PETSCDUALSPACEREFINED = "refined" - A PetscDualSpace object that defines the joint dual space of a group of cells, usually refined from one larger cell 201 202 Level: intermediate 203 204 .seealso: PetscDualSpaceType, PetscDualSpaceCreate(), PetscDualSpaceSetType() 205 M*/ 206 PETSC_EXTERN PetscErrorCode PetscDualSpaceCreate_Refined(PetscDualSpace sp) 207 { 208 PetscDualSpace_Refined *ref; 209 PetscErrorCode ierr; 210 211 PetscFunctionBegin; 212 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1); 213 ierr = PetscNewLog(sp,&ref);CHKERRQ(ierr); 214 sp->data = ref; 215 216 ierr = PetscDualSpaceInitialize_Refined(sp);CHKERRQ(ierr); 217 ierr = PetscObjectComposeFunction((PetscObject) sp, "PetscDualSpaceRefinedSetCellSpaces_C", PetscDualSpaceRefinedSetCellSpaces_Refined);CHKERRQ(ierr); 218 PetscFunctionReturn(0); 219 } 220