1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/isimpl.h> 3 #include <petsc/private/vecimpl.h> 4 #include <petsc/private/glvisvecimpl.h> 5 #include <petscsf.h> 6 #include <petscds.h> 7 #include <petscdraw.h> 8 9 /* Logging support */ 10 PetscLogEvent DMPLEX_Interpolate, PETSCPARTITIONER_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh; 11 12 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 13 14 /*@ 15 DMPlexRefineSimplexToTensor - Uniformly refines simplicial cells into tensor product cells. 16 3 quadrilaterals per triangle in 2D and 4 hexahedra per tetrahedron in 3D. 17 18 Collective 19 20 Input Parameters: 21 . dm - The DMPlex object 22 23 Output Parameters: 24 . dmRefined - The refined DMPlex object 25 26 Note: Returns NULL if the mesh is already a tensor product mesh. 27 28 Level: intermediate 29 30 .seealso: DMPlexCreate(), DMPlexSetRefinementUniform() 31 @*/ 32 PetscErrorCode DMPlexRefineSimplexToTensor(DM dm, DM *dmRefined) 33 { 34 PetscInt dim, cMax, fMax, cStart, cEnd, coneSize; 35 CellRefiner cellRefiner; 36 PetscBool lop, allnoop, localized; 37 PetscErrorCode ierr; 38 39 PetscFunctionBegin; 40 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 42 ierr = DMPlexGetHybridBounds(dm,&cMax,&fMax,NULL,NULL);CHKERRQ(ierr); 43 if (cMax >= 0 || fMax >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle hybrid meshes yet"); 44 ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 45 if (!(cEnd - cStart)) cellRefiner = REFINER_NOOP; 46 else { 47 ierr = DMPlexGetConeSize(dm,cStart,&coneSize);CHKERRQ(ierr); 48 switch (dim) { 49 case 1: 50 cellRefiner = REFINER_NOOP; 51 break; 52 case 2: 53 switch (coneSize) { 54 case 3: 55 cellRefiner = REFINER_SIMPLEX_TO_HEX_2D; 56 break; 57 case 4: 58 cellRefiner = REFINER_NOOP; 59 break; 60 default: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle coneSize %D with dimension %D",coneSize,dim); 61 } 62 break; 63 case 3: 64 switch (coneSize) { 65 case 4: 66 cellRefiner = REFINER_SIMPLEX_TO_HEX_3D; 67 break; 68 case 6: 69 cellRefiner = REFINER_NOOP; 70 break; 71 default: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle coneSize %D with dimension %D",coneSize,dim); 72 } 73 break; 74 default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle dimension %D",dim); 75 } 76 } 77 /* return if we don't need to refine */ 78 lop = (cellRefiner == REFINER_NOOP) ? PETSC_TRUE : PETSC_FALSE; 79 ierr = MPIU_Allreduce(&lop,&allnoop,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 80 if (allnoop) { 81 *dmRefined = NULL; 82 PetscFunctionReturn(0); 83 } 84 ierr = DMPlexRefineUniform_Internal(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 85 ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr); 86 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 87 if (localized) { 88 ierr = DMLocalizeCoordinates(*dmRefined);CHKERRQ(ierr); 89 } 90 PetscFunctionReturn(0); 91 } 92 93 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 94 { 95 PetscInt dim, pStart, pEnd, vStart, vEnd, cStart, cEnd, cEndInterior; 96 PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 97 PetscErrorCode ierr; 98 99 PetscFunctionBegin; 100 *ft = PETSC_VTK_POINT_FIELD; 101 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 102 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 103 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 104 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 105 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 106 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 107 if (field >= 0) { 108 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);} 109 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);} 110 } else { 111 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);} 112 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);} 113 } 114 ierr = MPI_Allreduce(&vcdof, &globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 115 if (globalvcdof[0]) { 116 *sStart = vStart; 117 *sEnd = vEnd; 118 if (globalvcdof[0] == dim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 119 else *ft = PETSC_VTK_POINT_FIELD; 120 } else if (globalvcdof[1]) { 121 *sStart = cStart; 122 *sEnd = cEnd; 123 if (globalvcdof[1] == dim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 124 else *ft = PETSC_VTK_CELL_FIELD; 125 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 126 PetscFunctionReturn(0); 127 } 128 129 static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 130 { 131 DM dm; 132 PetscSection s; 133 PetscDraw draw, popup; 134 DM cdm; 135 PetscSection coordSection; 136 Vec coordinates; 137 const PetscScalar *coords, *array; 138 PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 139 PetscReal vbound[2], time; 140 PetscBool isnull, flg; 141 PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 142 const char *name; 143 char title[PETSC_MAX_PATH_LEN]; 144 PetscErrorCode ierr; 145 146 PetscFunctionBegin; 147 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 148 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 149 if (isnull) PetscFunctionReturn(0); 150 151 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 152 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 153 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim); 154 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 155 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 156 ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 157 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 158 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 159 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 160 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 161 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 162 163 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 164 ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 165 166 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 167 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 168 for (c = 0; c < N; c += dim) { 169 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 170 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 171 } 172 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 173 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 174 175 /* Could implement something like DMDASelectFields() */ 176 for (f = 0; f < Nf; ++f) { 177 DM fdm = dm; 178 Vec fv = v; 179 IS fis; 180 char prefix[PETSC_MAX_PATH_LEN]; 181 const char *fname; 182 183 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 184 ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 185 186 if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 187 else {prefix[0] = '\0';} 188 if (Nf > 1) { 189 ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 190 ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 191 ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 192 ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 193 } 194 for (comp = 0; comp < Nc; ++comp, ++w) { 195 PetscInt nmax = 2; 196 197 ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 198 if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 199 else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 200 ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 201 202 /* TODO Get max and min only for this component */ 203 ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 204 if (!flg) { 205 ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 206 ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 207 if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 208 } 209 ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 210 ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 211 ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 212 213 ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 214 for (c = cStart; c < cEnd; ++c) { 215 PetscScalar *coords = NULL, *a = NULL; 216 PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 217 218 ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 219 if (a) { 220 color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 221 color[1] = color[2] = color[3] = color[0]; 222 } else { 223 PetscScalar *vals = NULL; 224 PetscInt numVals, va; 225 226 ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 227 if (numVals % Nc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %D does not divide the number of values in the closure %D", Nc, numVals); 228 switch (numVals/Nc) { 229 case 3: /* P1 Triangle */ 230 case 4: /* P1 Quadrangle */ 231 for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 232 break; 233 case 6: /* P2 Triangle */ 234 case 8: /* P2 Quadrangle */ 235 for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 236 break; 237 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 238 } 239 ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 240 } 241 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 242 switch (numCoords) { 243 case 6: 244 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 245 break; 246 case 8: 247 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 248 ierr = PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]);CHKERRQ(ierr); 249 break; 250 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 251 } 252 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 253 } 254 ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 255 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 256 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 257 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 258 } 259 if (Nf > 1) { 260 ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 261 ierr = ISDestroy(&fis);CHKERRQ(ierr); 262 ierr = DMDestroy(&fdm);CHKERRQ(ierr); 263 } 264 } 265 PetscFunctionReturn(0); 266 } 267 268 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 269 { 270 DM dm; 271 PetscBool isvtk, ishdf5, isdraw, isseq, isglvis; 272 PetscErrorCode ierr; 273 274 PetscFunctionBegin; 275 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 276 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 277 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 278 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 279 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 280 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 281 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 282 if (isvtk || ishdf5 || isglvis) { 283 PetscInt numFields; 284 PetscBool fem = PETSC_FALSE; 285 286 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 287 if (numFields) { 288 PetscObject fe; 289 290 ierr = DMGetField(dm, 0, &fe);CHKERRQ(ierr); 291 if (fe->classid == PETSCFE_CLASSID) fem = PETSC_TRUE; 292 } 293 if (fem) {ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, v, 0.0, NULL, NULL, NULL);CHKERRQ(ierr);} 294 } 295 if (isvtk) { 296 PetscSection section; 297 PetscViewerVTKFieldType ft; 298 PetscInt pStart, pEnd; 299 300 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 301 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 302 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 303 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 304 } else if (ishdf5) { 305 #if defined(PETSC_HAVE_HDF5) 306 ierr = VecView_Plex_Local_HDF5_Internal(v, viewer);CHKERRQ(ierr); 307 #else 308 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 309 #endif 310 } else if (isglvis) { 311 ierr = VecView_GLVis(v, viewer);CHKERRQ(ierr); 312 } else if (isdraw) { 313 ierr = VecView_Plex_Local_Draw(v, viewer);CHKERRQ(ierr); 314 } else { 315 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 316 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 317 } 318 PetscFunctionReturn(0); 319 } 320 321 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 322 { 323 DM dm; 324 PetscReal time = 0.0; 325 PetscBool isvtk, ishdf5, isdraw, isseq, isglvis; 326 PetscErrorCode ierr; 327 328 PetscFunctionBegin; 329 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 330 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 331 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 332 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 333 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 334 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 335 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 336 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 337 if (isvtk || isglvis) { 338 PetscInt num; 339 Vec locv; 340 const char *name; 341 342 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 343 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 344 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 345 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 346 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 347 ierr = DMGetOutputSequenceNumber(dm, &num, &time);CHKERRQ(ierr); 348 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 349 ierr = PetscViewerGLVisSetSnapId(viewer, num);CHKERRQ(ierr); 350 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 351 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 352 } else if (ishdf5) { 353 #if defined(PETSC_HAVE_HDF5) 354 ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 355 #else 356 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 357 #endif 358 } else if (isdraw) { 359 Vec locv; 360 const char *name; 361 362 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 363 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 364 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 365 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 366 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 367 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 368 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 369 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 370 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 371 } else { 372 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 373 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 374 } 375 PetscFunctionReturn(0); 376 } 377 378 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 379 { 380 DM dm; 381 MPI_Comm comm; 382 PetscViewerFormat format; 383 Vec v; 384 PetscBool isvtk, ishdf5; 385 PetscErrorCode ierr; 386 387 PetscFunctionBegin; 388 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 389 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 390 if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 391 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 392 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 393 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 394 if (format == PETSC_VIEWER_NATIVE) { 395 const char *vecname; 396 PetscInt n, nroots; 397 398 if (dm->sfNatural) { 399 ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 400 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 401 if (n == nroots) { 402 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 403 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 404 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 405 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 406 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 407 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 408 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 409 } else { 410 /* we are viewing a natural DMPlex vec. */ 411 v = originalv; 412 } 413 if (ishdf5) { 414 #if defined(PETSC_HAVE_HDF5) 415 ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 416 #else 417 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 418 #endif 419 } else if (isvtk) { 420 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 421 } else { 422 PetscBool isseq; 423 424 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 425 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 426 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 427 } 428 if (format == PETSC_VIEWER_NATIVE) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 429 PetscFunctionReturn(0); 430 } 431 432 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 433 { 434 DM dm; 435 PetscBool ishdf5; 436 PetscErrorCode ierr; 437 438 PetscFunctionBegin; 439 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 440 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 441 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 442 if (ishdf5) { 443 DM dmBC; 444 Vec gv; 445 const char *name; 446 447 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 448 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 449 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 450 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 451 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 452 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 453 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 454 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 455 } else { 456 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 457 } 458 PetscFunctionReturn(0); 459 } 460 461 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 462 { 463 DM dm; 464 PetscBool ishdf5; 465 PetscErrorCode ierr; 466 467 PetscFunctionBegin; 468 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 469 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 470 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 471 if (ishdf5) { 472 #if defined(PETSC_HAVE_HDF5) 473 ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 474 #else 475 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 476 #endif 477 } else { 478 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 479 } 480 PetscFunctionReturn(0); 481 } 482 483 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 484 { 485 DM dm; 486 PetscViewerFormat format; 487 PetscBool ishdf5; 488 PetscErrorCode ierr; 489 490 PetscFunctionBegin; 491 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 492 if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 493 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 494 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 495 if (format == PETSC_VIEWER_NATIVE) { 496 if (dm->sfNatural) { 497 if (ishdf5) { 498 #if defined(PETSC_HAVE_HDF5) 499 Vec v; 500 const char *vecname; 501 502 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 503 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 504 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 505 ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 506 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 507 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 508 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 509 #else 510 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 511 #endif 512 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 513 } 514 } 515 PetscFunctionReturn(0); 516 } 517 518 PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 519 { 520 PetscSection coordSection; 521 Vec coordinates; 522 DMLabel depthLabel; 523 const char *name[4]; 524 const PetscScalar *a; 525 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 526 PetscErrorCode ierr; 527 528 PetscFunctionBegin; 529 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 530 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 531 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 532 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 533 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 534 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 535 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 536 name[0] = "vertex"; 537 name[1] = "edge"; 538 name[dim-1] = "face"; 539 name[dim] = "cell"; 540 for (c = cStart; c < cEnd; ++c) { 541 PetscInt *closure = NULL; 542 PetscInt closureSize, cl; 543 544 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D:\n", c);CHKERRQ(ierr); 545 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 546 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 547 for (cl = 0; cl < closureSize*2; cl += 2) { 548 PetscInt point = closure[cl], depth, dof, off, d, p; 549 550 if ((point < pStart) || (point >= pEnd)) continue; 551 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 552 if (!dof) continue; 553 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 554 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 555 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 556 for (p = 0; p < dof/dim; ++p) { 557 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 558 for (d = 0; d < dim; ++d) { 559 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 560 ierr = PetscViewerASCIIPrintf(viewer, "%g", PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 561 } 562 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 563 } 564 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 565 } 566 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 567 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 568 } 569 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 570 PetscFunctionReturn(0); 571 } 572 573 static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 574 { 575 DM_Plex *mesh = (DM_Plex*) dm->data; 576 DM cdm; 577 DMLabel markers; 578 PetscSection coordSection; 579 Vec coordinates; 580 PetscViewerFormat format; 581 PetscErrorCode ierr; 582 583 PetscFunctionBegin; 584 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 585 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 586 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 587 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 588 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 589 const char *name; 590 PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 591 PetscInt pStart, pEnd, p; 592 PetscMPIInt rank, size; 593 594 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 595 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 596 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 597 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 598 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 599 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 600 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 601 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 602 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 603 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 604 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 605 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 606 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 607 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max sizes cone: %D support: %D\n", rank,maxConeSize, maxSupportSize);CHKERRQ(ierr); 608 for (p = pStart; p < pEnd; ++p) { 609 PetscInt dof, off, s; 610 611 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 612 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 613 for (s = off; s < off+dof; ++s) { 614 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 615 } 616 } 617 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 618 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 619 for (p = pStart; p < pEnd; ++p) { 620 PetscInt dof, off, c; 621 622 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 623 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 624 for (c = off; c < off+dof; ++c) { 625 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 626 } 627 } 628 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 629 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 630 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 631 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 632 ierr = DMGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 633 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 634 if (size > 1) { 635 PetscSF sf; 636 637 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 638 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 639 } 640 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 641 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 642 const char *name, *color; 643 const char *defcolors[3] = {"gray", "orange", "green"}; 644 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 645 PetscReal scale = 2.0; 646 PetscBool useNumbers = PETSC_TRUE, useLabels, useColors; 647 double tcoords[3]; 648 PetscScalar *coords; 649 PetscInt numLabels, l, numColors, numLColors, dim, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 650 PetscMPIInt rank, size; 651 char **names, **colors, **lcolors; 652 653 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 654 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 655 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 656 numLabels = PetscMax(numLabels, 10); 657 numColors = 10; 658 numLColors = 10; 659 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 660 ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 661 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 662 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 663 if (!useLabels) numLabels = 0; 664 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 665 if (!useColors) { 666 numColors = 3; 667 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 668 } 669 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 670 if (!useColors) { 671 numLColors = 4; 672 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 673 } 674 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 675 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 676 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 677 ierr = PetscViewerASCIIPrintf(viewer, "\ 678 \\documentclass[tikz]{standalone}\n\n\ 679 \\usepackage{pgflibraryshapes}\n\ 680 \\usetikzlibrary{backgrounds}\n\ 681 \\usetikzlibrary{arrows}\n\ 682 \\begin{document}\n");CHKERRQ(ierr); 683 if (size > 1) { 684 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 685 for (p = 0; p < size; ++p) { 686 if (p > 0 && p == size-1) { 687 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 688 } else if (p > 0) { 689 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 690 } 691 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 692 } 693 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 694 } 695 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", 1.0);CHKERRQ(ierr); 696 /* Plot vertices */ 697 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 698 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 699 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 700 for (v = vStart; v < vEnd; ++v) { 701 PetscInt off, dof, d; 702 PetscBool isLabeled = PETSC_FALSE; 703 704 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 705 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 706 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 707 if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 708 for (d = 0; d < dof; ++d) { 709 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 710 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 711 } 712 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 713 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 714 for (d = 0; d < dof; ++d) { 715 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 716 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", tcoords[d]);CHKERRQ(ierr); 717 } 718 color = colors[rank%numColors]; 719 for (l = 0; l < numLabels; ++l) { 720 PetscInt val; 721 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 722 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 723 } 724 if (useNumbers) { 725 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 726 } else { 727 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 728 } 729 } 730 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 731 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 732 /* Plot edges */ 733 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 734 if (dim < 3 && useNumbers) { 735 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 736 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 737 for (e = eStart; e < eEnd; ++e) { 738 const PetscInt *cone; 739 PetscInt coneSize, offA, offB, dof, d; 740 741 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 742 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 743 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 744 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 745 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 746 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 747 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 748 for (d = 0; d < dof; ++d) { 749 tcoords[d] = (double) (scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 750 tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 751 } 752 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 753 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 754 for (d = 0; d < dof; ++d) { 755 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 756 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 757 } 758 color = colors[rank%numColors]; 759 for (l = 0; l < numLabels; ++l) { 760 PetscInt val; 761 ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 762 if (val >= 0) {color = lcolors[l%numLColors]; break;} 763 } 764 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 765 } 766 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 767 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 768 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 769 } 770 /* Plot cells */ 771 if (dim == 3 || !useNumbers) { 772 for (e = eStart; e < eEnd; ++e) { 773 const PetscInt *cone; 774 775 color = colors[rank%numColors]; 776 for (l = 0; l < numLabels; ++l) { 777 PetscInt val; 778 ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 779 if (val >= 0) {color = lcolors[l%numLColors]; break;} 780 } 781 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 782 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 783 } 784 } else { 785 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 786 for (c = cStart; c < cEnd; ++c) { 787 PetscInt *closure = NULL; 788 PetscInt closureSize, firstPoint = -1; 789 790 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 791 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 792 for (p = 0; p < closureSize*2; p += 2) { 793 const PetscInt point = closure[p]; 794 795 if ((point < vStart) || (point >= vEnd)) continue; 796 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 797 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", point, rank);CHKERRQ(ierr); 798 if (firstPoint < 0) firstPoint = point; 799 } 800 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 801 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d);\n", firstPoint, rank);CHKERRQ(ierr); 802 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 803 } 804 } 805 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 806 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 807 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 808 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 809 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 810 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 811 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 812 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 813 } else { 814 MPI_Comm comm; 815 PetscInt *sizes, *hybsizes; 816 PetscInt locDepth, depth, cellHeight, dim, d, pMax[4]; 817 PetscInt pStart, pEnd, p; 818 PetscInt numLabels, l; 819 const char *name; 820 PetscMPIInt size; 821 822 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 823 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 824 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 825 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 826 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 827 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 828 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 829 if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 830 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 831 ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 832 ierr = DMPlexGetHybridBounds(dm, &pMax[depth], depth > 0 ? &pMax[depth-1] : NULL, &pMax[1], &pMax[0]);CHKERRQ(ierr); 833 ierr = PetscMalloc2(size,&sizes,size,&hybsizes);CHKERRQ(ierr); 834 if (depth == 1) { 835 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 836 pEnd = pEnd - pStart; 837 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 838 ierr = PetscViewerASCIIPrintf(viewer, " %d-cells:", 0);CHKERRQ(ierr); 839 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 840 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 841 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 842 pEnd = pEnd - pStart; 843 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 844 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 845 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 846 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 847 } else { 848 PetscMPIInt rank; 849 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 850 for (d = 0; d <= dim; d++) { 851 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 852 pEnd -= pStart; 853 pMax[d] -= pStart; 854 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 855 ierr = MPI_Gather(&pMax[d], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 856 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 857 for (p = 0; p < size; ++p) { 858 if (!rank) { 859 if (hybsizes[p] >= 0) {ierr = PetscViewerASCIIPrintf(viewer, " %D (%D)", sizes[p], sizes[p] - hybsizes[p]);CHKERRQ(ierr);} 860 else {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 861 } 862 } 863 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 864 } 865 } 866 ierr = PetscFree2(sizes,hybsizes);CHKERRQ(ierr); 867 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 868 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 869 for (l = 0; l < numLabels; ++l) { 870 DMLabel label; 871 const char *name; 872 IS valueIS; 873 const PetscInt *values; 874 PetscInt numValues, v; 875 876 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 877 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 878 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 879 ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 880 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 881 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 882 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 883 for (v = 0; v < numValues; ++v) { 884 PetscInt size; 885 886 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 887 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 888 ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 889 } 890 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 891 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 892 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 893 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 894 } 895 ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 896 if (cdm) { 897 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 898 ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 899 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 900 } 901 } 902 PetscFunctionReturn(0); 903 } 904 905 static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 906 { 907 PetscDraw draw; 908 DM cdm; 909 PetscSection coordSection; 910 Vec coordinates; 911 const PetscScalar *coords; 912 PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 913 PetscBool isnull; 914 PetscInt dim, vStart, vEnd, cStart, cEnd, c, N; 915 PetscErrorCode ierr; 916 917 PetscFunctionBegin; 918 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 919 if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 920 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 921 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 922 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 923 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 924 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 925 926 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 927 ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 928 if (isnull) PetscFunctionReturn(0); 929 ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 930 931 ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 932 ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 933 for (c = 0; c < N; c += dim) { 934 bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 935 bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 936 } 937 ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 938 ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 939 ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 940 ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 941 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 942 943 for (c = cStart; c < cEnd; ++c) { 944 PetscScalar *coords = NULL; 945 PetscInt numCoords,coneSize; 946 947 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 948 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 949 switch (coneSize) { 950 case 3: 951 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 952 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 953 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 954 break; 955 case 4: 956 ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 957 ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 958 ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 959 ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 960 break; 961 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D facets", coneSize); 962 } 963 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 964 } 965 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 966 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 967 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 968 PetscFunctionReturn(0); 969 } 970 971 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 972 { 973 PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis; 974 PetscErrorCode ierr; 975 976 PetscFunctionBegin; 977 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 978 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 979 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 980 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 981 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 982 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 983 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 984 if (iascii) { 985 PetscViewerFormat format; 986 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 987 if (format == PETSC_VIEWER_ASCII_GLVIS) { 988 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 989 } else { 990 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 991 } 992 } else if (ishdf5) { 993 #if defined(PETSC_HAVE_HDF5) 994 ierr = PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_VIZ);CHKERRQ(ierr); 995 ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 996 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 997 #else 998 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 999 #endif 1000 } else if (isvtk) { 1001 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1002 } else if (isdraw) { 1003 ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 1004 } else if (isglvis) { 1005 ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 1006 } 1007 /* Optionally view the partition */ 1008 ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1009 if (flg) { 1010 Vec ranks; 1011 ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1012 ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1013 ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1014 } 1015 PetscFunctionReturn(0); 1016 } 1017 1018 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 1019 { 1020 PetscBool isbinary, ishdf5; 1021 PetscErrorCode ierr; 1022 1023 PetscFunctionBegin; 1024 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1025 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1026 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 1027 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1028 if (isbinary) {SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Do not yet support binary viewers");} 1029 else if (ishdf5) { 1030 #if defined(PETSC_HAVE_HDF5) 1031 ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1032 #else 1033 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1034 #endif 1035 } 1036 PetscFunctionReturn(0); 1037 } 1038 1039 PetscErrorCode DMDestroy_Plex(DM dm) 1040 { 1041 DM_Plex *mesh = (DM_Plex*) dm->data; 1042 PetscErrorCode ierr; 1043 1044 PetscFunctionBegin; 1045 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 1046 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 1047 if (--mesh->refct > 0) PetscFunctionReturn(0); 1048 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 1049 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 1050 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 1051 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 1052 ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 1053 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 1054 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 1055 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 1056 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 1057 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 1058 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 1059 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 1060 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 1061 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 1062 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 1063 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 1064 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 1065 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 1066 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 1067 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 1068 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 1069 ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 1070 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 1071 ierr = PetscFree(mesh);CHKERRQ(ierr); 1072 PetscFunctionReturn(0); 1073 } 1074 1075 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 1076 { 1077 PetscSection sectionGlobal; 1078 PetscInt bs = -1, mbs; 1079 PetscInt localSize; 1080 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 1081 PetscErrorCode ierr; 1082 MatType mtype; 1083 ISLocalToGlobalMapping ltog; 1084 1085 PetscFunctionBegin; 1086 ierr = MatInitializePackage();CHKERRQ(ierr); 1087 mtype = dm->mattype; 1088 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1089 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 1090 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 1091 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 1092 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1093 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 1094 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 1095 ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 1096 if (mbs > 1) bs = mbs; 1097 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 1098 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 1099 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 1100 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 1101 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 1102 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 1103 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 1104 ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 1105 if (!isShell) { 1106 PetscSection subSection; 1107 PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 1108 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize; 1109 PetscInt pStart, pEnd, p, dof, cdof; 1110 1111 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */ 1112 if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */ 1113 PetscSection section; 1114 PetscInt size; 1115 1116 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1117 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 1118 ierr = PetscMalloc1(size,<ogidx);CHKERRQ(ierr); 1119 ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 1120 } else { 1121 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 1122 } 1123 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1124 for (p = pStart, lsize = 0; p < pEnd; ++p) { 1125 PetscInt bdof; 1126 1127 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 1128 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 1129 dof = dof < 0 ? -(dof+1) : dof; 1130 bdof = cdof && (dof-cdof) ? 1 : dof; 1131 if (dof) { 1132 if (bs < 0) {bs = bdof;} 1133 else if (bs != bdof) {bs = 1; if (!isMatIS) break;} 1134 } 1135 if (isMatIS) { 1136 PetscInt loff,c,off; 1137 ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr); 1138 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 1139 for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c; 1140 } 1141 } 1142 /* Must have same blocksize on all procs (some might have no points) */ 1143 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 1144 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 1145 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 1146 else {bs = bsMinMax[0];} 1147 bs = bs < 0 ? 1 : bs; 1148 if (isMatIS) { 1149 PetscInt l; 1150 /* Must reduce indices by blocksize */ 1151 if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] /= bs; 1152 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, <og);CHKERRQ(ierr); 1153 } 1154 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 1155 if (isMatIS) { 1156 ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 1157 } 1158 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 1159 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1160 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1161 } 1162 ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 1163 PetscFunctionReturn(0); 1164 } 1165 1166 /*@ 1167 DMPlexGetSubdomainSection - Returns the section associated with the subdomain 1168 1169 Not collective 1170 1171 Input Parameter: 1172 . mesh - The DMPlex 1173 1174 Output Parameters: 1175 . subsection - The subdomain section 1176 1177 Level: developer 1178 1179 .seealso: 1180 @*/ 1181 PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 1182 { 1183 DM_Plex *mesh = (DM_Plex*) dm->data; 1184 PetscErrorCode ierr; 1185 1186 PetscFunctionBegin; 1187 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1188 if (!mesh->subdomainSection) { 1189 PetscSection section; 1190 PetscSF sf; 1191 1192 ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 1193 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 1194 ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 1195 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 1196 } 1197 *subsection = mesh->subdomainSection; 1198 PetscFunctionReturn(0); 1199 } 1200 1201 /*@ 1202 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1203 1204 Not collective 1205 1206 Input Parameter: 1207 . mesh - The DMPlex 1208 1209 Output Parameters: 1210 + pStart - The first mesh point 1211 - pEnd - The upper bound for mesh points 1212 1213 Level: beginner 1214 1215 .seealso: DMPlexCreate(), DMPlexSetChart() 1216 @*/ 1217 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1218 { 1219 DM_Plex *mesh = (DM_Plex*) dm->data; 1220 PetscErrorCode ierr; 1221 1222 PetscFunctionBegin; 1223 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1224 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1225 PetscFunctionReturn(0); 1226 } 1227 1228 /*@ 1229 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1230 1231 Not collective 1232 1233 Input Parameters: 1234 + mesh - The DMPlex 1235 . pStart - The first mesh point 1236 - pEnd - The upper bound for mesh points 1237 1238 Output Parameters: 1239 1240 Level: beginner 1241 1242 .seealso: DMPlexCreate(), DMPlexGetChart() 1243 @*/ 1244 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1245 { 1246 DM_Plex *mesh = (DM_Plex*) dm->data; 1247 PetscErrorCode ierr; 1248 1249 PetscFunctionBegin; 1250 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1251 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1252 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1253 PetscFunctionReturn(0); 1254 } 1255 1256 /*@ 1257 DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 1258 1259 Not collective 1260 1261 Input Parameters: 1262 + mesh - The DMPlex 1263 - p - The point, which must lie in the chart set with DMPlexSetChart() 1264 1265 Output Parameter: 1266 . size - The cone size for point p 1267 1268 Level: beginner 1269 1270 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1271 @*/ 1272 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1273 { 1274 DM_Plex *mesh = (DM_Plex*) dm->data; 1275 PetscErrorCode ierr; 1276 1277 PetscFunctionBegin; 1278 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1279 PetscValidPointer(size, 3); 1280 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1281 PetscFunctionReturn(0); 1282 } 1283 1284 /*@ 1285 DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 1286 1287 Not collective 1288 1289 Input Parameters: 1290 + mesh - The DMPlex 1291 . p - The point, which must lie in the chart set with DMPlexSetChart() 1292 - size - The cone size for point p 1293 1294 Output Parameter: 1295 1296 Note: 1297 This should be called after DMPlexSetChart(). 1298 1299 Level: beginner 1300 1301 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1302 @*/ 1303 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1304 { 1305 DM_Plex *mesh = (DM_Plex*) dm->data; 1306 PetscErrorCode ierr; 1307 1308 PetscFunctionBegin; 1309 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1310 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1311 1312 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1313 PetscFunctionReturn(0); 1314 } 1315 1316 /*@ 1317 DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 1318 1319 Not collective 1320 1321 Input Parameters: 1322 + mesh - The DMPlex 1323 . p - The point, which must lie in the chart set with DMPlexSetChart() 1324 - size - The additional cone size for point p 1325 1326 Output Parameter: 1327 1328 Note: 1329 This should be called after DMPlexSetChart(). 1330 1331 Level: beginner 1332 1333 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 1334 @*/ 1335 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 1336 { 1337 DM_Plex *mesh = (DM_Plex*) dm->data; 1338 PetscInt csize; 1339 PetscErrorCode ierr; 1340 1341 PetscFunctionBegin; 1342 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1343 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1344 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 1345 1346 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 1347 PetscFunctionReturn(0); 1348 } 1349 1350 /*@C 1351 DMPlexGetCone - Return the points on the in-edges for this point in the DAG 1352 1353 Not collective 1354 1355 Input Parameters: 1356 + mesh - The DMPlex 1357 - p - The point, which must lie in the chart set with DMPlexSetChart() 1358 1359 Output Parameter: 1360 . cone - An array of points which are on the in-edges for point p 1361 1362 Level: beginner 1363 1364 Fortran Notes: 1365 Since it returns an array, this routine is only available in Fortran 90, and you must 1366 include petsc.h90 in your code. 1367 1368 You must also call DMPlexRestoreCone() after you finish using the returned array. 1369 1370 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1371 @*/ 1372 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1373 { 1374 DM_Plex *mesh = (DM_Plex*) dm->data; 1375 PetscInt off; 1376 PetscErrorCode ierr; 1377 1378 PetscFunctionBegin; 1379 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1380 PetscValidPointer(cone, 3); 1381 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1382 *cone = &mesh->cones[off]; 1383 PetscFunctionReturn(0); 1384 } 1385 1386 /*@ 1387 DMPlexSetCone - Set the points on the in-edges for this point in the DAG 1388 1389 Not collective 1390 1391 Input Parameters: 1392 + mesh - The DMPlex 1393 . p - The point, which must lie in the chart set with DMPlexSetChart() 1394 - cone - An array of points which are on the in-edges for point p 1395 1396 Output Parameter: 1397 1398 Note: 1399 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1400 1401 Level: beginner 1402 1403 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1404 @*/ 1405 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1406 { 1407 DM_Plex *mesh = (DM_Plex*) dm->data; 1408 PetscInt pStart, pEnd; 1409 PetscInt dof, off, c; 1410 PetscErrorCode ierr; 1411 1412 PetscFunctionBegin; 1413 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1414 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1415 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1416 if (dof) PetscValidPointer(cone, 3); 1417 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1418 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1419 for (c = 0; c < dof; ++c) { 1420 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1421 mesh->cones[off+c] = cone[c]; 1422 } 1423 PetscFunctionReturn(0); 1424 } 1425 1426 /*@C 1427 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 1428 1429 Not collective 1430 1431 Input Parameters: 1432 + mesh - The DMPlex 1433 - p - The point, which must lie in the chart set with DMPlexSetChart() 1434 1435 Output Parameter: 1436 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1437 integer giving the prescription for cone traversal. If it is negative, the cone is 1438 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1439 the index of the cone point on which to start. 1440 1441 Level: beginner 1442 1443 Fortran Notes: 1444 Since it returns an array, this routine is only available in Fortran 90, and you must 1445 include petsc.h90 in your code. 1446 1447 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 1448 1449 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1450 @*/ 1451 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1452 { 1453 DM_Plex *mesh = (DM_Plex*) dm->data; 1454 PetscInt off; 1455 PetscErrorCode ierr; 1456 1457 PetscFunctionBegin; 1458 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1459 #if defined(PETSC_USE_DEBUG) 1460 { 1461 PetscInt dof; 1462 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1463 if (dof) PetscValidPointer(coneOrientation, 3); 1464 } 1465 #endif 1466 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1467 1468 *coneOrientation = &mesh->coneOrientations[off]; 1469 PetscFunctionReturn(0); 1470 } 1471 1472 /*@ 1473 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 1474 1475 Not collective 1476 1477 Input Parameters: 1478 + mesh - The DMPlex 1479 . p - The point, which must lie in the chart set with DMPlexSetChart() 1480 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1481 integer giving the prescription for cone traversal. If it is negative, the cone is 1482 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1483 the index of the cone point on which to start. 1484 1485 Output Parameter: 1486 1487 Note: 1488 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1489 1490 Level: beginner 1491 1492 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1493 @*/ 1494 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1495 { 1496 DM_Plex *mesh = (DM_Plex*) dm->data; 1497 PetscInt pStart, pEnd; 1498 PetscInt dof, off, c; 1499 PetscErrorCode ierr; 1500 1501 PetscFunctionBegin; 1502 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1503 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1504 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1505 if (dof) PetscValidPointer(coneOrientation, 3); 1506 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1507 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1508 for (c = 0; c < dof; ++c) { 1509 PetscInt cdof, o = coneOrientation[c]; 1510 1511 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1512 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1513 mesh->coneOrientations[off+c] = o; 1514 } 1515 PetscFunctionReturn(0); 1516 } 1517 1518 /*@ 1519 DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 1520 1521 Not collective 1522 1523 Input Parameters: 1524 + mesh - The DMPlex 1525 . p - The point, which must lie in the chart set with DMPlexSetChart() 1526 . conePos - The local index in the cone where the point should be put 1527 - conePoint - The mesh point to insert 1528 1529 Level: beginner 1530 1531 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1532 @*/ 1533 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1534 { 1535 DM_Plex *mesh = (DM_Plex*) dm->data; 1536 PetscInt pStart, pEnd; 1537 PetscInt dof, off; 1538 PetscErrorCode ierr; 1539 1540 PetscFunctionBegin; 1541 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1542 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1543 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1544 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1545 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1546 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1547 if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1548 mesh->cones[off+conePos] = conePoint; 1549 PetscFunctionReturn(0); 1550 } 1551 1552 /*@ 1553 DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 1554 1555 Not collective 1556 1557 Input Parameters: 1558 + mesh - The DMPlex 1559 . p - The point, which must lie in the chart set with DMPlexSetChart() 1560 . conePos - The local index in the cone where the point should be put 1561 - coneOrientation - The point orientation to insert 1562 1563 Level: beginner 1564 1565 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1566 @*/ 1567 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 1568 { 1569 DM_Plex *mesh = (DM_Plex*) dm->data; 1570 PetscInt pStart, pEnd; 1571 PetscInt dof, off; 1572 PetscErrorCode ierr; 1573 1574 PetscFunctionBegin; 1575 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1576 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1577 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1578 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1579 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1580 if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1581 mesh->coneOrientations[off+conePos] = coneOrientation; 1582 PetscFunctionReturn(0); 1583 } 1584 1585 /*@ 1586 DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 1587 1588 Not collective 1589 1590 Input Parameters: 1591 + mesh - The DMPlex 1592 - p - The point, which must lie in the chart set with DMPlexSetChart() 1593 1594 Output Parameter: 1595 . size - The support size for point p 1596 1597 Level: beginner 1598 1599 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1600 @*/ 1601 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1602 { 1603 DM_Plex *mesh = (DM_Plex*) dm->data; 1604 PetscErrorCode ierr; 1605 1606 PetscFunctionBegin; 1607 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1608 PetscValidPointer(size, 3); 1609 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1610 PetscFunctionReturn(0); 1611 } 1612 1613 /*@ 1614 DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 1615 1616 Not collective 1617 1618 Input Parameters: 1619 + mesh - The DMPlex 1620 . p - The point, which must lie in the chart set with DMPlexSetChart() 1621 - size - The support size for point p 1622 1623 Output Parameter: 1624 1625 Note: 1626 This should be called after DMPlexSetChart(). 1627 1628 Level: beginner 1629 1630 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1631 @*/ 1632 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1633 { 1634 DM_Plex *mesh = (DM_Plex*) dm->data; 1635 PetscErrorCode ierr; 1636 1637 PetscFunctionBegin; 1638 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1639 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1640 1641 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1642 PetscFunctionReturn(0); 1643 } 1644 1645 /*@C 1646 DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 1647 1648 Not collective 1649 1650 Input Parameters: 1651 + mesh - The DMPlex 1652 - p - The point, which must lie in the chart set with DMPlexSetChart() 1653 1654 Output Parameter: 1655 . support - An array of points which are on the out-edges for point p 1656 1657 Level: beginner 1658 1659 Fortran Notes: 1660 Since it returns an array, this routine is only available in Fortran 90, and you must 1661 include petsc.h90 in your code. 1662 1663 You must also call DMPlexRestoreSupport() after you finish using the returned array. 1664 1665 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1666 @*/ 1667 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1668 { 1669 DM_Plex *mesh = (DM_Plex*) dm->data; 1670 PetscInt off; 1671 PetscErrorCode ierr; 1672 1673 PetscFunctionBegin; 1674 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1675 PetscValidPointer(support, 3); 1676 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1677 *support = &mesh->supports[off]; 1678 PetscFunctionReturn(0); 1679 } 1680 1681 /*@ 1682 DMPlexSetSupport - Set the points on the out-edges for this point in the DAG 1683 1684 Not collective 1685 1686 Input Parameters: 1687 + mesh - The DMPlex 1688 . p - The point, which must lie in the chart set with DMPlexSetChart() 1689 - support - An array of points which are on the in-edges for point p 1690 1691 Output Parameter: 1692 1693 Note: 1694 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1695 1696 Level: beginner 1697 1698 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1699 @*/ 1700 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1701 { 1702 DM_Plex *mesh = (DM_Plex*) dm->data; 1703 PetscInt pStart, pEnd; 1704 PetscInt dof, off, c; 1705 PetscErrorCode ierr; 1706 1707 PetscFunctionBegin; 1708 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1709 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1710 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1711 if (dof) PetscValidPointer(support, 3); 1712 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1713 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1714 for (c = 0; c < dof; ++c) { 1715 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1716 mesh->supports[off+c] = support[c]; 1717 } 1718 PetscFunctionReturn(0); 1719 } 1720 1721 /*@ 1722 DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 1723 1724 Not collective 1725 1726 Input Parameters: 1727 + mesh - The DMPlex 1728 . p - The point, which must lie in the chart set with DMPlexSetChart() 1729 . supportPos - The local index in the cone where the point should be put 1730 - supportPoint - The mesh point to insert 1731 1732 Level: beginner 1733 1734 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1735 @*/ 1736 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1737 { 1738 DM_Plex *mesh = (DM_Plex*) dm->data; 1739 PetscInt pStart, pEnd; 1740 PetscInt dof, off; 1741 PetscErrorCode ierr; 1742 1743 PetscFunctionBegin; 1744 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1745 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1746 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1747 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1748 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1749 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1750 if (supportPos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1751 mesh->supports[off+supportPos] = supportPoint; 1752 PetscFunctionReturn(0); 1753 } 1754 1755 /*@C 1756 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 1757 1758 Not collective 1759 1760 Input Parameters: 1761 + mesh - The DMPlex 1762 . p - The point, which must lie in the chart set with DMPlexSetChart() 1763 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1764 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1765 1766 Output Parameters: 1767 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1768 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1769 1770 Note: 1771 If using internal storage (points is NULL on input), each call overwrites the last output. 1772 1773 Fortran Notes: 1774 Since it returns an array, this routine is only available in Fortran 90, and you must 1775 include petsc.h90 in your code. 1776 1777 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1778 1779 Level: beginner 1780 1781 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1782 @*/ 1783 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1784 { 1785 DM_Plex *mesh = (DM_Plex*) dm->data; 1786 PetscInt *closure, *fifo; 1787 const PetscInt *tmp = NULL, *tmpO = NULL; 1788 PetscInt tmpSize, t; 1789 PetscInt depth = 0, maxSize; 1790 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1791 PetscErrorCode ierr; 1792 1793 PetscFunctionBegin; 1794 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1795 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1796 /* This is only 1-level */ 1797 if (useCone) { 1798 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1799 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1800 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1801 } else { 1802 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1803 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1804 } 1805 if (depth == 1) { 1806 if (*points) { 1807 closure = *points; 1808 } else { 1809 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 1810 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 1811 } 1812 closure[0] = p; closure[1] = 0; 1813 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 1814 closure[closureSize] = tmp[t]; 1815 closure[closureSize+1] = tmpO ? tmpO[t] : 0; 1816 } 1817 if (numPoints) *numPoints = closureSize/2; 1818 if (points) *points = closure; 1819 PetscFunctionReturn(0); 1820 } 1821 { 1822 PetscInt c, coneSeries, s,supportSeries; 1823 1824 c = mesh->maxConeSize; 1825 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 1826 s = mesh->maxSupportSize; 1827 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 1828 maxSize = 2*PetscMax(coneSeries,supportSeries); 1829 } 1830 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 1831 if (*points) { 1832 closure = *points; 1833 } else { 1834 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 1835 } 1836 closure[0] = p; closure[1] = 0; 1837 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1838 const PetscInt cp = tmp[t]; 1839 const PetscInt co = tmpO ? tmpO[t] : 0; 1840 1841 closure[closureSize] = cp; 1842 closure[closureSize+1] = co; 1843 fifo[fifoSize] = cp; 1844 fifo[fifoSize+1] = co; 1845 } 1846 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 1847 while (fifoSize - fifoStart) { 1848 const PetscInt q = fifo[fifoStart]; 1849 const PetscInt o = fifo[fifoStart+1]; 1850 const PetscInt rev = o >= 0 ? 0 : 1; 1851 const PetscInt off = rev ? -(o+1) : o; 1852 1853 if (useCone) { 1854 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1855 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1856 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1857 } else { 1858 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1859 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1860 tmpO = NULL; 1861 } 1862 for (t = 0; t < tmpSize; ++t) { 1863 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1864 const PetscInt cp = tmp[i]; 1865 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 1866 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 1867 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 1868 PetscInt co = tmpO ? tmpO[i] : 0; 1869 PetscInt c; 1870 1871 if (rev) { 1872 PetscInt childSize, coff; 1873 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1874 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 1875 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1876 } 1877 /* Check for duplicate */ 1878 for (c = 0; c < closureSize; c += 2) { 1879 if (closure[c] == cp) break; 1880 } 1881 if (c == closureSize) { 1882 closure[closureSize] = cp; 1883 closure[closureSize+1] = co; 1884 fifo[fifoSize] = cp; 1885 fifo[fifoSize+1] = co; 1886 closureSize += 2; 1887 fifoSize += 2; 1888 } 1889 } 1890 fifoStart += 2; 1891 } 1892 if (numPoints) *numPoints = closureSize/2; 1893 if (points) *points = closure; 1894 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 1895 PetscFunctionReturn(0); 1896 } 1897 1898 /*@C 1899 DMPlexGetTransitiveClosure_Internal - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG with a specified initial orientation 1900 1901 Not collective 1902 1903 Input Parameters: 1904 + mesh - The DMPlex 1905 . p - The point, which must lie in the chart set with DMPlexSetChart() 1906 . orientation - The orientation of the point 1907 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1908 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1909 1910 Output Parameters: 1911 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1912 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1913 1914 Note: 1915 If using internal storage (points is NULL on input), each call overwrites the last output. 1916 1917 Fortran Notes: 1918 Since it returns an array, this routine is only available in Fortran 90, and you must 1919 include petsc.h90 in your code. 1920 1921 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1922 1923 Level: beginner 1924 1925 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1926 @*/ 1927 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1928 { 1929 DM_Plex *mesh = (DM_Plex*) dm->data; 1930 PetscInt *closure, *fifo; 1931 const PetscInt *tmp = NULL, *tmpO = NULL; 1932 PetscInt tmpSize, t; 1933 PetscInt depth = 0, maxSize; 1934 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1935 PetscErrorCode ierr; 1936 1937 PetscFunctionBegin; 1938 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1939 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1940 /* This is only 1-level */ 1941 if (useCone) { 1942 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1943 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1944 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1945 } else { 1946 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1947 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1948 } 1949 if (depth == 1) { 1950 if (*points) { 1951 closure = *points; 1952 } else { 1953 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 1954 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 1955 } 1956 closure[0] = p; closure[1] = ornt; 1957 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 1958 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 1959 closure[closureSize] = tmp[i]; 1960 closure[closureSize+1] = tmpO ? tmpO[i] : 0; 1961 } 1962 if (numPoints) *numPoints = closureSize/2; 1963 if (points) *points = closure; 1964 PetscFunctionReturn(0); 1965 } 1966 { 1967 PetscInt c, coneSeries, s,supportSeries; 1968 1969 c = mesh->maxConeSize; 1970 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 1971 s = mesh->maxSupportSize; 1972 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 1973 maxSize = 2*PetscMax(coneSeries,supportSeries); 1974 } 1975 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 1976 if (*points) { 1977 closure = *points; 1978 } else { 1979 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 1980 } 1981 closure[0] = p; closure[1] = ornt; 1982 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1983 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 1984 const PetscInt cp = tmp[i]; 1985 PetscInt co = tmpO ? tmpO[i] : 0; 1986 1987 if (ornt < 0) { 1988 PetscInt childSize, coff; 1989 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1990 coff = co < 0 ? -(tmpO[i]+1) : tmpO[i]; 1991 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1992 } 1993 closure[closureSize] = cp; 1994 closure[closureSize+1] = co; 1995 fifo[fifoSize] = cp; 1996 fifo[fifoSize+1] = co; 1997 } 1998 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 1999 while (fifoSize - fifoStart) { 2000 const PetscInt q = fifo[fifoStart]; 2001 const PetscInt o = fifo[fifoStart+1]; 2002 const PetscInt rev = o >= 0 ? 0 : 1; 2003 const PetscInt off = rev ? -(o+1) : o; 2004 2005 if (useCone) { 2006 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 2007 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 2008 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 2009 } else { 2010 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 2011 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 2012 tmpO = NULL; 2013 } 2014 for (t = 0; t < tmpSize; ++t) { 2015 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 2016 const PetscInt cp = tmp[i]; 2017 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 2018 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 2019 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 2020 PetscInt co = tmpO ? tmpO[i] : 0; 2021 PetscInt c; 2022 2023 if (rev) { 2024 PetscInt childSize, coff; 2025 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 2026 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 2027 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 2028 } 2029 /* Check for duplicate */ 2030 for (c = 0; c < closureSize; c += 2) { 2031 if (closure[c] == cp) break; 2032 } 2033 if (c == closureSize) { 2034 closure[closureSize] = cp; 2035 closure[closureSize+1] = co; 2036 fifo[fifoSize] = cp; 2037 fifo[fifoSize+1] = co; 2038 closureSize += 2; 2039 fifoSize += 2; 2040 } 2041 } 2042 fifoStart += 2; 2043 } 2044 if (numPoints) *numPoints = closureSize/2; 2045 if (points) *points = closure; 2046 ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 2047 PetscFunctionReturn(0); 2048 } 2049 2050 /*@C 2051 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 2052 2053 Not collective 2054 2055 Input Parameters: 2056 + mesh - The DMPlex 2057 . p - The point, which must lie in the chart set with DMPlexSetChart() 2058 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 2059 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit 2060 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit 2061 2062 Note: 2063 If not using internal storage (points is not NULL on input), this call is unnecessary 2064 2065 Fortran Notes: 2066 Since it returns an array, this routine is only available in Fortran 90, and you must 2067 include petsc.h90 in your code. 2068 2069 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2070 2071 Level: beginner 2072 2073 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 2074 @*/ 2075 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 2076 { 2077 PetscErrorCode ierr; 2078 2079 PetscFunctionBegin; 2080 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2081 if (numPoints) PetscValidIntPointer(numPoints,4); 2082 if (points) PetscValidPointer(points,5); 2083 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 2084 if (numPoints) *numPoints = 0; 2085 PetscFunctionReturn(0); 2086 } 2087 2088 /*@ 2089 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 2090 2091 Not collective 2092 2093 Input Parameter: 2094 . mesh - The DMPlex 2095 2096 Output Parameters: 2097 + maxConeSize - The maximum number of in-edges 2098 - maxSupportSize - The maximum number of out-edges 2099 2100 Level: beginner 2101 2102 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2103 @*/ 2104 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 2105 { 2106 DM_Plex *mesh = (DM_Plex*) dm->data; 2107 2108 PetscFunctionBegin; 2109 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2110 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 2111 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 2112 PetscFunctionReturn(0); 2113 } 2114 2115 PetscErrorCode DMSetUp_Plex(DM dm) 2116 { 2117 DM_Plex *mesh = (DM_Plex*) dm->data; 2118 PetscInt size; 2119 PetscErrorCode ierr; 2120 2121 PetscFunctionBegin; 2122 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2123 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 2124 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 2125 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 2126 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 2127 if (mesh->maxSupportSize) { 2128 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 2129 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 2130 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 2131 } 2132 PetscFunctionReturn(0); 2133 } 2134 2135 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 2136 { 2137 PetscErrorCode ierr; 2138 2139 PetscFunctionBegin; 2140 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 2141 ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 2142 PetscFunctionReturn(0); 2143 } 2144 2145 PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 2146 { 2147 PetscErrorCode ierr; 2148 2149 PetscFunctionBegin; 2150 if (superdm) {ierr = DMClone(dms[0], superdm);CHKERRQ(ierr);} 2151 ierr = DMCreateSuperDM_Section_Private(dms, len, is, superdm);CHKERRQ(ierr); 2152 PetscFunctionReturn(0); 2153 } 2154 2155 /*@ 2156 DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 2157 2158 Not collective 2159 2160 Input Parameter: 2161 . mesh - The DMPlex 2162 2163 Output Parameter: 2164 2165 Note: 2166 This should be called after all calls to DMPlexSetCone() 2167 2168 Level: beginner 2169 2170 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 2171 @*/ 2172 PetscErrorCode DMPlexSymmetrize(DM dm) 2173 { 2174 DM_Plex *mesh = (DM_Plex*) dm->data; 2175 PetscInt *offsets; 2176 PetscInt supportSize; 2177 PetscInt pStart, pEnd, p; 2178 PetscErrorCode ierr; 2179 2180 PetscFunctionBegin; 2181 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2182 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 2183 /* Calculate support sizes */ 2184 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2185 for (p = pStart; p < pEnd; ++p) { 2186 PetscInt dof, off, c; 2187 2188 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2189 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2190 for (c = off; c < off+dof; ++c) { 2191 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 2192 } 2193 } 2194 for (p = pStart; p < pEnd; ++p) { 2195 PetscInt dof; 2196 2197 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2198 2199 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 2200 } 2201 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 2202 /* Calculate supports */ 2203 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 2204 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 2205 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 2206 for (p = pStart; p < pEnd; ++p) { 2207 PetscInt dof, off, c; 2208 2209 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2210 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2211 for (c = off; c < off+dof; ++c) { 2212 const PetscInt q = mesh->cones[c]; 2213 PetscInt offS; 2214 2215 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 2216 2217 mesh->supports[offS+offsets[q]] = p; 2218 ++offsets[q]; 2219 } 2220 } 2221 ierr = PetscFree(offsets);CHKERRQ(ierr); 2222 PetscFunctionReturn(0); 2223 } 2224 2225 /*@ 2226 DMPlexStratify - The DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2227 can be illustrated by a Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2228 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2229 the DAG. 2230 2231 Collective on dm 2232 2233 Input Parameter: 2234 . mesh - The DMPlex 2235 2236 Output Parameter: 2237 2238 Notes: 2239 Concretely, DMPlexStratify() creates a new label named "depth" containing the dimension of each element: 0 for vertices, 2240 1 for edges, and so on. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 2241 manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 2242 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 2243 2244 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 2245 2246 Level: beginner 2247 2248 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2249 @*/ 2250 PetscErrorCode DMPlexStratify(DM dm) 2251 { 2252 DM_Plex *mesh = (DM_Plex*) dm->data; 2253 DMLabel label; 2254 PetscInt pStart, pEnd, p; 2255 PetscInt numRoots = 0, numLeaves = 0; 2256 PetscErrorCode ierr; 2257 2258 PetscFunctionBegin; 2259 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2260 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2261 /* Calculate depth */ 2262 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2263 ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 2264 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2265 /* Initialize roots and count leaves */ 2266 for (p = pStart; p < pEnd; ++p) { 2267 PetscInt coneSize, supportSize; 2268 2269 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2270 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2271 if (!coneSize && supportSize) { 2272 ++numRoots; 2273 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 2274 } else if (!supportSize && coneSize) { 2275 ++numLeaves; 2276 } else if (!supportSize && !coneSize) { 2277 /* Isolated points */ 2278 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 2279 } 2280 } 2281 if (numRoots + numLeaves == (pEnd - pStart)) { 2282 for (p = pStart; p < pEnd; ++p) { 2283 PetscInt coneSize, supportSize; 2284 2285 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2286 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2287 if (!supportSize && coneSize) { 2288 ierr = DMLabelSetValue(label, p, 1);CHKERRQ(ierr); 2289 } 2290 } 2291 } else { 2292 IS pointIS; 2293 PetscInt numPoints = 0, level = 0; 2294 2295 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 2296 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 2297 while (numPoints) { 2298 const PetscInt *points; 2299 const PetscInt newLevel = level+1; 2300 2301 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 2302 for (p = 0; p < numPoints; ++p) { 2303 const PetscInt point = points[p]; 2304 const PetscInt *support; 2305 PetscInt supportSize, s; 2306 2307 ierr = DMPlexGetSupportSize(dm, point, &supportSize);CHKERRQ(ierr); 2308 ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 2309 for (s = 0; s < supportSize; ++s) { 2310 ierr = DMLabelSetValue(label, support[s], newLevel);CHKERRQ(ierr); 2311 } 2312 } 2313 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 2314 ++level; 2315 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2316 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 2317 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 2318 else {numPoints = 0;} 2319 } 2320 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2321 } 2322 { /* just in case there is an empty process */ 2323 PetscInt numValues, maxValues = 0, v; 2324 2325 ierr = DMLabelGetNumValues(label,&numValues);CHKERRQ(ierr); 2326 for (v = 0; v < numValues; v++) { 2327 IS pointIS; 2328 2329 ierr = DMLabelGetStratumIS(label, v, &pointIS);CHKERRQ(ierr); 2330 if (pointIS) { 2331 PetscInt min, max, numPoints; 2332 PetscInt start; 2333 PetscBool contig; 2334 2335 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 2336 ierr = ISGetMinMax(pointIS, &min, &max);CHKERRQ(ierr); 2337 ierr = ISContiguousLocal(pointIS,min,max+1,&start,&contig);CHKERRQ(ierr); 2338 if (start == 0 && contig) { 2339 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2340 ierr = ISCreateStride(PETSC_COMM_SELF,numPoints,min,1,&pointIS);CHKERRQ(ierr); 2341 ierr = DMLabelSetStratumIS(label, v, pointIS);CHKERRQ(ierr); 2342 } 2343 } 2344 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2345 } 2346 ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 2347 for (v = numValues; v < maxValues; v++) { 2348 DMLabelAddStratum(label,v);CHKERRQ(ierr); 2349 } 2350 } 2351 2352 ierr = DMLabelGetState(label, &mesh->depthState);CHKERRQ(ierr); 2353 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2354 PetscFunctionReturn(0); 2355 } 2356 2357 /*@C 2358 DMPlexGetJoin - Get an array for the join of the set of points 2359 2360 Not Collective 2361 2362 Input Parameters: 2363 + dm - The DMPlex object 2364 . numPoints - The number of input points for the join 2365 - points - The input points 2366 2367 Output Parameters: 2368 + numCoveredPoints - The number of points in the join 2369 - coveredPoints - The points in the join 2370 2371 Level: intermediate 2372 2373 Note: Currently, this is restricted to a single level join 2374 2375 Fortran Notes: 2376 Since it returns an array, this routine is only available in Fortran 90, and you must 2377 include petsc.h90 in your code. 2378 2379 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2380 2381 .keywords: mesh 2382 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2383 @*/ 2384 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2385 { 2386 DM_Plex *mesh = (DM_Plex*) dm->data; 2387 PetscInt *join[2]; 2388 PetscInt joinSize, i = 0; 2389 PetscInt dof, off, p, c, m; 2390 PetscErrorCode ierr; 2391 2392 PetscFunctionBegin; 2393 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2394 PetscValidPointer(points, 2); 2395 PetscValidPointer(numCoveredPoints, 3); 2396 PetscValidPointer(coveredPoints, 4); 2397 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 2398 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 2399 /* Copy in support of first point */ 2400 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2401 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2402 for (joinSize = 0; joinSize < dof; ++joinSize) { 2403 join[i][joinSize] = mesh->supports[off+joinSize]; 2404 } 2405 /* Check each successive support */ 2406 for (p = 1; p < numPoints; ++p) { 2407 PetscInt newJoinSize = 0; 2408 2409 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2410 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2411 for (c = 0; c < dof; ++c) { 2412 const PetscInt point = mesh->supports[off+c]; 2413 2414 for (m = 0; m < joinSize; ++m) { 2415 if (point == join[i][m]) { 2416 join[1-i][newJoinSize++] = point; 2417 break; 2418 } 2419 } 2420 } 2421 joinSize = newJoinSize; 2422 i = 1-i; 2423 } 2424 *numCoveredPoints = joinSize; 2425 *coveredPoints = join[i]; 2426 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 2427 PetscFunctionReturn(0); 2428 } 2429 2430 /*@C 2431 DMPlexRestoreJoin - Restore an array for the join of the set of points 2432 2433 Not Collective 2434 2435 Input Parameters: 2436 + dm - The DMPlex object 2437 . numPoints - The number of input points for the join 2438 - points - The input points 2439 2440 Output Parameters: 2441 + numCoveredPoints - The number of points in the join 2442 - coveredPoints - The points in the join 2443 2444 Fortran Notes: 2445 Since it returns an array, this routine is only available in Fortran 90, and you must 2446 include petsc.h90 in your code. 2447 2448 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2449 2450 Level: intermediate 2451 2452 .keywords: mesh 2453 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2454 @*/ 2455 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2456 { 2457 PetscErrorCode ierr; 2458 2459 PetscFunctionBegin; 2460 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2461 if (points) PetscValidIntPointer(points,3); 2462 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2463 PetscValidPointer(coveredPoints, 5); 2464 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 2465 if (numCoveredPoints) *numCoveredPoints = 0; 2466 PetscFunctionReturn(0); 2467 } 2468 2469 /*@C 2470 DMPlexGetFullJoin - Get an array for the join of the set of points 2471 2472 Not Collective 2473 2474 Input Parameters: 2475 + dm - The DMPlex object 2476 . numPoints - The number of input points for the join 2477 - points - The input points 2478 2479 Output Parameters: 2480 + numCoveredPoints - The number of points in the join 2481 - coveredPoints - The points in the join 2482 2483 Fortran Notes: 2484 Since it returns an array, this routine is only available in Fortran 90, and you must 2485 include petsc.h90 in your code. 2486 2487 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2488 2489 Level: intermediate 2490 2491 .keywords: mesh 2492 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2493 @*/ 2494 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2495 { 2496 DM_Plex *mesh = (DM_Plex*) dm->data; 2497 PetscInt *offsets, **closures; 2498 PetscInt *join[2]; 2499 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2500 PetscInt p, d, c, m, ms; 2501 PetscErrorCode ierr; 2502 2503 PetscFunctionBegin; 2504 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2505 PetscValidPointer(points, 2); 2506 PetscValidPointer(numCoveredPoints, 3); 2507 PetscValidPointer(coveredPoints, 4); 2508 2509 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2510 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 2511 ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 2512 ms = mesh->maxSupportSize; 2513 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 2514 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 2515 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 2516 2517 for (p = 0; p < numPoints; ++p) { 2518 PetscInt closureSize; 2519 2520 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2521 2522 offsets[p*(depth+2)+0] = 0; 2523 for (d = 0; d < depth+1; ++d) { 2524 PetscInt pStart, pEnd, i; 2525 2526 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2527 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2528 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2529 offsets[p*(depth+2)+d+1] = i; 2530 break; 2531 } 2532 } 2533 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2534 } 2535 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2536 } 2537 for (d = 0; d < depth+1; ++d) { 2538 PetscInt dof; 2539 2540 /* Copy in support of first point */ 2541 dof = offsets[d+1] - offsets[d]; 2542 for (joinSize = 0; joinSize < dof; ++joinSize) { 2543 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2544 } 2545 /* Check each successive cone */ 2546 for (p = 1; p < numPoints && joinSize; ++p) { 2547 PetscInt newJoinSize = 0; 2548 2549 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2550 for (c = 0; c < dof; ++c) { 2551 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2552 2553 for (m = 0; m < joinSize; ++m) { 2554 if (point == join[i][m]) { 2555 join[1-i][newJoinSize++] = point; 2556 break; 2557 } 2558 } 2559 } 2560 joinSize = newJoinSize; 2561 i = 1-i; 2562 } 2563 if (joinSize) break; 2564 } 2565 *numCoveredPoints = joinSize; 2566 *coveredPoints = join[i]; 2567 for (p = 0; p < numPoints; ++p) { 2568 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2569 } 2570 ierr = PetscFree(closures);CHKERRQ(ierr); 2571 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 2572 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 2573 PetscFunctionReturn(0); 2574 } 2575 2576 /*@C 2577 DMPlexGetMeet - Get an array for the meet of the set of points 2578 2579 Not Collective 2580 2581 Input Parameters: 2582 + dm - The DMPlex object 2583 . numPoints - The number of input points for the meet 2584 - points - The input points 2585 2586 Output Parameters: 2587 + numCoveredPoints - The number of points in the meet 2588 - coveredPoints - The points in the meet 2589 2590 Level: intermediate 2591 2592 Note: Currently, this is restricted to a single level meet 2593 2594 Fortran Notes: 2595 Since it returns an array, this routine is only available in Fortran 90, and you must 2596 include petsc.h90 in your code. 2597 2598 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2599 2600 .keywords: mesh 2601 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2602 @*/ 2603 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2604 { 2605 DM_Plex *mesh = (DM_Plex*) dm->data; 2606 PetscInt *meet[2]; 2607 PetscInt meetSize, i = 0; 2608 PetscInt dof, off, p, c, m; 2609 PetscErrorCode ierr; 2610 2611 PetscFunctionBegin; 2612 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2613 PetscValidPointer(points, 2); 2614 PetscValidPointer(numCoveringPoints, 3); 2615 PetscValidPointer(coveringPoints, 4); 2616 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 2617 ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 2618 /* Copy in cone of first point */ 2619 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2620 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2621 for (meetSize = 0; meetSize < dof; ++meetSize) { 2622 meet[i][meetSize] = mesh->cones[off+meetSize]; 2623 } 2624 /* Check each successive cone */ 2625 for (p = 1; p < numPoints; ++p) { 2626 PetscInt newMeetSize = 0; 2627 2628 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2629 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2630 for (c = 0; c < dof; ++c) { 2631 const PetscInt point = mesh->cones[off+c]; 2632 2633 for (m = 0; m < meetSize; ++m) { 2634 if (point == meet[i][m]) { 2635 meet[1-i][newMeetSize++] = point; 2636 break; 2637 } 2638 } 2639 } 2640 meetSize = newMeetSize; 2641 i = 1-i; 2642 } 2643 *numCoveringPoints = meetSize; 2644 *coveringPoints = meet[i]; 2645 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 2646 PetscFunctionReturn(0); 2647 } 2648 2649 /*@C 2650 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2651 2652 Not Collective 2653 2654 Input Parameters: 2655 + dm - The DMPlex object 2656 . numPoints - The number of input points for the meet 2657 - points - The input points 2658 2659 Output Parameters: 2660 + numCoveredPoints - The number of points in the meet 2661 - coveredPoints - The points in the meet 2662 2663 Level: intermediate 2664 2665 Fortran Notes: 2666 Since it returns an array, this routine is only available in Fortran 90, and you must 2667 include petsc.h90 in your code. 2668 2669 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2670 2671 .keywords: mesh 2672 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2673 @*/ 2674 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2675 { 2676 PetscErrorCode ierr; 2677 2678 PetscFunctionBegin; 2679 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2680 if (points) PetscValidIntPointer(points,3); 2681 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2682 PetscValidPointer(coveredPoints,5); 2683 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 2684 if (numCoveredPoints) *numCoveredPoints = 0; 2685 PetscFunctionReturn(0); 2686 } 2687 2688 /*@C 2689 DMPlexGetFullMeet - Get an array for the meet of the set of points 2690 2691 Not Collective 2692 2693 Input Parameters: 2694 + dm - The DMPlex object 2695 . numPoints - The number of input points for the meet 2696 - points - The input points 2697 2698 Output Parameters: 2699 + numCoveredPoints - The number of points in the meet 2700 - coveredPoints - The points in the meet 2701 2702 Level: intermediate 2703 2704 Fortran Notes: 2705 Since it returns an array, this routine is only available in Fortran 90, and you must 2706 include petsc.h90 in your code. 2707 2708 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2709 2710 .keywords: mesh 2711 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2712 @*/ 2713 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2714 { 2715 DM_Plex *mesh = (DM_Plex*) dm->data; 2716 PetscInt *offsets, **closures; 2717 PetscInt *meet[2]; 2718 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2719 PetscInt p, h, c, m, mc; 2720 PetscErrorCode ierr; 2721 2722 PetscFunctionBegin; 2723 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2724 PetscValidPointer(points, 2); 2725 PetscValidPointer(numCoveredPoints, 3); 2726 PetscValidPointer(coveredPoints, 4); 2727 2728 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2729 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 2730 ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 2731 mc = mesh->maxConeSize; 2732 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 2733 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 2734 ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 2735 2736 for (p = 0; p < numPoints; ++p) { 2737 PetscInt closureSize; 2738 2739 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2740 2741 offsets[p*(height+2)+0] = 0; 2742 for (h = 0; h < height+1; ++h) { 2743 PetscInt pStart, pEnd, i; 2744 2745 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2746 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2747 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2748 offsets[p*(height+2)+h+1] = i; 2749 break; 2750 } 2751 } 2752 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2753 } 2754 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2755 } 2756 for (h = 0; h < height+1; ++h) { 2757 PetscInt dof; 2758 2759 /* Copy in cone of first point */ 2760 dof = offsets[h+1] - offsets[h]; 2761 for (meetSize = 0; meetSize < dof; ++meetSize) { 2762 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2763 } 2764 /* Check each successive cone */ 2765 for (p = 1; p < numPoints && meetSize; ++p) { 2766 PetscInt newMeetSize = 0; 2767 2768 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2769 for (c = 0; c < dof; ++c) { 2770 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2771 2772 for (m = 0; m < meetSize; ++m) { 2773 if (point == meet[i][m]) { 2774 meet[1-i][newMeetSize++] = point; 2775 break; 2776 } 2777 } 2778 } 2779 meetSize = newMeetSize; 2780 i = 1-i; 2781 } 2782 if (meetSize) break; 2783 } 2784 *numCoveredPoints = meetSize; 2785 *coveredPoints = meet[i]; 2786 for (p = 0; p < numPoints; ++p) { 2787 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2788 } 2789 ierr = PetscFree(closures);CHKERRQ(ierr); 2790 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 2791 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 2792 PetscFunctionReturn(0); 2793 } 2794 2795 /*@C 2796 DMPlexEqual - Determine if two DMs have the same topology 2797 2798 Not Collective 2799 2800 Input Parameters: 2801 + dmA - A DMPlex object 2802 - dmB - A DMPlex object 2803 2804 Output Parameters: 2805 . equal - PETSC_TRUE if the topologies are identical 2806 2807 Level: intermediate 2808 2809 Notes: 2810 We are not solving graph isomorphism, so we do not permutation. 2811 2812 .keywords: mesh 2813 .seealso: DMPlexGetCone() 2814 @*/ 2815 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 2816 { 2817 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 2818 PetscErrorCode ierr; 2819 2820 PetscFunctionBegin; 2821 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 2822 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 2823 PetscValidPointer(equal, 3); 2824 2825 *equal = PETSC_FALSE; 2826 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 2827 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 2828 if (depth != depthB) PetscFunctionReturn(0); 2829 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 2830 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 2831 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 2832 for (p = pStart; p < pEnd; ++p) { 2833 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 2834 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 2835 2836 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 2837 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 2838 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 2839 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 2840 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 2841 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 2842 if (coneSize != coneSizeB) PetscFunctionReturn(0); 2843 for (c = 0; c < coneSize; ++c) { 2844 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 2845 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 2846 } 2847 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 2848 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 2849 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 2850 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 2851 if (supportSize != supportSizeB) PetscFunctionReturn(0); 2852 for (s = 0; s < supportSize; ++s) { 2853 if (support[s] != supportB[s]) PetscFunctionReturn(0); 2854 } 2855 } 2856 *equal = PETSC_TRUE; 2857 PetscFunctionReturn(0); 2858 } 2859 2860 /*@C 2861 DMPlexGetNumFaceVertices - Returns the number of vertices on a face 2862 2863 Not Collective 2864 2865 Input Parameters: 2866 + dm - The DMPlex 2867 . cellDim - The cell dimension 2868 - numCorners - The number of vertices on a cell 2869 2870 Output Parameters: 2871 . numFaceVertices - The number of vertices on a face 2872 2873 Level: developer 2874 2875 Notes: 2876 Of course this can only work for a restricted set of symmetric shapes 2877 2878 .seealso: DMPlexGetCone() 2879 @*/ 2880 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 2881 { 2882 MPI_Comm comm; 2883 PetscErrorCode ierr; 2884 2885 PetscFunctionBegin; 2886 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2887 PetscValidPointer(numFaceVertices,3); 2888 switch (cellDim) { 2889 case 0: 2890 *numFaceVertices = 0; 2891 break; 2892 case 1: 2893 *numFaceVertices = 1; 2894 break; 2895 case 2: 2896 switch (numCorners) { 2897 case 3: /* triangle */ 2898 *numFaceVertices = 2; /* Edge has 2 vertices */ 2899 break; 2900 case 4: /* quadrilateral */ 2901 *numFaceVertices = 2; /* Edge has 2 vertices */ 2902 break; 2903 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2904 *numFaceVertices = 3; /* Edge has 3 vertices */ 2905 break; 2906 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2907 *numFaceVertices = 3; /* Edge has 3 vertices */ 2908 break; 2909 default: 2910 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 2911 } 2912 break; 2913 case 3: 2914 switch (numCorners) { 2915 case 4: /* tetradehdron */ 2916 *numFaceVertices = 3; /* Face has 3 vertices */ 2917 break; 2918 case 6: /* tet cohesive cells */ 2919 *numFaceVertices = 4; /* Face has 4 vertices */ 2920 break; 2921 case 8: /* hexahedron */ 2922 *numFaceVertices = 4; /* Face has 4 vertices */ 2923 break; 2924 case 9: /* tet cohesive Lagrange cells */ 2925 *numFaceVertices = 6; /* Face has 6 vertices */ 2926 break; 2927 case 10: /* quadratic tetrahedron */ 2928 *numFaceVertices = 6; /* Face has 6 vertices */ 2929 break; 2930 case 12: /* hex cohesive Lagrange cells */ 2931 *numFaceVertices = 6; /* Face has 6 vertices */ 2932 break; 2933 case 18: /* quadratic tet cohesive Lagrange cells */ 2934 *numFaceVertices = 6; /* Face has 6 vertices */ 2935 break; 2936 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2937 *numFaceVertices = 9; /* Face has 9 vertices */ 2938 break; 2939 default: 2940 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 2941 } 2942 break; 2943 default: 2944 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 2945 } 2946 PetscFunctionReturn(0); 2947 } 2948 2949 /*@ 2950 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 2951 2952 Not Collective 2953 2954 Input Parameter: 2955 . dm - The DMPlex object 2956 2957 Output Parameter: 2958 . depthLabel - The DMLabel recording point depth 2959 2960 Level: developer 2961 2962 .keywords: mesh, points 2963 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2964 @*/ 2965 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 2966 { 2967 PetscErrorCode ierr; 2968 2969 PetscFunctionBegin; 2970 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2971 PetscValidPointer(depthLabel, 2); 2972 if (!dm->depthLabel) {ierr = DMGetLabel(dm, "depth", &dm->depthLabel);CHKERRQ(ierr);} 2973 *depthLabel = dm->depthLabel; 2974 PetscFunctionReturn(0); 2975 } 2976 2977 /*@ 2978 DMPlexGetDepth - Get the depth of the DAG representing this mesh 2979 2980 Not Collective 2981 2982 Input Parameter: 2983 . dm - The DMPlex object 2984 2985 Output Parameter: 2986 . depth - The number of strata (breadth first levels) in the DAG 2987 2988 Level: developer 2989 2990 .keywords: mesh, points 2991 .seealso: DMPlexGetDepthLabel(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2992 @*/ 2993 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 2994 { 2995 DMLabel label; 2996 PetscInt d = 0; 2997 PetscErrorCode ierr; 2998 2999 PetscFunctionBegin; 3000 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3001 PetscValidPointer(depth, 2); 3002 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3003 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 3004 *depth = d-1; 3005 PetscFunctionReturn(0); 3006 } 3007 3008 /*@ 3009 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 3010 3011 Not Collective 3012 3013 Input Parameters: 3014 + dm - The DMPlex object 3015 - stratumValue - The requested depth 3016 3017 Output Parameters: 3018 + start - The first point at this depth 3019 - end - One beyond the last point at this depth 3020 3021 Level: developer 3022 3023 .keywords: mesh, points 3024 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 3025 @*/ 3026 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 3027 { 3028 DMLabel label; 3029 PetscInt pStart, pEnd; 3030 PetscErrorCode ierr; 3031 3032 PetscFunctionBegin; 3033 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3034 if (start) {PetscValidPointer(start, 3); *start = 0;} 3035 if (end) {PetscValidPointer(end, 4); *end = 0;} 3036 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3037 if (pStart == pEnd) PetscFunctionReturn(0); 3038 if (stratumValue < 0) { 3039 if (start) *start = pStart; 3040 if (end) *end = pEnd; 3041 PetscFunctionReturn(0); 3042 } 3043 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3044 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 3045 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 3046 PetscFunctionReturn(0); 3047 } 3048 3049 /*@ 3050 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 3051 3052 Not Collective 3053 3054 Input Parameters: 3055 + dm - The DMPlex object 3056 - stratumValue - The requested height 3057 3058 Output Parameters: 3059 + start - The first point at this height 3060 - end - One beyond the last point at this height 3061 3062 Level: developer 3063 3064 .keywords: mesh, points 3065 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 3066 @*/ 3067 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 3068 { 3069 DMLabel label; 3070 PetscInt depth, pStart, pEnd; 3071 PetscErrorCode ierr; 3072 3073 PetscFunctionBegin; 3074 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3075 if (start) {PetscValidPointer(start, 3); *start = 0;} 3076 if (end) {PetscValidPointer(end, 4); *end = 0;} 3077 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3078 if (pStart == pEnd) PetscFunctionReturn(0); 3079 if (stratumValue < 0) { 3080 if (start) *start = pStart; 3081 if (end) *end = pEnd; 3082 PetscFunctionReturn(0); 3083 } 3084 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3085 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 3086 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 3087 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 3088 PetscFunctionReturn(0); 3089 } 3090 3091 /* Set the number of dof on each point and separate by fields */ 3092 static PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 3093 { 3094 PetscInt *pMax; 3095 PetscInt depth, cellHeight, pStart = 0, pEnd = 0; 3096 PetscInt Nf, p, d, dep, f; 3097 PetscBool *isFE; 3098 PetscErrorCode ierr; 3099 3100 PetscFunctionBegin; 3101 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 3102 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 3103 for (f = 0; f < numFields; ++f) { 3104 PetscObject obj; 3105 PetscClassId id; 3106 3107 isFE[f] = PETSC_FALSE; 3108 if (f >= Nf) continue; 3109 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 3110 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 3111 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 3112 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 3113 } 3114 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 3115 if (numFields > 0) { 3116 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 3117 if (numComp) { 3118 for (f = 0; f < numFields; ++f) { 3119 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 3120 if (isFE[f]) { 3121 PetscFE fe; 3122 PetscDualSpace dspace; 3123 const PetscInt ***perms; 3124 const PetscScalar ***flips; 3125 const PetscInt *numDof; 3126 3127 ierr = DMGetField(dm,f,(PetscObject *) &fe);CHKERRQ(ierr); 3128 ierr = PetscFEGetDualSpace(fe,&dspace);CHKERRQ(ierr); 3129 ierr = PetscDualSpaceGetSymmetries(dspace,&perms,&flips);CHKERRQ(ierr); 3130 ierr = PetscDualSpaceGetNumDof(dspace,&numDof);CHKERRQ(ierr); 3131 if (perms || flips) { 3132 DM K; 3133 DMLabel depthLabel; 3134 PetscInt depth, h; 3135 PetscSectionSym sym; 3136 3137 ierr = PetscDualSpaceGetDM(dspace,&K);CHKERRQ(ierr); 3138 ierr = DMPlexGetDepthLabel(dm,&depthLabel);CHKERRQ(ierr); 3139 ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 3140 ierr = PetscSectionSymCreateLabel(PetscObjectComm((PetscObject)*section),depthLabel,&sym);CHKERRQ(ierr); 3141 for (h = 0; h <= depth; h++) { 3142 PetscDualSpace hspace; 3143 PetscInt kStart, kEnd; 3144 PetscInt kConeSize; 3145 const PetscInt **perms0 = NULL; 3146 const PetscScalar **flips0 = NULL; 3147 3148 ierr = PetscDualSpaceGetHeightSubspace(dspace,h,&hspace);CHKERRQ(ierr); 3149 ierr = DMPlexGetHeightStratum(K,h,&kStart,&kEnd);CHKERRQ(ierr); 3150 if (!hspace) continue; 3151 ierr = PetscDualSpaceGetSymmetries(hspace,&perms,&flips);CHKERRQ(ierr); 3152 if (perms) perms0 = perms[0]; 3153 if (flips) flips0 = flips[0]; 3154 if (!(perms0 || flips0)) continue; 3155 ierr = DMPlexGetConeSize(K,kStart,&kConeSize);CHKERRQ(ierr); 3156 ierr = PetscSectionSymLabelSetStratum(sym,depth - h,numDof[depth - h],-kConeSize,kConeSize,PETSC_USE_POINTER,perms0 ? &perms0[-kConeSize] : NULL,flips0 ? &flips0[-kConeSize] : NULL);CHKERRQ(ierr); 3157 } 3158 ierr = PetscSectionSetFieldSym(*section,f,sym);CHKERRQ(ierr); 3159 ierr = PetscSectionSymDestroy(&sym);CHKERRQ(ierr); 3160 } 3161 } 3162 } 3163 } 3164 } 3165 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3166 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 3167 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3168 ierr = PetscMalloc1(depth+1,&pMax);CHKERRQ(ierr); 3169 ierr = DMPlexGetHybridBounds(dm, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 3170 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 3171 for (dep = 0; dep <= depth - cellHeight; ++dep) { 3172 d = dim == depth ? dep : (!dep ? 0 : dim); 3173 ierr = DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd);CHKERRQ(ierr); 3174 pMax[dep] = pMax[dep] < 0 ? pEnd : pMax[dep]; 3175 for (p = pStart; p < pEnd; ++p) { 3176 PetscInt tot = 0; 3177 3178 for (f = 0; f < numFields; ++f) { 3179 if (isFE[f] && p >= pMax[dep]) continue; 3180 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 3181 tot += numDof[f*(dim+1)+d]; 3182 } 3183 ierr = PetscSectionSetDof(*section, p, tot);CHKERRQ(ierr); 3184 } 3185 } 3186 ierr = PetscFree(pMax);CHKERRQ(ierr); 3187 ierr = PetscFree(isFE);CHKERRQ(ierr); 3188 PetscFunctionReturn(0); 3189 } 3190 3191 /* Set the number of dof on each point and separate by fields 3192 If bcComps is NULL or the IS is NULL, constrain every dof on the point 3193 */ 3194 static PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 3195 { 3196 PetscInt numFields; 3197 PetscInt bc; 3198 PetscSection aSec; 3199 PetscErrorCode ierr; 3200 3201 PetscFunctionBegin; 3202 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3203 for (bc = 0; bc < numBC; ++bc) { 3204 PetscInt field = 0; 3205 const PetscInt *comp; 3206 const PetscInt *idx; 3207 PetscInt Nc = -1, n, i; 3208 3209 if (numFields) field = bcField[bc]; 3210 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 3211 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3212 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 3213 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3214 for (i = 0; i < n; ++i) { 3215 const PetscInt p = idx[i]; 3216 PetscInt numConst; 3217 3218 if (numFields) { 3219 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 3220 } else { 3221 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 3222 } 3223 /* If Nc < 0, constrain every dof on the point */ 3224 if (Nc > 0) numConst = PetscMin(numConst, Nc); 3225 if (numFields) {ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr);} 3226 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 3227 } 3228 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3229 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3230 } 3231 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3232 if (aSec) { 3233 PetscInt aStart, aEnd, a; 3234 3235 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3236 for (a = aStart; a < aEnd; a++) { 3237 PetscInt dof, f; 3238 3239 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3240 if (dof) { 3241 /* if there are point-to-point constraints, then all dofs are constrained */ 3242 ierr = PetscSectionGetDof(section, a, &dof);CHKERRQ(ierr); 3243 ierr = PetscSectionSetConstraintDof(section, a, dof);CHKERRQ(ierr); 3244 for (f = 0; f < numFields; f++) { 3245 ierr = PetscSectionGetFieldDof(section, a, f, &dof);CHKERRQ(ierr); 3246 ierr = PetscSectionSetFieldConstraintDof(section, a, f, dof);CHKERRQ(ierr); 3247 } 3248 } 3249 } 3250 } 3251 PetscFunctionReturn(0); 3252 } 3253 3254 /* Set the constrained field indices on each point 3255 If bcComps is NULL or the IS is NULL, constrain every dof on the point 3256 */ 3257 static PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt numBC,const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 3258 { 3259 PetscSection aSec; 3260 PetscInt *indices; 3261 PetscInt numFields, cdof, maxDof = 0, pStart, pEnd, p, bc, f, d; 3262 PetscErrorCode ierr; 3263 3264 PetscFunctionBegin; 3265 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3266 if (!numFields) PetscFunctionReturn(0); 3267 /* Initialize all field indices to -1 */ 3268 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3269 for (p = pStart; p < pEnd; ++p) {ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); maxDof = PetscMax(maxDof, cdof);} 3270 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3271 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3272 for (p = pStart; p < pEnd; ++p) for (f = 0; f < numFields; ++f) {ierr = PetscSectionSetFieldConstraintIndices(section, p, f, indices);CHKERRQ(ierr);} 3273 /* Handle BC constraints */ 3274 for (bc = 0; bc < numBC; ++bc) { 3275 const PetscInt field = bcField[bc]; 3276 const PetscInt *comp, *idx; 3277 PetscInt Nc = -1, n, i; 3278 3279 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 3280 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3281 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 3282 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3283 for (i = 0; i < n; ++i) { 3284 const PetscInt p = idx[i]; 3285 const PetscInt *find; 3286 PetscInt fdof, fcdof, c; 3287 3288 ierr = PetscSectionGetFieldDof(section, p, field, &fdof);CHKERRQ(ierr); 3289 if (!fdof) continue; 3290 if (Nc < 0) { 3291 for (d = 0; d < fdof; ++d) indices[d] = d; 3292 fcdof = fdof; 3293 } else { 3294 ierr = PetscSectionGetFieldConstraintDof(section, p, field, &fcdof);CHKERRQ(ierr); 3295 ierr = PetscSectionGetFieldConstraintIndices(section, p, field, &find);CHKERRQ(ierr); 3296 for (d = 0; d < fcdof; ++d) {if (find[d] < 0) break; indices[d] = find[d];} 3297 for (c = 0; c < Nc; ++c) indices[d++] = comp[c]; 3298 ierr = PetscSortRemoveDupsInt(&d, indices);CHKERRQ(ierr); 3299 for (c = d; c < fcdof; ++c) indices[c] = -1; 3300 fcdof = d; 3301 } 3302 ierr = PetscSectionSetFieldConstraintDof(section, p, field, fcdof);CHKERRQ(ierr); 3303 ierr = PetscSectionSetFieldConstraintIndices(section, p, field, indices);CHKERRQ(ierr); 3304 } 3305 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3306 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3307 } 3308 /* Handle anchors */ 3309 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3310 if (aSec) { 3311 PetscInt aStart, aEnd, a; 3312 3313 for (d = 0; d < maxDof; ++d) indices[d] = d; 3314 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3315 for (a = aStart; a < aEnd; a++) { 3316 PetscInt dof, f; 3317 3318 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3319 if (dof) { 3320 /* if there are point-to-point constraints, then all dofs are constrained */ 3321 for (f = 0; f < numFields; f++) { 3322 ierr = PetscSectionSetFieldConstraintIndices(section, a, f, indices);CHKERRQ(ierr); 3323 } 3324 } 3325 } 3326 } 3327 ierr = PetscFree(indices);CHKERRQ(ierr); 3328 PetscFunctionReturn(0); 3329 } 3330 3331 /* Set the constrained indices on each point */ 3332 static PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 3333 { 3334 PetscInt *indices; 3335 PetscInt numFields, maxDof, pStart, pEnd, p, f, d; 3336 PetscErrorCode ierr; 3337 3338 PetscFunctionBegin; 3339 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3340 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 3341 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3342 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3343 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3344 for (p = pStart; p < pEnd; ++p) { 3345 PetscInt cdof, d; 3346 3347 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 3348 if (cdof) { 3349 if (numFields) { 3350 PetscInt numConst = 0, foff = 0; 3351 3352 for (f = 0; f < numFields; ++f) { 3353 const PetscInt *find; 3354 PetscInt fcdof, fdof; 3355 3356 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 3357 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 3358 /* Change constraint numbering from field component to local dof number */ 3359 ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &find);CHKERRQ(ierr); 3360 for (d = 0; d < fcdof; ++d) indices[numConst+d] = find[d] + foff; 3361 numConst += fcdof; 3362 foff += fdof; 3363 } 3364 if (cdof != numConst) {ierr = PetscSectionSetConstraintDof(section, p, numConst);CHKERRQ(ierr);} 3365 } else { 3366 for (d = 0; d < cdof; ++d) indices[d] = d; 3367 } 3368 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 3369 } 3370 } 3371 ierr = PetscFree(indices);CHKERRQ(ierr); 3372 PetscFunctionReturn(0); 3373 } 3374 3375 /*@C 3376 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 3377 3378 Not Collective 3379 3380 Input Parameters: 3381 + dm - The DMPlex object 3382 . dim - The spatial dimension of the problem 3383 . numFields - The number of fields in the problem 3384 . numComp - An array of size numFields that holds the number of components for each field 3385 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 3386 . numBC - The number of boundary conditions 3387 . bcField - An array of size numBC giving the field number for each boundry condition 3388 . bcComps - [Optional] An array of size numBC giving an IS holding the field components to which each boundary condition applies 3389 . bcPoints - An array of size numBC giving an IS holding the Plex points to which each boundary condition applies 3390 - perm - Optional permutation of the chart, or NULL 3391 3392 Output Parameter: 3393 . section - The PetscSection object 3394 3395 Notes: numDof[f*(dim+1)+d] gives the number of dof for field f on points of dimension d. For instance, numDof[1] is the 3396 number of dof for field 0 on each edge. 3397 3398 The chart permutation is the same one set using PetscSectionSetPermutation() 3399 3400 Level: developer 3401 3402 Fortran Notes: 3403 A Fortran 90 version is available as DMPlexCreateSectionF90() 3404 3405 .keywords: mesh, elements 3406 .seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation() 3407 @*/ 3408 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], IS perm, PetscSection *section) 3409 { 3410 PetscSection aSec; 3411 PetscErrorCode ierr; 3412 3413 PetscFunctionBegin; 3414 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 3415 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3416 if (perm) {ierr = PetscSectionSetPermutation(*section, perm);CHKERRQ(ierr);} 3417 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3418 ierr = DMPlexGetAnchors(dm,&aSec,NULL);CHKERRQ(ierr); 3419 if (numBC || aSec) { 3420 ierr = DMPlexCreateSectionBCIndicesField(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3421 ierr = DMPlexCreateSectionBCIndices(dm, *section);CHKERRQ(ierr); 3422 } 3423 ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr); 3424 PetscFunctionReturn(0); 3425 } 3426 3427 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 3428 { 3429 PetscSection section, s; 3430 Mat m; 3431 PetscInt maxHeight; 3432 PetscErrorCode ierr; 3433 3434 PetscFunctionBegin; 3435 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 3436 ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 3437 ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 3438 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 3439 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 3440 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3441 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 3442 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 3443 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 3444 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 3445 ierr = MatDestroy(&m);CHKERRQ(ierr); 3446 PetscFunctionReturn(0); 3447 } 3448 3449 /*@C 3450 DMPlexGetConeSection - Return a section which describes the layout of cone data 3451 3452 Not Collective 3453 3454 Input Parameters: 3455 . dm - The DMPlex object 3456 3457 Output Parameter: 3458 . section - The PetscSection object 3459 3460 Level: developer 3461 3462 .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 3463 @*/ 3464 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 3465 { 3466 DM_Plex *mesh = (DM_Plex*) dm->data; 3467 3468 PetscFunctionBegin; 3469 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3470 if (section) *section = mesh->coneSection; 3471 PetscFunctionReturn(0); 3472 } 3473 3474 /*@C 3475 DMPlexGetSupportSection - Return a section which describes the layout of support data 3476 3477 Not Collective 3478 3479 Input Parameters: 3480 . dm - The DMPlex object 3481 3482 Output Parameter: 3483 . section - The PetscSection object 3484 3485 Level: developer 3486 3487 .seealso: DMPlexGetConeSection() 3488 @*/ 3489 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 3490 { 3491 DM_Plex *mesh = (DM_Plex*) dm->data; 3492 3493 PetscFunctionBegin; 3494 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3495 if (section) *section = mesh->supportSection; 3496 PetscFunctionReturn(0); 3497 } 3498 3499 /*@C 3500 DMPlexGetCones - Return cone data 3501 3502 Not Collective 3503 3504 Input Parameters: 3505 . dm - The DMPlex object 3506 3507 Output Parameter: 3508 . cones - The cone for each point 3509 3510 Level: developer 3511 3512 .seealso: DMPlexGetConeSection() 3513 @*/ 3514 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 3515 { 3516 DM_Plex *mesh = (DM_Plex*) dm->data; 3517 3518 PetscFunctionBegin; 3519 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3520 if (cones) *cones = mesh->cones; 3521 PetscFunctionReturn(0); 3522 } 3523 3524 /*@C 3525 DMPlexGetConeOrientations - Return cone orientation data 3526 3527 Not Collective 3528 3529 Input Parameters: 3530 . dm - The DMPlex object 3531 3532 Output Parameter: 3533 . coneOrientations - The cone orientation for each point 3534 3535 Level: developer 3536 3537 .seealso: DMPlexGetConeSection() 3538 @*/ 3539 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 3540 { 3541 DM_Plex *mesh = (DM_Plex*) dm->data; 3542 3543 PetscFunctionBegin; 3544 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3545 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 3546 PetscFunctionReturn(0); 3547 } 3548 3549 /******************************** FEM Support **********************************/ 3550 3551 PetscErrorCode DMPlexCreateSpectralClosurePermutation(DM dm, PetscInt point, PetscSection section) 3552 { 3553 DMLabel label; 3554 PetscInt *perm; 3555 PetscInt dim, depth, eStart, k, Nf, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 3556 PetscErrorCode ierr; 3557 3558 PetscFunctionBegin; 3559 if (point < 0) {ierr = DMPlexGetDepthStratum(dm, 1, &point, NULL);CHKERRQ(ierr);} 3560 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3561 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3562 ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); 3563 if (depth == 1) {eStart = point;} 3564 else if (depth == dim) { 3565 const PetscInt *cone; 3566 3567 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3568 eStart = cone[0]; 3569 } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering", point, depth); 3570 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3571 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 3572 if (dim <= 1) PetscFunctionReturn(0); 3573 for (f = 0; f < Nf; ++f) { 3574 /* An order k SEM disc has k-1 dofs on an edge */ 3575 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3576 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3577 k = k/Nc + 1; 3578 size += PetscPowInt(k+1, dim)*Nc; 3579 } 3580 ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 3581 for (f = 0; f < Nf; ++f) { 3582 switch (dim) { 3583 case 2: 3584 /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 3585 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3586 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3587 k = k/Nc + 1; 3588 /* The SEM order is 3589 3590 v_lb, {e_b}, v_rb, 3591 e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 3592 v_lt, reverse {e_t}, v_rt 3593 */ 3594 { 3595 const PetscInt of = 0; 3596 const PetscInt oeb = of + PetscSqr(k-1); 3597 const PetscInt oer = oeb + (k-1); 3598 const PetscInt oet = oer + (k-1); 3599 const PetscInt oel = oet + (k-1); 3600 const PetscInt ovlb = oel + (k-1); 3601 const PetscInt ovrb = ovlb + 1; 3602 const PetscInt ovrt = ovrb + 1; 3603 const PetscInt ovlt = ovrt + 1; 3604 PetscInt o; 3605 3606 /* bottom */ 3607 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 3608 for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3609 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 3610 /* middle */ 3611 for (i = 0; i < k-1; ++i) { 3612 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 3613 for (o = of+(k-1)*i; o < of+(k-1)*(i+1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3614 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 3615 } 3616 /* top */ 3617 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 3618 for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3619 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 3620 foffset = offset; 3621 } 3622 break; 3623 case 3: 3624 /* The original hex closure is 3625 3626 {c, 3627 f_b, f_t, f_f, f_b, f_r, f_l, 3628 e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 3629 v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 3630 */ 3631 ierr = PetscSectionGetFieldDof(section, eStart, f, &k);CHKERRQ(ierr); 3632 ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 3633 k = k/Nc + 1; 3634 /* The SEM order is 3635 Bottom Slice 3636 v_blf, {e^{(k-1)-n}_bf}, v_brf, 3637 e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 3638 v_blb, {e_bb}, v_brb, 3639 3640 Middle Slice (j) 3641 {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 3642 f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 3643 e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 3644 3645 Top Slice 3646 v_tlf, {e_tf}, v_trf, 3647 e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 3648 v_tlb, {e^{(k-1)-n}_tb}, v_trb, 3649 */ 3650 { 3651 const PetscInt oc = 0; 3652 const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 3653 const PetscInt oft = ofb + PetscSqr(k-1); 3654 const PetscInt off = oft + PetscSqr(k-1); 3655 const PetscInt ofk = off + PetscSqr(k-1); 3656 const PetscInt ofr = ofk + PetscSqr(k-1); 3657 const PetscInt ofl = ofr + PetscSqr(k-1); 3658 const PetscInt oebl = ofl + PetscSqr(k-1); 3659 const PetscInt oebb = oebl + (k-1); 3660 const PetscInt oebr = oebb + (k-1); 3661 const PetscInt oebf = oebr + (k-1); 3662 const PetscInt oetf = oebf + (k-1); 3663 const PetscInt oetr = oetf + (k-1); 3664 const PetscInt oetb = oetr + (k-1); 3665 const PetscInt oetl = oetb + (k-1); 3666 const PetscInt oerf = oetl + (k-1); 3667 const PetscInt oelf = oerf + (k-1); 3668 const PetscInt oelb = oelf + (k-1); 3669 const PetscInt oerb = oelb + (k-1); 3670 const PetscInt ovblf = oerb + (k-1); 3671 const PetscInt ovblb = ovblf + 1; 3672 const PetscInt ovbrb = ovblb + 1; 3673 const PetscInt ovbrf = ovbrb + 1; 3674 const PetscInt ovtlf = ovbrf + 1; 3675 const PetscInt ovtrf = ovtlf + 1; 3676 const PetscInt ovtrb = ovtrf + 1; 3677 const PetscInt ovtlb = ovtrb + 1; 3678 PetscInt o, n; 3679 3680 /* Bottom Slice */ 3681 /* bottom */ 3682 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 3683 for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3684 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 3685 /* middle */ 3686 for (i = 0; i < k-1; ++i) { 3687 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 3688 for (n = 0; n < k-1; ++n) {o = ofb+n*(k-1)+i; for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;} 3689 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 3690 } 3691 /* top */ 3692 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 3693 for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3694 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 3695 3696 /* Middle Slice */ 3697 for (j = 0; j < k-1; ++j) { 3698 /* bottom */ 3699 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 3700 for (o = off+j*(k-1); o < off+(j+1)*(k-1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3701 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 3702 /* middle */ 3703 for (i = 0; i < k-1; ++i) { 3704 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 3705 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc+(j*(k-1)+i)*(k-1)+n)*Nc + c + foffset; 3706 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 3707 } 3708 /* top */ 3709 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 3710 for (o = ofk+j*(k-1)+(k-2); o >= ofk+j*(k-1); --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3711 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 3712 } 3713 3714 /* Top Slice */ 3715 /* bottom */ 3716 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 3717 for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3718 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 3719 /* middle */ 3720 for (i = 0; i < k-1; ++i) { 3721 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 3722 for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 3723 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 3724 } 3725 /* top */ 3726 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 3727 for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 3728 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 3729 3730 foffset = offset; 3731 } 3732 break; 3733 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", dim); 3734 } 3735 } 3736 if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 3737 /* Check permutation */ 3738 { 3739 PetscInt *check; 3740 3741 ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 3742 for (i = 0; i < size; ++i) {check[i] = -1; if (perm[i] < 0 || perm[i] >= size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid permutation index p[%D] = %D", i, perm[i]);} 3743 for (i = 0; i < size; ++i) check[perm[i]] = i; 3744 for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 3745 ierr = PetscFree(check);CHKERRQ(ierr); 3746 } 3747 ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 3748 PetscFunctionReturn(0); 3749 } 3750 3751 PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 3752 { 3753 PetscDS prob; 3754 PetscInt depth, Nf, h; 3755 DMLabel label; 3756 PetscErrorCode ierr; 3757 3758 PetscFunctionBeginHot; 3759 prob = dm->prob; 3760 Nf = prob->Nf; 3761 label = dm->depthLabel; 3762 *dspace = NULL; 3763 if (field < Nf) { 3764 PetscObject disc = prob->disc[field]; 3765 3766 if (disc->classid == PETSCFE_CLASSID) { 3767 PetscDualSpace dsp; 3768 3769 ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 3770 ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 3771 ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 3772 h = depth - 1 - h; 3773 if (h) { 3774 ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 3775 } else { 3776 *dspace = dsp; 3777 } 3778 } 3779 } 3780 PetscFunctionReturn(0); 3781 } 3782 3783 3784 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3785 { 3786 PetscScalar *array, *vArray; 3787 const PetscInt *cone, *coneO; 3788 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3789 PetscErrorCode ierr; 3790 3791 PetscFunctionBeginHot; 3792 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3793 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3794 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3795 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3796 if (!values || !*values) { 3797 if ((point >= pStart) && (point < pEnd)) { 3798 PetscInt dof; 3799 3800 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3801 size += dof; 3802 } 3803 for (p = 0; p < numPoints; ++p) { 3804 const PetscInt cp = cone[p]; 3805 PetscInt dof; 3806 3807 if ((cp < pStart) || (cp >= pEnd)) continue; 3808 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3809 size += dof; 3810 } 3811 if (!values) { 3812 if (csize) *csize = size; 3813 PetscFunctionReturn(0); 3814 } 3815 ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 3816 } else { 3817 array = *values; 3818 } 3819 size = 0; 3820 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3821 if ((point >= pStart) && (point < pEnd)) { 3822 PetscInt dof, off, d; 3823 PetscScalar *varr; 3824 3825 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3826 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3827 varr = &vArray[off]; 3828 for (d = 0; d < dof; ++d, ++offset) { 3829 array[offset] = varr[d]; 3830 } 3831 size += dof; 3832 } 3833 for (p = 0; p < numPoints; ++p) { 3834 const PetscInt cp = cone[p]; 3835 PetscInt o = coneO[p]; 3836 PetscInt dof, off, d; 3837 PetscScalar *varr; 3838 3839 if ((cp < pStart) || (cp >= pEnd)) continue; 3840 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3841 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3842 varr = &vArray[off]; 3843 if (o >= 0) { 3844 for (d = 0; d < dof; ++d, ++offset) { 3845 array[offset] = varr[d]; 3846 } 3847 } else { 3848 for (d = dof-1; d >= 0; --d, ++offset) { 3849 array[offset] = varr[d]; 3850 } 3851 } 3852 size += dof; 3853 } 3854 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3855 if (!*values) { 3856 if (csize) *csize = size; 3857 *values = array; 3858 } else { 3859 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 3860 *csize = size; 3861 } 3862 PetscFunctionReturn(0); 3863 } 3864 3865 static PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 3866 { 3867 const PetscInt *cla; 3868 PetscInt np, *pts = NULL; 3869 PetscErrorCode ierr; 3870 3871 PetscFunctionBeginHot; 3872 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 3873 if (!*clPoints) { 3874 PetscInt pStart, pEnd, p, q; 3875 3876 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3877 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 3878 /* Compress out points not in the section */ 3879 for (p = 0, q = 0; p < np; p++) { 3880 PetscInt r = pts[2*p]; 3881 if ((r >= pStart) && (r < pEnd)) { 3882 pts[q*2] = r; 3883 pts[q*2+1] = pts[2*p+1]; 3884 ++q; 3885 } 3886 } 3887 np = q; 3888 cla = NULL; 3889 } else { 3890 PetscInt dof, off; 3891 3892 ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 3893 ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 3894 ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 3895 np = dof/2; 3896 pts = (PetscInt *) &cla[off]; 3897 } 3898 *numPoints = np; 3899 *points = pts; 3900 *clp = cla; 3901 3902 PetscFunctionReturn(0); 3903 } 3904 3905 static PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 3906 { 3907 PetscErrorCode ierr; 3908 3909 PetscFunctionBeginHot; 3910 if (!*clPoints) { 3911 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 3912 } else { 3913 ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 3914 } 3915 *numPoints = 0; 3916 *points = NULL; 3917 *clSec = NULL; 3918 *clPoints = NULL; 3919 *clp = NULL; 3920 PetscFunctionReturn(0); 3921 } 3922 3923 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3924 { 3925 PetscInt offset = 0, p; 3926 const PetscInt **perms = NULL; 3927 const PetscScalar **flips = NULL; 3928 PetscErrorCode ierr; 3929 3930 PetscFunctionBeginHot; 3931 *size = 0; 3932 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 3933 for (p = 0; p < numPoints; p++) { 3934 const PetscInt point = points[2*p]; 3935 const PetscInt *perm = perms ? perms[p] : NULL; 3936 const PetscScalar *flip = flips ? flips[p] : NULL; 3937 PetscInt dof, off, d; 3938 const PetscScalar *varr; 3939 3940 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3941 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3942 varr = &vArray[off]; 3943 if (clperm) { 3944 if (perm) { 3945 for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 3946 } else { 3947 for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 3948 } 3949 if (flip) { 3950 for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 3951 } 3952 } else { 3953 if (perm) { 3954 for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 3955 } else { 3956 for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 3957 } 3958 if (flip) { 3959 for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 3960 } 3961 } 3962 offset += dof; 3963 } 3964 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 3965 *size = offset; 3966 PetscFunctionReturn(0); 3967 } 3968 3969 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3970 { 3971 PetscInt offset = 0, f; 3972 PetscErrorCode ierr; 3973 3974 PetscFunctionBeginHot; 3975 *size = 0; 3976 for (f = 0; f < numFields; ++f) { 3977 PetscInt p; 3978 const PetscInt **perms = NULL; 3979 const PetscScalar **flips = NULL; 3980 3981 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 3982 for (p = 0; p < numPoints; p++) { 3983 const PetscInt point = points[2*p]; 3984 PetscInt fdof, foff, b; 3985 const PetscScalar *varr; 3986 const PetscInt *perm = perms ? perms[p] : NULL; 3987 const PetscScalar *flip = flips ? flips[p] : NULL; 3988 3989 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3990 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3991 varr = &vArray[foff]; 3992 if (clperm) { 3993 if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 3994 else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 3995 if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 3996 } else { 3997 if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 3998 else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 3999 if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 4000 } 4001 offset += fdof; 4002 } 4003 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4004 } 4005 *size = offset; 4006 PetscFunctionReturn(0); 4007 } 4008 4009 /*@C 4010 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 4011 4012 Not collective 4013 4014 Input Parameters: 4015 + dm - The DM 4016 . section - The section describing the layout in v, or NULL to use the default section 4017 . v - The local vector 4018 . point - The point in the DM 4019 . csize - The size of the input values array, or NULL 4020 - values - An array to use for the values, or NULL to have it allocated automatically 4021 4022 Output Parameters: 4023 + csize - The number of values in the closure 4024 - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed 4025 4026 $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 4027 $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 4028 $ assembly function, and a user may already have allocated storage for this operation. 4029 $ 4030 $ A typical use could be 4031 $ 4032 $ values = NULL; 4033 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4034 $ for (cl = 0; cl < clSize; ++cl) { 4035 $ <Compute on closure> 4036 $ } 4037 $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4038 $ 4039 $ or 4040 $ 4041 $ PetscMalloc1(clMaxSize, &values); 4042 $ for (p = pStart; p < pEnd; ++p) { 4043 $ clSize = clMaxSize; 4044 $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 4045 $ for (cl = 0; cl < clSize; ++cl) { 4046 $ <Compute on closure> 4047 $ } 4048 $ } 4049 $ PetscFree(values); 4050 4051 Fortran Notes: 4052 Since it returns an array, this routine is only available in Fortran 90, and you must 4053 include petsc.h90 in your code. 4054 4055 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4056 4057 Level: intermediate 4058 4059 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4060 @*/ 4061 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4062 { 4063 PetscSection clSection; 4064 IS clPoints; 4065 PetscScalar *array; 4066 const PetscScalar *vArray; 4067 PetscInt *points = NULL; 4068 const PetscInt *clp, *perm; 4069 PetscInt depth, numFields, numPoints, size; 4070 PetscErrorCode ierr; 4071 4072 PetscFunctionBeginHot; 4073 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4074 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4075 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4076 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4077 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4078 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4079 if (depth == 1 && numFields < 2) { 4080 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 4081 PetscFunctionReturn(0); 4082 } 4083 /* Get points */ 4084 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4085 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 4086 /* Get array */ 4087 if (!values || !*values) { 4088 PetscInt asize = 0, dof, p; 4089 4090 for (p = 0; p < numPoints*2; p += 2) { 4091 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4092 asize += dof; 4093 } 4094 if (!values) { 4095 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4096 if (csize) *csize = asize; 4097 PetscFunctionReturn(0); 4098 } 4099 ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 4100 } else { 4101 array = *values; 4102 } 4103 ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 4104 /* Get values */ 4105 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 4106 else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, array);CHKERRQ(ierr);} 4107 /* Cleanup points */ 4108 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4109 /* Cleanup array */ 4110 ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 4111 if (!*values) { 4112 if (csize) *csize = size; 4113 *values = array; 4114 } else { 4115 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 4116 *csize = size; 4117 } 4118 PetscFunctionReturn(0); 4119 } 4120 4121 /*@C 4122 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 4123 4124 Not collective 4125 4126 Input Parameters: 4127 + dm - The DM 4128 . section - The section describing the layout in v, or NULL to use the default section 4129 . v - The local vector 4130 . point - The point in the DM 4131 . csize - The number of values in the closure, or NULL 4132 - values - The array of values, which is a borrowed array and should not be freed 4133 4134 Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 4135 4136 Fortran Notes: 4137 Since it returns an array, this routine is only available in Fortran 90, and you must 4138 include petsc.h90 in your code. 4139 4140 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4141 4142 Level: intermediate 4143 4144 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4145 @*/ 4146 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4147 { 4148 PetscInt size = 0; 4149 PetscErrorCode ierr; 4150 4151 PetscFunctionBegin; 4152 /* Should work without recalculating size */ 4153 ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 4154 *values = NULL; 4155 PetscFunctionReturn(0); 4156 } 4157 4158 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 4159 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 4160 4161 PETSC_STATIC_INLINE PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 4162 { 4163 PetscInt cdof; /* The number of constraints on this point */ 4164 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4165 PetscScalar *a; 4166 PetscInt off, cind = 0, k; 4167 PetscErrorCode ierr; 4168 4169 PetscFunctionBegin; 4170 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4171 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4172 a = &array[off]; 4173 if (!cdof || setBC) { 4174 if (clperm) { 4175 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 4176 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 4177 } else { 4178 if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 4179 else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 4180 } 4181 } else { 4182 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4183 if (clperm) { 4184 if (perm) {for (k = 0; k < dof; ++k) { 4185 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4186 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4187 } 4188 } else { 4189 for (k = 0; k < dof; ++k) { 4190 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4191 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4192 } 4193 } 4194 } else { 4195 if (perm) { 4196 for (k = 0; k < dof; ++k) { 4197 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4198 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4199 } 4200 } else { 4201 for (k = 0; k < dof; ++k) { 4202 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4203 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4204 } 4205 } 4206 } 4207 } 4208 PetscFunctionReturn(0); 4209 } 4210 4211 PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 4212 { 4213 PetscInt cdof; /* The number of constraints on this point */ 4214 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4215 PetscScalar *a; 4216 PetscInt off, cind = 0, k; 4217 PetscErrorCode ierr; 4218 4219 PetscFunctionBegin; 4220 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4221 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4222 a = &array[off]; 4223 if (cdof) { 4224 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4225 if (clperm) { 4226 if (perm) { 4227 for (k = 0; k < dof; ++k) { 4228 if ((cind < cdof) && (k == cdofs[cind])) { 4229 fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4230 cind++; 4231 } 4232 } 4233 } else { 4234 for (k = 0; k < dof; ++k) { 4235 if ((cind < cdof) && (k == cdofs[cind])) { 4236 fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 4237 cind++; 4238 } 4239 } 4240 } 4241 } else { 4242 if (perm) { 4243 for (k = 0; k < dof; ++k) { 4244 if ((cind < cdof) && (k == cdofs[cind])) { 4245 fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 4246 cind++; 4247 } 4248 } 4249 } else { 4250 for (k = 0; k < dof; ++k) { 4251 if ((cind < cdof) && (k == cdofs[cind])) { 4252 fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 4253 cind++; 4254 } 4255 } 4256 } 4257 } 4258 } 4259 PetscFunctionReturn(0); 4260 } 4261 4262 PETSC_STATIC_INLINE PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, const PetscInt *perm, const PetscScalar *flip, PetscInt f, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 4263 { 4264 PetscScalar *a; 4265 PetscInt fdof, foff, fcdof, foffset = *offset; 4266 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4267 PetscInt cind = 0, b; 4268 PetscErrorCode ierr; 4269 4270 PetscFunctionBegin; 4271 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4272 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4273 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4274 a = &array[foff]; 4275 if (!fcdof || setBC) { 4276 if (clperm) { 4277 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 4278 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 4279 } else { 4280 if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 4281 else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 4282 } 4283 } else { 4284 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4285 if (clperm) { 4286 if (perm) { 4287 for (b = 0; b < fdof; b++) { 4288 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4289 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4290 } 4291 } else { 4292 for (b = 0; b < fdof; b++) { 4293 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4294 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 4295 } 4296 } 4297 } else { 4298 if (perm) { 4299 for (b = 0; b < fdof; b++) { 4300 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4301 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 4302 } 4303 } else { 4304 for (b = 0; b < fdof; b++) { 4305 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 4306 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 4307 } 4308 } 4309 } 4310 } 4311 *offset += fdof; 4312 PetscFunctionReturn(0); 4313 } 4314 4315 PETSC_STATIC_INLINE PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, const PetscInt perm[], const PetscScalar flip[], PetscInt f, PetscInt Ncc, const PetscInt comps[], void (*fuse)(PetscScalar*, PetscScalar), const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 4316 { 4317 PetscScalar *a; 4318 PetscInt fdof, foff, fcdof, foffset = *offset; 4319 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4320 PetscInt cind = 0, ncind = 0, b; 4321 PetscBool ncSet, fcSet; 4322 PetscErrorCode ierr; 4323 4324 PetscFunctionBegin; 4325 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4326 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 4327 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 4328 a = &array[foff]; 4329 if (fcdof) { 4330 /* We just override fcdof and fcdofs with Ncc and comps */ 4331 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4332 if (clperm) { 4333 if (perm) { 4334 if (comps) { 4335 for (b = 0; b < fdof; b++) { 4336 ncSet = fcSet = PETSC_FALSE; 4337 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4338 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4339 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 4340 } 4341 } else { 4342 for (b = 0; b < fdof; b++) { 4343 if ((cind < fcdof) && (b == fcdofs[cind])) { 4344 fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 4345 ++cind; 4346 } 4347 } 4348 } 4349 } else { 4350 if (comps) { 4351 for (b = 0; b < fdof; b++) { 4352 ncSet = fcSet = PETSC_FALSE; 4353 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4354 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4355 if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 4356 } 4357 } else { 4358 for (b = 0; b < fdof; b++) { 4359 if ((cind < fcdof) && (b == fcdofs[cind])) { 4360 fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 4361 ++cind; 4362 } 4363 } 4364 } 4365 } 4366 } else { 4367 if (perm) { 4368 if (comps) { 4369 for (b = 0; b < fdof; b++) { 4370 ncSet = fcSet = PETSC_FALSE; 4371 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4372 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4373 if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 4374 } 4375 } else { 4376 for (b = 0; b < fdof; b++) { 4377 if ((cind < fcdof) && (b == fcdofs[cind])) { 4378 fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 4379 ++cind; 4380 } 4381 } 4382 } 4383 } else { 4384 if (comps) { 4385 for (b = 0; b < fdof; b++) { 4386 ncSet = fcSet = PETSC_FALSE; 4387 if ((ncind < Ncc) && (b == comps[ncind])) {++ncind; ncSet = PETSC_TRUE;} 4388 if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 4389 if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 4390 } 4391 } else { 4392 for (b = 0; b < fdof; b++) { 4393 if ((cind < fcdof) && (b == fcdofs[cind])) { 4394 fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 4395 ++cind; 4396 } 4397 } 4398 } 4399 } 4400 } 4401 } 4402 *offset += fdof; 4403 PetscFunctionReturn(0); 4404 } 4405 4406 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4407 { 4408 PetscScalar *array; 4409 const PetscInt *cone, *coneO; 4410 PetscInt pStart, pEnd, p, numPoints, off, dof; 4411 PetscErrorCode ierr; 4412 4413 PetscFunctionBeginHot; 4414 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4415 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 4416 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4417 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 4418 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4419 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 4420 const PetscInt cp = !p ? point : cone[p-1]; 4421 const PetscInt o = !p ? 0 : coneO[p-1]; 4422 4423 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 4424 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 4425 /* ADD_VALUES */ 4426 { 4427 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4428 PetscScalar *a; 4429 PetscInt cdof, coff, cind = 0, k; 4430 4431 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 4432 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 4433 a = &array[coff]; 4434 if (!cdof) { 4435 if (o >= 0) { 4436 for (k = 0; k < dof; ++k) { 4437 a[k] += values[off+k]; 4438 } 4439 } else { 4440 for (k = 0; k < dof; ++k) { 4441 a[k] += values[off+dof-k-1]; 4442 } 4443 } 4444 } else { 4445 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 4446 if (o >= 0) { 4447 for (k = 0; k < dof; ++k) { 4448 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4449 a[k] += values[off+k]; 4450 } 4451 } else { 4452 for (k = 0; k < dof; ++k) { 4453 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 4454 a[k] += values[off+dof-k-1]; 4455 } 4456 } 4457 } 4458 } 4459 } 4460 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4461 PetscFunctionReturn(0); 4462 } 4463 4464 /*@C 4465 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 4466 4467 Not collective 4468 4469 Input Parameters: 4470 + dm - The DM 4471 . section - The section describing the layout in v, or NULL to use the default section 4472 . v - The local vector 4473 . point - The point in the DM 4474 . values - The array of values 4475 - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 4476 where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 4477 4478 Fortran Notes: 4479 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4480 4481 Level: intermediate 4482 4483 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 4484 @*/ 4485 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 4486 { 4487 PetscSection clSection; 4488 IS clPoints; 4489 PetscScalar *array; 4490 PetscInt *points = NULL; 4491 const PetscInt *clp, *clperm; 4492 PetscInt depth, numFields, numPoints, p; 4493 PetscErrorCode ierr; 4494 4495 PetscFunctionBeginHot; 4496 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4497 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4498 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4499 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4500 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4501 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4502 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 4503 ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 4504 PetscFunctionReturn(0); 4505 } 4506 /* Get points */ 4507 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 4508 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4509 /* Get array */ 4510 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4511 /* Get values */ 4512 if (numFields > 0) { 4513 PetscInt offset = 0, f; 4514 for (f = 0; f < numFields; ++f) { 4515 const PetscInt **perms = NULL; 4516 const PetscScalar **flips = NULL; 4517 4518 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4519 switch (mode) { 4520 case INSERT_VALUES: 4521 for (p = 0; p < numPoints; p++) { 4522 const PetscInt point = points[2*p]; 4523 const PetscInt *perm = perms ? perms[p] : NULL; 4524 const PetscScalar *flip = flips ? flips[p] : NULL; 4525 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 4526 } break; 4527 case INSERT_ALL_VALUES: 4528 for (p = 0; p < numPoints; p++) { 4529 const PetscInt point = points[2*p]; 4530 const PetscInt *perm = perms ? perms[p] : NULL; 4531 const PetscScalar *flip = flips ? flips[p] : NULL; 4532 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 4533 } break; 4534 case INSERT_BC_VALUES: 4535 for (p = 0; p < numPoints; p++) { 4536 const PetscInt point = points[2*p]; 4537 const PetscInt *perm = perms ? perms[p] : NULL; 4538 const PetscScalar *flip = flips ? flips[p] : NULL; 4539 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 4540 } break; 4541 case ADD_VALUES: 4542 for (p = 0; p < numPoints; p++) { 4543 const PetscInt point = points[2*p]; 4544 const PetscInt *perm = perms ? perms[p] : NULL; 4545 const PetscScalar *flip = flips ? flips[p] : NULL; 4546 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 4547 } break; 4548 case ADD_ALL_VALUES: 4549 for (p = 0; p < numPoints; p++) { 4550 const PetscInt point = points[2*p]; 4551 const PetscInt *perm = perms ? perms[p] : NULL; 4552 const PetscScalar *flip = flips ? flips[p] : NULL; 4553 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 4554 } break; 4555 case ADD_BC_VALUES: 4556 for (p = 0; p < numPoints; p++) { 4557 const PetscInt point = points[2*p]; 4558 const PetscInt *perm = perms ? perms[p] : NULL; 4559 const PetscScalar *flip = flips ? flips[p] : NULL; 4560 updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 4561 } break; 4562 default: 4563 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4564 } 4565 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4566 } 4567 } else { 4568 PetscInt dof, off; 4569 const PetscInt **perms = NULL; 4570 const PetscScalar **flips = NULL; 4571 4572 ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4573 switch (mode) { 4574 case INSERT_VALUES: 4575 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4576 const PetscInt point = points[2*p]; 4577 const PetscInt *perm = perms ? perms[p] : NULL; 4578 const PetscScalar *flip = flips ? flips[p] : NULL; 4579 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4580 updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 4581 } break; 4582 case INSERT_ALL_VALUES: 4583 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4584 const PetscInt point = points[2*p]; 4585 const PetscInt *perm = perms ? perms[p] : NULL; 4586 const PetscScalar *flip = flips ? flips[p] : NULL; 4587 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4588 updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 4589 } break; 4590 case INSERT_BC_VALUES: 4591 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4592 const PetscInt point = points[2*p]; 4593 const PetscInt *perm = perms ? perms[p] : NULL; 4594 const PetscScalar *flip = flips ? flips[p] : NULL; 4595 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4596 updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 4597 } break; 4598 case ADD_VALUES: 4599 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4600 const PetscInt point = points[2*p]; 4601 const PetscInt *perm = perms ? perms[p] : NULL; 4602 const PetscScalar *flip = flips ? flips[p] : NULL; 4603 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4604 updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 4605 } break; 4606 case ADD_ALL_VALUES: 4607 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4608 const PetscInt point = points[2*p]; 4609 const PetscInt *perm = perms ? perms[p] : NULL; 4610 const PetscScalar *flip = flips ? flips[p] : NULL; 4611 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4612 updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 4613 } break; 4614 case ADD_BC_VALUES: 4615 for (p = 0, off = 0; p < numPoints; p++, off += dof) { 4616 const PetscInt point = points[2*p]; 4617 const PetscInt *perm = perms ? perms[p] : NULL; 4618 const PetscScalar *flip = flips ? flips[p] : NULL; 4619 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4620 updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 4621 } break; 4622 default: 4623 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4624 } 4625 ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4626 } 4627 /* Cleanup points */ 4628 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4629 /* Cleanup array */ 4630 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4631 PetscFunctionReturn(0); 4632 } 4633 4634 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], const PetscScalar values[], InsertMode mode) 4635 { 4636 PetscSection clSection; 4637 IS clPoints; 4638 PetscScalar *array; 4639 PetscInt *points = NULL; 4640 const PetscInt *clp, *clperm; 4641 PetscInt numFields, numPoints, p; 4642 PetscInt offset = 0, f; 4643 PetscErrorCode ierr; 4644 4645 PetscFunctionBeginHot; 4646 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4647 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4648 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4649 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4650 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4651 /* Get points */ 4652 ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 4653 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4654 /* Get array */ 4655 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4656 /* Get values */ 4657 for (f = 0; f < numFields; ++f) { 4658 const PetscInt **perms = NULL; 4659 const PetscScalar **flips = NULL; 4660 4661 if (!fieldActive[f]) { 4662 for (p = 0; p < numPoints*2; p += 2) { 4663 PetscInt fdof; 4664 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4665 offset += fdof; 4666 } 4667 continue; 4668 } 4669 ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4670 switch (mode) { 4671 case INSERT_VALUES: 4672 for (p = 0; p < numPoints; p++) { 4673 const PetscInt point = points[2*p]; 4674 const PetscInt *perm = perms ? perms[p] : NULL; 4675 const PetscScalar *flip = flips ? flips[p] : NULL; 4676 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 4677 } break; 4678 case INSERT_ALL_VALUES: 4679 for (p = 0; p < numPoints; p++) { 4680 const PetscInt point = points[2*p]; 4681 const PetscInt *perm = perms ? perms[p] : NULL; 4682 const PetscScalar *flip = flips ? flips[p] : NULL; 4683 updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 4684 } break; 4685 case INSERT_BC_VALUES: 4686 for (p = 0; p < numPoints; p++) { 4687 const PetscInt point = points[2*p]; 4688 const PetscInt *perm = perms ? perms[p] : NULL; 4689 const PetscScalar *flip = flips ? flips[p] : NULL; 4690 updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, clperm, values, &offset, array); 4691 } break; 4692 case ADD_VALUES: 4693 for (p = 0; p < numPoints; p++) { 4694 const PetscInt point = points[2*p]; 4695 const PetscInt *perm = perms ? perms[p] : NULL; 4696 const PetscScalar *flip = flips ? flips[p] : NULL; 4697 updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 4698 } break; 4699 case ADD_ALL_VALUES: 4700 for (p = 0; p < numPoints; p++) { 4701 const PetscInt point = points[2*p]; 4702 const PetscInt *perm = perms ? perms[p] : NULL; 4703 const PetscScalar *flip = flips ? flips[p] : NULL; 4704 updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 4705 } break; 4706 default: 4707 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4708 } 4709 ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 4710 } 4711 /* Cleanup points */ 4712 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4713 /* Cleanup array */ 4714 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4715 PetscFunctionReturn(0); 4716 } 4717 4718 static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 4719 { 4720 PetscMPIInt rank; 4721 PetscInt i, j; 4722 PetscErrorCode ierr; 4723 4724 PetscFunctionBegin; 4725 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 4726 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 4727 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 4728 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 4729 numCIndices = numCIndices ? numCIndices : numRIndices; 4730 for (i = 0; i < numRIndices; i++) { 4731 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 4732 for (j = 0; j < numCIndices; j++) { 4733 #if defined(PETSC_USE_COMPLEX) 4734 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 4735 #else 4736 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 4737 #endif 4738 } 4739 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 4740 } 4741 PetscFunctionReturn(0); 4742 } 4743 4744 /* . off - The global offset of this point */ 4745 PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], PetscInt indices[]) 4746 { 4747 PetscInt dof; /* The number of unknowns on this point */ 4748 PetscInt cdof; /* The number of constraints on this point */ 4749 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4750 PetscInt cind = 0, k; 4751 PetscErrorCode ierr; 4752 4753 PetscFunctionBegin; 4754 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4755 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4756 if (!cdof || setBC) { 4757 if (perm) { 4758 for (k = 0; k < dof; k++) indices[*loff+perm[k]] = off + k; 4759 } else { 4760 for (k = 0; k < dof; k++) indices[*loff+k] = off + k; 4761 } 4762 } else { 4763 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4764 if (perm) { 4765 for (k = 0; k < dof; ++k) { 4766 if ((cind < cdof) && (k == cdofs[cind])) { 4767 /* Insert check for returning constrained indices */ 4768 indices[*loff+perm[k]] = -(off+k+1); 4769 ++cind; 4770 } else { 4771 indices[*loff+perm[k]] = off+k-cind; 4772 } 4773 } 4774 } else { 4775 for (k = 0; k < dof; ++k) { 4776 if ((cind < cdof) && (k == cdofs[cind])) { 4777 /* Insert check for returning constrained indices */ 4778 indices[*loff+k] = -(off+k+1); 4779 ++cind; 4780 } else { 4781 indices[*loff+k] = off+k-cind; 4782 } 4783 } 4784 } 4785 } 4786 *loff += dof; 4787 PetscFunctionReturn(0); 4788 } 4789 4790 /* . off - The global offset of this point */ 4791 PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, PetscInt indices[]) 4792 { 4793 PetscInt numFields, foff, f; 4794 PetscErrorCode ierr; 4795 4796 PetscFunctionBegin; 4797 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4798 for (f = 0, foff = 0; f < numFields; ++f) { 4799 PetscInt fdof, cfdof; 4800 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4801 PetscInt cind = 0, b; 4802 const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 4803 4804 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4805 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4806 if (!cfdof || setBC) { 4807 if (perm) {for (b = 0; b < fdof; b++) {indices[foffs[f]+perm[b]] = off+foff+b;}} 4808 else {for (b = 0; b < fdof; b++) {indices[foffs[f]+ b ] = off+foff+b;}} 4809 } else { 4810 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4811 if (perm) { 4812 for (b = 0; b < fdof; b++) { 4813 if ((cind < cfdof) && (b == fcdofs[cind])) { 4814 indices[foffs[f]+perm[b]] = -(off+foff+b+1); 4815 ++cind; 4816 } else { 4817 indices[foffs[f]+perm[b]] = off+foff+b-cind; 4818 } 4819 } 4820 } else { 4821 for (b = 0; b < fdof; b++) { 4822 if ((cind < cfdof) && (b == fcdofs[cind])) { 4823 indices[foffs[f]+b] = -(off+foff+b+1); 4824 ++cind; 4825 } else { 4826 indices[foffs[f]+b] = off+foff+b-cind; 4827 } 4828 } 4829 } 4830 } 4831 foff += (setBC ? fdof : (fdof - cfdof)); 4832 foffs[f] += fdof; 4833 } 4834 PetscFunctionReturn(0); 4835 } 4836 4837 PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyLeft) 4838 { 4839 Mat cMat; 4840 PetscSection aSec, cSec; 4841 IS aIS; 4842 PetscInt aStart = -1, aEnd = -1; 4843 const PetscInt *anchors; 4844 PetscInt numFields, f, p, q, newP = 0; 4845 PetscInt newNumPoints = 0, newNumIndices = 0; 4846 PetscInt *newPoints, *indices, *newIndices; 4847 PetscInt maxAnchor, maxDof; 4848 PetscInt newOffsets[32]; 4849 PetscInt *pointMatOffsets[32]; 4850 PetscInt *newPointOffsets[32]; 4851 PetscScalar *pointMat[32]; 4852 PetscScalar *newValues=NULL,*tmpValues; 4853 PetscBool anyConstrained = PETSC_FALSE; 4854 PetscErrorCode ierr; 4855 4856 PetscFunctionBegin; 4857 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4858 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4859 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4860 4861 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 4862 /* if there are point-to-point constraints */ 4863 if (aSec) { 4864 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4865 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 4866 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 4867 /* figure out how many points are going to be in the new element matrix 4868 * (we allow double counting, because it's all just going to be summed 4869 * into the global matrix anyway) */ 4870 for (p = 0; p < 2*numPoints; p+=2) { 4871 PetscInt b = points[p]; 4872 PetscInt bDof = 0, bSecDof; 4873 4874 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4875 if (!bSecDof) { 4876 continue; 4877 } 4878 if (b >= aStart && b < aEnd) { 4879 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 4880 } 4881 if (bDof) { 4882 /* this point is constrained */ 4883 /* it is going to be replaced by its anchors */ 4884 PetscInt bOff, q; 4885 4886 anyConstrained = PETSC_TRUE; 4887 newNumPoints += bDof; 4888 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 4889 for (q = 0; q < bDof; q++) { 4890 PetscInt a = anchors[bOff + q]; 4891 PetscInt aDof; 4892 4893 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 4894 newNumIndices += aDof; 4895 for (f = 0; f < numFields; ++f) { 4896 PetscInt fDof; 4897 4898 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 4899 newOffsets[f+1] += fDof; 4900 } 4901 } 4902 } 4903 else { 4904 /* this point is not constrained */ 4905 newNumPoints++; 4906 newNumIndices += bSecDof; 4907 for (f = 0; f < numFields; ++f) { 4908 PetscInt fDof; 4909 4910 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4911 newOffsets[f+1] += fDof; 4912 } 4913 } 4914 } 4915 } 4916 if (!anyConstrained) { 4917 if (outNumPoints) *outNumPoints = 0; 4918 if (outNumIndices) *outNumIndices = 0; 4919 if (outPoints) *outPoints = NULL; 4920 if (outValues) *outValues = NULL; 4921 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4922 PetscFunctionReturn(0); 4923 } 4924 4925 if (outNumPoints) *outNumPoints = newNumPoints; 4926 if (outNumIndices) *outNumIndices = newNumIndices; 4927 4928 for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 4929 4930 if (!outPoints && !outValues) { 4931 if (offsets) { 4932 for (f = 0; f <= numFields; f++) { 4933 offsets[f] = newOffsets[f]; 4934 } 4935 } 4936 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4937 PetscFunctionReturn(0); 4938 } 4939 4940 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 4941 4942 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 4943 4944 /* workspaces */ 4945 if (numFields) { 4946 for (f = 0; f < numFields; f++) { 4947 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4948 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4949 } 4950 } 4951 else { 4952 ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4953 ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4954 } 4955 4956 /* get workspaces for the point-to-point matrices */ 4957 if (numFields) { 4958 PetscInt totalOffset, totalMatOffset; 4959 4960 for (p = 0; p < numPoints; p++) { 4961 PetscInt b = points[2*p]; 4962 PetscInt bDof = 0, bSecDof; 4963 4964 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4965 if (!bSecDof) { 4966 for (f = 0; f < numFields; f++) { 4967 newPointOffsets[f][p + 1] = 0; 4968 pointMatOffsets[f][p + 1] = 0; 4969 } 4970 continue; 4971 } 4972 if (b >= aStart && b < aEnd) { 4973 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4974 } 4975 if (bDof) { 4976 for (f = 0; f < numFields; f++) { 4977 PetscInt fDof, q, bOff, allFDof = 0; 4978 4979 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4980 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4981 for (q = 0; q < bDof; q++) { 4982 PetscInt a = anchors[bOff + q]; 4983 PetscInt aFDof; 4984 4985 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 4986 allFDof += aFDof; 4987 } 4988 newPointOffsets[f][p+1] = allFDof; 4989 pointMatOffsets[f][p+1] = fDof * allFDof; 4990 } 4991 } 4992 else { 4993 for (f = 0; f < numFields; f++) { 4994 PetscInt fDof; 4995 4996 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4997 newPointOffsets[f][p+1] = fDof; 4998 pointMatOffsets[f][p+1] = 0; 4999 } 5000 } 5001 } 5002 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 5003 newPointOffsets[f][0] = totalOffset; 5004 pointMatOffsets[f][0] = totalMatOffset; 5005 for (p = 0; p < numPoints; p++) { 5006 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 5007 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 5008 } 5009 totalOffset = newPointOffsets[f][numPoints]; 5010 totalMatOffset = pointMatOffsets[f][numPoints]; 5011 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5012 } 5013 } 5014 else { 5015 for (p = 0; p < numPoints; p++) { 5016 PetscInt b = points[2*p]; 5017 PetscInt bDof = 0, bSecDof; 5018 5019 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 5020 if (!bSecDof) { 5021 newPointOffsets[0][p + 1] = 0; 5022 pointMatOffsets[0][p + 1] = 0; 5023 continue; 5024 } 5025 if (b >= aStart && b < aEnd) { 5026 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5027 } 5028 if (bDof) { 5029 PetscInt bOff, q, allDof = 0; 5030 5031 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5032 for (q = 0; q < bDof; q++) { 5033 PetscInt a = anchors[bOff + q], aDof; 5034 5035 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 5036 allDof += aDof; 5037 } 5038 newPointOffsets[0][p+1] = allDof; 5039 pointMatOffsets[0][p+1] = bSecDof * allDof; 5040 } 5041 else { 5042 newPointOffsets[0][p+1] = bSecDof; 5043 pointMatOffsets[0][p+1] = 0; 5044 } 5045 } 5046 newPointOffsets[0][0] = 0; 5047 pointMatOffsets[0][0] = 0; 5048 for (p = 0; p < numPoints; p++) { 5049 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 5050 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 5051 } 5052 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5053 } 5054 5055 /* output arrays */ 5056 ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5057 5058 /* get the point-to-point matrices; construct newPoints */ 5059 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 5060 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 5061 ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 5062 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5063 if (numFields) { 5064 for (p = 0, newP = 0; p < numPoints; p++) { 5065 PetscInt b = points[2*p]; 5066 PetscInt o = points[2*p+1]; 5067 PetscInt bDof = 0, bSecDof; 5068 5069 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5070 if (!bSecDof) { 5071 continue; 5072 } 5073 if (b >= aStart && b < aEnd) { 5074 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5075 } 5076 if (bDof) { 5077 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 5078 5079 fStart[0] = 0; 5080 fEnd[0] = 0; 5081 for (f = 0; f < numFields; f++) { 5082 PetscInt fDof; 5083 5084 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 5085 fStart[f+1] = fStart[f] + fDof; 5086 fEnd[f+1] = fStart[f+1]; 5087 } 5088 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5089 ierr = DMPlexGetIndicesPointFields_Internal(cSec, b, bOff, fEnd, PETSC_TRUE, perms, p, indices);CHKERRQ(ierr); 5090 5091 fAnchorStart[0] = 0; 5092 fAnchorEnd[0] = 0; 5093 for (f = 0; f < numFields; f++) { 5094 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 5095 5096 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 5097 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 5098 } 5099 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5100 for (q = 0; q < bDof; q++) { 5101 PetscInt a = anchors[bOff + q], aOff; 5102 5103 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5104 newPoints[2*(newP + q)] = a; 5105 newPoints[2*(newP + q) + 1] = 0; 5106 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5107 ierr = DMPlexGetIndicesPointFields_Internal(section, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, newIndices);CHKERRQ(ierr); 5108 } 5109 newP += bDof; 5110 5111 if (outValues) { 5112 /* get the point-to-point submatrix */ 5113 for (f = 0; f < numFields; f++) { 5114 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 5115 } 5116 } 5117 } 5118 else { 5119 newPoints[2 * newP] = b; 5120 newPoints[2 * newP + 1] = o; 5121 newP++; 5122 } 5123 } 5124 } else { 5125 for (p = 0; p < numPoints; p++) { 5126 PetscInt b = points[2*p]; 5127 PetscInt o = points[2*p+1]; 5128 PetscInt bDof = 0, bSecDof; 5129 5130 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 5131 if (!bSecDof) { 5132 continue; 5133 } 5134 if (b >= aStart && b < aEnd) { 5135 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5136 } 5137 if (bDof) { 5138 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 5139 5140 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 5141 ierr = DMPlexGetIndicesPoint_Internal(cSec, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, indices);CHKERRQ(ierr); 5142 5143 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 5144 for (q = 0; q < bDof; q++) { 5145 PetscInt a = anchors[bOff + q], aOff; 5146 5147 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5148 5149 newPoints[2*(newP + q)] = a; 5150 newPoints[2*(newP + q) + 1] = 0; 5151 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 5152 ierr = DMPlexGetIndicesPoint_Internal(section, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, newIndices);CHKERRQ(ierr); 5153 } 5154 newP += bDof; 5155 5156 /* get the point-to-point submatrix */ 5157 if (outValues) { 5158 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 5159 } 5160 } 5161 else { 5162 newPoints[2 * newP] = b; 5163 newPoints[2 * newP + 1] = o; 5164 newP++; 5165 } 5166 } 5167 } 5168 5169 if (outValues) { 5170 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 5171 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 5172 /* multiply constraints on the right */ 5173 if (numFields) { 5174 for (f = 0; f < numFields; f++) { 5175 PetscInt oldOff = offsets[f]; 5176 5177 for (p = 0; p < numPoints; p++) { 5178 PetscInt cStart = newPointOffsets[f][p]; 5179 PetscInt b = points[2 * p]; 5180 PetscInt c, r, k; 5181 PetscInt dof; 5182 5183 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5184 if (!dof) { 5185 continue; 5186 } 5187 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 5188 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 5189 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 5190 5191 for (r = 0; r < numIndices; r++) { 5192 for (c = 0; c < nCols; c++) { 5193 for (k = 0; k < dof; k++) { 5194 tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 5195 } 5196 } 5197 } 5198 } 5199 else { 5200 /* copy this column as is */ 5201 for (r = 0; r < numIndices; r++) { 5202 for (c = 0; c < dof; c++) { 5203 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5204 } 5205 } 5206 } 5207 oldOff += dof; 5208 } 5209 } 5210 } 5211 else { 5212 PetscInt oldOff = 0; 5213 for (p = 0; p < numPoints; p++) { 5214 PetscInt cStart = newPointOffsets[0][p]; 5215 PetscInt b = points[2 * p]; 5216 PetscInt c, r, k; 5217 PetscInt dof; 5218 5219 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 5220 if (!dof) { 5221 continue; 5222 } 5223 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 5224 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 5225 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 5226 5227 for (r = 0; r < numIndices; r++) { 5228 for (c = 0; c < nCols; c++) { 5229 for (k = 0; k < dof; k++) { 5230 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 5231 } 5232 } 5233 } 5234 } 5235 else { 5236 /* copy this column as is */ 5237 for (r = 0; r < numIndices; r++) { 5238 for (c = 0; c < dof; c++) { 5239 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 5240 } 5241 } 5242 } 5243 oldOff += dof; 5244 } 5245 } 5246 5247 if (multiplyLeft) { 5248 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 5249 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 5250 /* multiply constraints transpose on the left */ 5251 if (numFields) { 5252 for (f = 0; f < numFields; f++) { 5253 PetscInt oldOff = offsets[f]; 5254 5255 for (p = 0; p < numPoints; p++) { 5256 PetscInt rStart = newPointOffsets[f][p]; 5257 PetscInt b = points[2 * p]; 5258 PetscInt c, r, k; 5259 PetscInt dof; 5260 5261 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 5262 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 5263 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 5264 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 5265 5266 for (r = 0; r < nRows; r++) { 5267 for (c = 0; c < newNumIndices; c++) { 5268 for (k = 0; k < dof; k++) { 5269 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 5270 } 5271 } 5272 } 5273 } 5274 else { 5275 /* copy this row as is */ 5276 for (r = 0; r < dof; r++) { 5277 for (c = 0; c < newNumIndices; c++) { 5278 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 5279 } 5280 } 5281 } 5282 oldOff += dof; 5283 } 5284 } 5285 } 5286 else { 5287 PetscInt oldOff = 0; 5288 5289 for (p = 0; p < numPoints; p++) { 5290 PetscInt rStart = newPointOffsets[0][p]; 5291 PetscInt b = points[2 * p]; 5292 PetscInt c, r, k; 5293 PetscInt dof; 5294 5295 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 5296 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 5297 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 5298 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 5299 5300 for (r = 0; r < nRows; r++) { 5301 for (c = 0; c < newNumIndices; c++) { 5302 for (k = 0; k < dof; k++) { 5303 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 5304 } 5305 } 5306 } 5307 } 5308 else { 5309 /* copy this row as is */ 5310 for (r = 0; r < dof; r++) { 5311 for (c = 0; c < newNumIndices; c++) { 5312 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 5313 } 5314 } 5315 } 5316 oldOff += dof; 5317 } 5318 } 5319 5320 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 5321 } 5322 else { 5323 newValues = tmpValues; 5324 } 5325 } 5326 5327 /* clean up */ 5328 ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 5329 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5330 5331 if (numFields) { 5332 for (f = 0; f < numFields; f++) { 5333 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5334 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 5335 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 5336 } 5337 } 5338 else { 5339 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5340 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 5341 ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 5342 } 5343 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 5344 5345 /* output */ 5346 if (outPoints) { 5347 *outPoints = newPoints; 5348 } 5349 else { 5350 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5351 } 5352 if (outValues) { 5353 *outValues = newValues; 5354 } 5355 for (f = 0; f <= numFields; f++) { 5356 offsets[f] = newOffsets[f]; 5357 } 5358 PetscFunctionReturn(0); 5359 } 5360 5361 /*@C 5362 DMPlexGetClosureIndices - Get the global indices in a vector v for all points in the closure of the given point 5363 5364 Not collective 5365 5366 Input Parameters: 5367 + dm - The DM 5368 . section - The section describing the layout in v, or NULL to use the default section 5369 . globalSection - The section describing the parallel layout in v, or NULL to use the default section 5370 - point - The mesh point 5371 5372 Output parameters: 5373 + numIndices - The number of indices 5374 . indices - The indices 5375 - outOffsets - Field offset if not NULL 5376 5377 Note: Must call DMPlexRestoreClosureIndices() to free allocated memory 5378 5379 Level: advanced 5380 5381 .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 5382 @*/ 5383 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices, PetscInt *outOffsets) 5384 { 5385 PetscSection clSection; 5386 IS clPoints; 5387 const PetscInt *clp; 5388 const PetscInt **perms[32] = {NULL}; 5389 PetscInt *points = NULL, *pointsNew; 5390 PetscInt numPoints, numPointsNew; 5391 PetscInt offsets[32]; 5392 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 5393 PetscErrorCode ierr; 5394 5395 PetscFunctionBegin; 5396 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5397 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5398 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5399 if (numIndices) PetscValidPointer(numIndices, 4); 5400 PetscValidPointer(indices, 5); 5401 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 5402 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 5403 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5404 /* Get points in closure */ 5405 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5406 /* Get number of indices and indices per field */ 5407 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 5408 PetscInt dof, fdof; 5409 5410 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5411 for (f = 0; f < Nf; ++f) { 5412 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5413 offsets[f+1] += fdof; 5414 } 5415 Nind += dof; 5416 } 5417 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 5418 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Nind); 5419 if (!Nf) offsets[1] = Nind; 5420 /* Get dual space symmetries */ 5421 for (f = 0; f < PetscMax(1,Nf); f++) { 5422 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5423 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5424 } 5425 /* Correct for hanging node constraints */ 5426 { 5427 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, perms, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 5428 if (numPointsNew) { 5429 for (f = 0; f < PetscMax(1,Nf); f++) { 5430 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5431 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5432 } 5433 for (f = 0; f < PetscMax(1,Nf); f++) { 5434 if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 5435 else {ierr = PetscSectionGetPointSyms(section,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 5436 } 5437 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5438 numPoints = numPointsNew; 5439 Nind = NindNew; 5440 points = pointsNew; 5441 } 5442 } 5443 /* Calculate indices */ 5444 ierr = DMGetWorkArray(dm, Nind, MPIU_INT, indices);CHKERRQ(ierr); 5445 if (Nf) { 5446 if (outOffsets) { 5447 PetscInt f; 5448 5449 for (f = 0; f <= Nf; f++) { 5450 outOffsets[f] = offsets[f]; 5451 } 5452 } 5453 for (p = 0; p < numPoints; p++) { 5454 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5455 DMPlexGetIndicesPointFields_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, *indices); 5456 } 5457 } else { 5458 for (p = 0, off = 0; p < numPoints; p++) { 5459 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 5460 5461 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5462 DMPlexGetIndicesPoint_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, *indices); 5463 } 5464 } 5465 /* Cleanup points */ 5466 for (f = 0; f < PetscMax(1,Nf); f++) { 5467 if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5468 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 5469 } 5470 if (numPointsNew) { 5471 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, MPIU_INT, &pointsNew);CHKERRQ(ierr); 5472 } else { 5473 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5474 } 5475 if (numIndices) *numIndices = Nind; 5476 PetscFunctionReturn(0); 5477 } 5478 5479 /*@C 5480 DMPlexRestoreClosureIndices - Restore the indices in a vector v for all points in the closure of the given point 5481 5482 Not collective 5483 5484 Input Parameters: 5485 + dm - The DM 5486 . section - The section describing the layout in v, or NULL to use the default section 5487 . globalSection - The section describing the parallel layout in v, or NULL to use the default section 5488 . point - The mesh point 5489 . numIndices - The number of indices 5490 . indices - The indices 5491 - outOffsets - Field offset if not NULL 5492 5493 Level: advanced 5494 5495 .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 5496 @*/ 5497 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices,PetscInt *outOffsets) 5498 { 5499 PetscErrorCode ierr; 5500 5501 PetscFunctionBegin; 5502 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5503 PetscValidPointer(indices, 5); 5504 ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 5505 PetscFunctionReturn(0); 5506 } 5507 5508 /*@C 5509 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 5510 5511 Not collective 5512 5513 Input Parameters: 5514 + dm - The DM 5515 . section - The section describing the layout in v, or NULL to use the default section 5516 . globalSection - The section describing the layout in v, or NULL to use the default global section 5517 . A - The matrix 5518 . point - The point in the DM 5519 . values - The array of values 5520 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 5521 5522 Fortran Notes: 5523 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 5524 5525 Level: intermediate 5526 5527 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 5528 @*/ 5529 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5530 { 5531 DM_Plex *mesh = (DM_Plex*) dm->data; 5532 PetscSection clSection; 5533 IS clPoints; 5534 PetscInt *points = NULL, *newPoints; 5535 const PetscInt *clp; 5536 PetscInt *indices; 5537 PetscInt offsets[32]; 5538 const PetscInt **perms[32] = {NULL}; 5539 const PetscScalar **flips[32] = {NULL}; 5540 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, p, f; 5541 PetscScalar *valCopy = NULL; 5542 PetscScalar *newValues; 5543 PetscErrorCode ierr; 5544 5545 PetscFunctionBegin; 5546 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5547 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 5548 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5549 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 5550 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 5551 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 5552 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5553 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5554 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5555 ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5556 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 5557 PetscInt fdof; 5558 5559 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 5560 for (f = 0; f < numFields; ++f) { 5561 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5562 offsets[f+1] += fdof; 5563 } 5564 numIndices += dof; 5565 } 5566 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 5567 5568 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[numFields], numIndices); 5569 /* Get symmetries */ 5570 for (f = 0; f < PetscMax(1,numFields); f++) { 5571 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5572 else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5573 if (values && flips[f]) { /* may need to apply sign changes to the element matrix */ 5574 PetscInt foffset = offsets[f]; 5575 5576 for (p = 0; p < numPoints; p++) { 5577 PetscInt point = points[2*p], fdof; 5578 const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 5579 5580 if (!numFields) { 5581 ierr = PetscSectionGetDof(section,point,&fdof);CHKERRQ(ierr); 5582 } else { 5583 ierr = PetscSectionGetFieldDof(section,point,f,&fdof);CHKERRQ(ierr); 5584 } 5585 if (flip) { 5586 PetscInt i, j, k; 5587 5588 if (!valCopy) { 5589 ierr = DMGetWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5590 for (j = 0; j < numIndices * numIndices; j++) valCopy[j] = values[j]; 5591 values = valCopy; 5592 } 5593 for (i = 0; i < fdof; i++) { 5594 PetscScalar fval = flip[i]; 5595 5596 for (k = 0; k < numIndices; k++) { 5597 valCopy[numIndices * (foffset + i) + k] *= fval; 5598 valCopy[numIndices * k + (foffset + i)] *= fval; 5599 } 5600 } 5601 } 5602 foffset += fdof; 5603 } 5604 } 5605 } 5606 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,perms,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets,PETSC_TRUE);CHKERRQ(ierr); 5607 if (newNumPoints) { 5608 if (valCopy) { 5609 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5610 } 5611 for (f = 0; f < PetscMax(1,numFields); f++) { 5612 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5613 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5614 } 5615 for (f = 0; f < PetscMax(1,numFields); f++) { 5616 if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 5617 else {ierr = PetscSectionGetPointSyms(section,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 5618 } 5619 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5620 numPoints = newNumPoints; 5621 numIndices = newNumIndices; 5622 points = newPoints; 5623 values = newValues; 5624 } 5625 ierr = DMGetWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 5626 if (numFields) { 5627 for (p = 0; p < numPoints; p++) { 5628 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5629 DMPlexGetIndicesPointFields_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, indices); 5630 } 5631 } else { 5632 for (p = 0, off = 0; p < numPoints; p++) { 5633 const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 5634 ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 5635 DMPlexGetIndicesPoint_Internal(section, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, indices); 5636 } 5637 } 5638 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 5639 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 5640 if (mesh->printFEM > 1) { 5641 PetscInt i; 5642 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 5643 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 5644 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5645 } 5646 if (ierr) { 5647 PetscMPIInt rank; 5648 PetscErrorCode ierr2; 5649 5650 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5651 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5652 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 5653 ierr2 = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr2); 5654 CHKERRQ(ierr); 5655 } 5656 for (f = 0; f < PetscMax(1,numFields); f++) { 5657 if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5658 else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 5659 } 5660 if (newNumPoints) { 5661 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 5662 ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 5663 } 5664 else { 5665 if (valCopy) { 5666 ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 5667 } 5668 ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5669 } 5670 ierr = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 5671 PetscFunctionReturn(0); 5672 } 5673 5674 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 5675 { 5676 DM_Plex *mesh = (DM_Plex*) dmf->data; 5677 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5678 PetscInt *cpoints = NULL; 5679 PetscInt *findices, *cindices; 5680 PetscInt foffsets[32], coffsets[32]; 5681 CellRefiner cellRefiner; 5682 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5683 PetscErrorCode ierr; 5684 5685 PetscFunctionBegin; 5686 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5687 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5688 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5689 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5690 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5691 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5692 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5693 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5694 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5695 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5696 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 5697 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5698 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5699 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5700 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5701 /* Column indices */ 5702 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5703 maxFPoints = numCPoints; 5704 /* Compress out points not in the section */ 5705 /* TODO: Squeeze out points with 0 dof as well */ 5706 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5707 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5708 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5709 cpoints[q*2] = cpoints[p]; 5710 cpoints[q*2+1] = cpoints[p+1]; 5711 ++q; 5712 } 5713 } 5714 numCPoints = q; 5715 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5716 PetscInt fdof; 5717 5718 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5719 if (!dof) continue; 5720 for (f = 0; f < numFields; ++f) { 5721 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5722 coffsets[f+1] += fdof; 5723 } 5724 numCIndices += dof; 5725 } 5726 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5727 /* Row indices */ 5728 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5729 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5730 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 5731 for (r = 0, q = 0; r < numSubcells; ++r) { 5732 /* TODO Map from coarse to fine cells */ 5733 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5734 /* Compress out points not in the section */ 5735 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5736 for (p = 0; p < numFPoints*2; p += 2) { 5737 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5738 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5739 if (!dof) continue; 5740 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5741 if (s < q) continue; 5742 ftotpoints[q*2] = fpoints[p]; 5743 ftotpoints[q*2+1] = fpoints[p+1]; 5744 ++q; 5745 } 5746 } 5747 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5748 } 5749 numFPoints = q; 5750 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5751 PetscInt fdof; 5752 5753 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5754 if (!dof) continue; 5755 for (f = 0; f < numFields; ++f) { 5756 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5757 foffsets[f+1] += fdof; 5758 } 5759 numFIndices += dof; 5760 } 5761 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5762 5763 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 5764 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 5765 ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 5766 ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 5767 if (numFields) { 5768 const PetscInt **permsF[32] = {NULL}; 5769 const PetscInt **permsC[32] = {NULL}; 5770 5771 for (f = 0; f < numFields; f++) { 5772 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 5773 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 5774 } 5775 for (p = 0; p < numFPoints; p++) { 5776 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 5777 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, findices); 5778 } 5779 for (p = 0; p < numCPoints; p++) { 5780 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 5781 DMPlexGetIndicesPointFields_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cindices); 5782 } 5783 for (f = 0; f < numFields; f++) { 5784 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 5785 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 5786 } 5787 } else { 5788 const PetscInt **permsF = NULL; 5789 const PetscInt **permsC = NULL; 5790 5791 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 5792 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 5793 for (p = 0, off = 0; p < numFPoints; p++) { 5794 const PetscInt *perm = permsF ? permsF[p] : NULL; 5795 5796 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 5797 ierr = DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, findices);CHKERRQ(ierr); 5798 } 5799 for (p = 0, off = 0; p < numCPoints; p++) { 5800 const PetscInt *perm = permsC ? permsC[p] : NULL; 5801 5802 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 5803 ierr = DMPlexGetIndicesPoint_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cindices);CHKERRQ(ierr); 5804 } 5805 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 5806 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 5807 } 5808 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 5809 /* TODO: flips */ 5810 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 5811 if (ierr) { 5812 PetscMPIInt rank; 5813 PetscErrorCode ierr2; 5814 5815 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5816 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5817 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 5818 ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 5819 ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 5820 CHKERRQ(ierr); 5821 } 5822 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 5823 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5824 ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 5825 ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 5826 PetscFunctionReturn(0); 5827 } 5828 5829 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 5830 { 5831 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5832 PetscInt *cpoints = NULL; 5833 PetscInt foffsets[32], coffsets[32]; 5834 CellRefiner cellRefiner; 5835 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5836 PetscErrorCode ierr; 5837 5838 PetscFunctionBegin; 5839 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5840 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5841 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5842 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5843 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5844 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5845 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5846 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5847 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5848 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5849 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5850 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5851 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5852 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5853 /* Column indices */ 5854 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5855 maxFPoints = numCPoints; 5856 /* Compress out points not in the section */ 5857 /* TODO: Squeeze out points with 0 dof as well */ 5858 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5859 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5860 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5861 cpoints[q*2] = cpoints[p]; 5862 cpoints[q*2+1] = cpoints[p+1]; 5863 ++q; 5864 } 5865 } 5866 numCPoints = q; 5867 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5868 PetscInt fdof; 5869 5870 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5871 if (!dof) continue; 5872 for (f = 0; f < numFields; ++f) { 5873 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5874 coffsets[f+1] += fdof; 5875 } 5876 numCIndices += dof; 5877 } 5878 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5879 /* Row indices */ 5880 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5881 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5882 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 5883 for (r = 0, q = 0; r < numSubcells; ++r) { 5884 /* TODO Map from coarse to fine cells */ 5885 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5886 /* Compress out points not in the section */ 5887 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5888 for (p = 0; p < numFPoints*2; p += 2) { 5889 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5890 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5891 if (!dof) continue; 5892 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5893 if (s < q) continue; 5894 ftotpoints[q*2] = fpoints[p]; 5895 ftotpoints[q*2+1] = fpoints[p+1]; 5896 ++q; 5897 } 5898 } 5899 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5900 } 5901 numFPoints = q; 5902 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5903 PetscInt fdof; 5904 5905 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5906 if (!dof) continue; 5907 for (f = 0; f < numFields; ++f) { 5908 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5909 foffsets[f+1] += fdof; 5910 } 5911 numFIndices += dof; 5912 } 5913 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5914 5915 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 5916 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 5917 if (numFields) { 5918 const PetscInt **permsF[32] = {NULL}; 5919 const PetscInt **permsC[32] = {NULL}; 5920 5921 for (f = 0; f < numFields; f++) { 5922 ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 5923 ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 5924 } 5925 for (p = 0; p < numFPoints; p++) { 5926 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 5927 DMPlexGetIndicesPointFields_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, findices); 5928 } 5929 for (p = 0; p < numCPoints; p++) { 5930 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 5931 DMPlexGetIndicesPointFields_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cindices); 5932 } 5933 for (f = 0; f < numFields; f++) { 5934 ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 5935 ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 5936 } 5937 } else { 5938 const PetscInt **permsF = NULL; 5939 const PetscInt **permsC = NULL; 5940 5941 ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 5942 ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 5943 for (p = 0, off = 0; p < numFPoints; p++) { 5944 const PetscInt *perm = permsF ? permsF[p] : NULL; 5945 5946 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 5947 DMPlexGetIndicesPoint_Internal(fsection, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, findices); 5948 } 5949 for (p = 0, off = 0; p < numCPoints; p++) { 5950 const PetscInt *perm = permsC ? permsC[p] : NULL; 5951 5952 ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 5953 DMPlexGetIndicesPoint_Internal(csection, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cindices); 5954 } 5955 ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 5956 ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 5957 } 5958 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 5959 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5960 PetscFunctionReturn(0); 5961 } 5962 5963 /*@ 5964 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 5965 5966 Input Parameter: 5967 . dm - The DMPlex object 5968 5969 Output Parameters: 5970 + cMax - The first hybrid cell 5971 . fMax - The first hybrid face 5972 . eMax - The first hybrid edge 5973 - vMax - The first hybrid vertex 5974 5975 Level: developer 5976 5977 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 5978 @*/ 5979 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 5980 { 5981 DM_Plex *mesh = (DM_Plex*) dm->data; 5982 PetscInt dim; 5983 PetscErrorCode ierr; 5984 5985 PetscFunctionBegin; 5986 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5987 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5988 if (cMax) *cMax = mesh->hybridPointMax[dim]; 5989 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 5990 if (eMax) *eMax = mesh->hybridPointMax[1]; 5991 if (vMax) *vMax = mesh->hybridPointMax[0]; 5992 PetscFunctionReturn(0); 5993 } 5994 5995 /*@ 5996 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 5997 5998 Input Parameters: 5999 . dm - The DMPlex object 6000 . cMax - The first hybrid cell 6001 . fMax - The first hybrid face 6002 . eMax - The first hybrid edge 6003 - vMax - The first hybrid vertex 6004 6005 Level: developer 6006 6007 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 6008 @*/ 6009 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 6010 { 6011 DM_Plex *mesh = (DM_Plex*) dm->data; 6012 PetscInt dim; 6013 PetscErrorCode ierr; 6014 6015 PetscFunctionBegin; 6016 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6017 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6018 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 6019 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 6020 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 6021 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 6022 PetscFunctionReturn(0); 6023 } 6024 6025 /*@C 6026 DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 6027 6028 Input Parameter: 6029 . dm - The DMPlex object 6030 6031 Output Parameter: 6032 . cellHeight - The height of a cell 6033 6034 Level: developer 6035 6036 .seealso DMPlexSetVTKCellHeight() 6037 @*/ 6038 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 6039 { 6040 DM_Plex *mesh = (DM_Plex*) dm->data; 6041 6042 PetscFunctionBegin; 6043 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6044 PetscValidPointer(cellHeight, 2); 6045 *cellHeight = mesh->vtkCellHeight; 6046 PetscFunctionReturn(0); 6047 } 6048 6049 /*@C 6050 DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 6051 6052 Input Parameters: 6053 + dm - The DMPlex object 6054 - cellHeight - The height of a cell 6055 6056 Level: developer 6057 6058 .seealso DMPlexGetVTKCellHeight() 6059 @*/ 6060 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 6061 { 6062 DM_Plex *mesh = (DM_Plex*) dm->data; 6063 6064 PetscFunctionBegin; 6065 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6066 mesh->vtkCellHeight = cellHeight; 6067 PetscFunctionReturn(0); 6068 } 6069 6070 /* We can easily have a form that takes an IS instead */ 6071 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 6072 { 6073 PetscSection section, globalSection; 6074 PetscInt *numbers, p; 6075 PetscErrorCode ierr; 6076 6077 PetscFunctionBegin; 6078 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6079 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 6080 for (p = pStart; p < pEnd; ++p) { 6081 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 6082 } 6083 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 6084 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 6085 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 6086 for (p = pStart; p < pEnd; ++p) { 6087 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 6088 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 6089 else numbers[p-pStart] += shift; 6090 } 6091 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 6092 if (globalSize) { 6093 PetscLayout layout; 6094 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 6095 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 6096 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 6097 } 6098 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6099 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 6100 PetscFunctionReturn(0); 6101 } 6102 6103 PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 6104 { 6105 PetscInt cellHeight, cStart, cEnd, cMax; 6106 PetscErrorCode ierr; 6107 6108 PetscFunctionBegin; 6109 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 6110 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6111 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6112 if (cMax >= 0 && !includeHybrid) cEnd = PetscMin(cEnd, cMax); 6113 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 6114 PetscFunctionReturn(0); 6115 } 6116 6117 /*@C 6118 DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 6119 6120 Input Parameter: 6121 . dm - The DMPlex object 6122 6123 Output Parameter: 6124 . globalCellNumbers - Global cell numbers for all cells on this process 6125 6126 Level: developer 6127 6128 .seealso DMPlexGetVertexNumbering() 6129 @*/ 6130 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 6131 { 6132 DM_Plex *mesh = (DM_Plex*) dm->data; 6133 PetscErrorCode ierr; 6134 6135 PetscFunctionBegin; 6136 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6137 if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 6138 *globalCellNumbers = mesh->globalCellNumbers; 6139 PetscFunctionReturn(0); 6140 } 6141 6142 PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 6143 { 6144 PetscInt vStart, vEnd, vMax; 6145 PetscErrorCode ierr; 6146 6147 PetscFunctionBegin; 6148 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6149 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6150 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 6151 if (vMax >= 0 && !includeHybrid) vEnd = PetscMin(vEnd, vMax); 6152 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 6153 PetscFunctionReturn(0); 6154 } 6155 6156 /*@C 6157 DMPlexGetVertexNumbering - Get a global certex numbering for all vertices on this process 6158 6159 Input Parameter: 6160 . dm - The DMPlex object 6161 6162 Output Parameter: 6163 . globalVertexNumbers - Global vertex numbers for all vertices on this process 6164 6165 Level: developer 6166 6167 .seealso DMPlexGetCellNumbering() 6168 @*/ 6169 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 6170 { 6171 DM_Plex *mesh = (DM_Plex*) dm->data; 6172 PetscErrorCode ierr; 6173 6174 PetscFunctionBegin; 6175 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6176 if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 6177 *globalVertexNumbers = mesh->globalVertexNumbers; 6178 PetscFunctionReturn(0); 6179 } 6180 6181 /*@C 6182 DMPlexCreatePointNumbering - Create a global numbering for all points on this process 6183 6184 Input Parameter: 6185 . dm - The DMPlex object 6186 6187 Output Parameter: 6188 . globalPointNumbers - Global numbers for all points on this process 6189 6190 Level: developer 6191 6192 .seealso DMPlexGetCellNumbering() 6193 @*/ 6194 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 6195 { 6196 IS nums[4]; 6197 PetscInt depths[4]; 6198 PetscInt depth, d, shift = 0; 6199 PetscErrorCode ierr; 6200 6201 PetscFunctionBegin; 6202 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6203 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6204 /* For unstratified meshes use dim instead of depth */ 6205 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 6206 depths[0] = depth; depths[1] = 0; 6207 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 6208 for (d = 0; d <= depth; ++d) { 6209 PetscInt pStart, pEnd, gsize; 6210 6211 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 6212 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 6213 shift += gsize; 6214 } 6215 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 6216 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 6217 PetscFunctionReturn(0); 6218 } 6219 6220 6221 /*@ 6222 DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 6223 6224 Input Parameter: 6225 . dm - The DMPlex object 6226 6227 Output Parameter: 6228 . ranks - The rank field 6229 6230 Options Database Keys: 6231 . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 6232 6233 Level: intermediate 6234 6235 .seealso: DMView() 6236 @*/ 6237 PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 6238 { 6239 DM rdm; 6240 PetscDS prob; 6241 PetscFE fe; 6242 PetscScalar *r; 6243 PetscMPIInt rank; 6244 PetscInt dim, cStart, cEnd, c; 6245 PetscErrorCode ierr; 6246 6247 PetscFunctionBeginUser; 6248 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 6249 ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 6250 ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 6251 ierr = PetscFECreateDefault(rdm, dim, 1, PETSC_TRUE, NULL, -1, &fe);CHKERRQ(ierr); 6252 ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 6253 ierr = DMGetDS(rdm, &prob);CHKERRQ(ierr); 6254 ierr = PetscDSSetDiscretization(prob, 0, (PetscObject) fe);CHKERRQ(ierr); 6255 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 6256 ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6257 ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 6258 ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 6259 ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 6260 for (c = cStart; c < cEnd; ++c) { 6261 PetscScalar *lr; 6262 6263 ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 6264 *lr = rank; 6265 } 6266 ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 6267 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 6268 PetscFunctionReturn(0); 6269 } 6270 6271 /*@ 6272 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 6273 6274 Input Parameter: 6275 . dm - The DMPlex object 6276 6277 Note: This is a useful diagnostic when creating meshes programmatically. 6278 6279 Level: developer 6280 6281 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 6282 @*/ 6283 PetscErrorCode DMPlexCheckSymmetry(DM dm) 6284 { 6285 PetscSection coneSection, supportSection; 6286 const PetscInt *cone, *support; 6287 PetscInt coneSize, c, supportSize, s; 6288 PetscInt pStart, pEnd, p, csize, ssize; 6289 PetscErrorCode ierr; 6290 6291 PetscFunctionBegin; 6292 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6293 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 6294 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 6295 /* Check that point p is found in the support of its cone points, and vice versa */ 6296 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6297 for (p = pStart; p < pEnd; ++p) { 6298 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 6299 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 6300 for (c = 0; c < coneSize; ++c) { 6301 PetscBool dup = PETSC_FALSE; 6302 PetscInt d; 6303 for (d = c-1; d >= 0; --d) { 6304 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 6305 } 6306 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 6307 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 6308 for (s = 0; s < supportSize; ++s) { 6309 if (support[s] == p) break; 6310 } 6311 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 6312 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 6313 for (s = 0; s < coneSize; ++s) { 6314 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 6315 } 6316 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6317 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 6318 for (s = 0; s < supportSize; ++s) { 6319 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 6320 } 6321 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6322 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 6323 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 6324 } 6325 } 6326 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 6327 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 6328 for (s = 0; s < supportSize; ++s) { 6329 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6330 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6331 for (c = 0; c < coneSize; ++c) { 6332 if (cone[c] == p) break; 6333 } 6334 if (c >= coneSize) { 6335 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 6336 for (c = 0; c < supportSize; ++c) { 6337 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 6338 } 6339 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6340 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 6341 for (c = 0; c < coneSize; ++c) { 6342 ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 6343 } 6344 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6345 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 6346 } 6347 } 6348 } 6349 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 6350 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 6351 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 6352 PetscFunctionReturn(0); 6353 } 6354 6355 /*@ 6356 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 6357 6358 Input Parameters: 6359 + dm - The DMPlex object 6360 . isSimplex - Are the cells simplices or tensor products 6361 - cellHeight - Normally 0 6362 6363 Note: This is a useful diagnostic when creating meshes programmatically. 6364 6365 Level: developer 6366 6367 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 6368 @*/ 6369 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 6370 { 6371 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 6372 PetscErrorCode ierr; 6373 6374 PetscFunctionBegin; 6375 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6376 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6377 switch (dim) { 6378 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 6379 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 6380 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 6381 default: 6382 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %D", dim); 6383 } 6384 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6385 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6386 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 6387 cMax = cMax >= 0 ? cMax : cEnd; 6388 for (c = cStart; c < cMax; ++c) { 6389 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 6390 6391 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6392 for (cl = 0; cl < closureSize*2; cl += 2) { 6393 const PetscInt p = closure[cl]; 6394 if ((p >= vStart) && (p < vEnd)) ++coneSize; 6395 } 6396 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6397 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D vertices != %D", c, coneSize, numCorners); 6398 } 6399 for (c = cMax; c < cEnd; ++c) { 6400 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 6401 6402 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6403 for (cl = 0; cl < closureSize*2; cl += 2) { 6404 const PetscInt p = closure[cl]; 6405 if ((p >= vStart) && (p < vEnd)) ++coneSize; 6406 } 6407 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6408 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %D has %D vertices > %D", c, coneSize, numHybridCorners); 6409 } 6410 PetscFunctionReturn(0); 6411 } 6412 6413 /*@ 6414 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 6415 6416 Input Parameters: 6417 + dm - The DMPlex object 6418 . isSimplex - Are the cells simplices or tensor products 6419 - cellHeight - Normally 0 6420 6421 Note: This is a useful diagnostic when creating meshes programmatically. 6422 6423 Level: developer 6424 6425 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 6426 @*/ 6427 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 6428 { 6429 PetscInt pMax[4]; 6430 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 6431 PetscErrorCode ierr; 6432 6433 PetscFunctionBegin; 6434 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6435 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6436 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6437 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 6438 for (h = cellHeight; h < dim; ++h) { 6439 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 6440 for (c = cStart; c < cEnd; ++c) { 6441 const PetscInt *cone, *ornt, *faces; 6442 PetscInt numFaces, faceSize, coneSize,f; 6443 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 6444 6445 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 6446 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 6447 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6448 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6449 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6450 for (cl = 0; cl < closureSize*2; cl += 2) { 6451 const PetscInt p = closure[cl]; 6452 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 6453 } 6454 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 6455 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D faces but should have %D", c, coneSize, numFaces); 6456 for (f = 0; f < numFaces; ++f) { 6457 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 6458 6459 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 6460 for (cl = 0; cl < fclosureSize*2; cl += 2) { 6461 const PetscInt p = fclosure[cl]; 6462 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 6463 } 6464 if (fnumCorners != faceSize) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D (%D) of cell %D has %D vertices but should have %D", cone[f], f, c, fnumCorners, faceSize); 6465 for (v = 0; v < fnumCorners; ++v) { 6466 if (fclosure[v] != faces[f*faceSize+v]) SETERRQ6(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D (%d) of cell %D vertex %D, %D != %D", cone[f], f, c, v, fclosure[v], faces[f*faceSize+v]); 6467 } 6468 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 6469 } 6470 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 6471 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6472 } 6473 } 6474 PetscFunctionReturn(0); 6475 } 6476 6477 /* Pointwise interpolation 6478 Just code FEM for now 6479 u^f = I u^c 6480 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 6481 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 6482 I_{ij} = psi^f_i phi^c_j 6483 */ 6484 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 6485 { 6486 PetscSection gsc, gsf; 6487 PetscInt m, n; 6488 void *ctx; 6489 DM cdm; 6490 PetscBool regular; 6491 PetscErrorCode ierr; 6492 6493 PetscFunctionBegin; 6494 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 6495 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 6496 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 6497 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 6498 6499 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 6500 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6501 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 6502 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 6503 6504 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 6505 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 6506 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 6507 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 6508 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 6509 /* Use naive scaling */ 6510 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 6511 PetscFunctionReturn(0); 6512 } 6513 6514 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 6515 { 6516 PetscErrorCode ierr; 6517 VecScatter ctx; 6518 6519 PetscFunctionBegin; 6520 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 6521 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 6522 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 6523 PetscFunctionReturn(0); 6524 } 6525 6526 PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 6527 { 6528 PetscSection gsc, gsf; 6529 PetscInt m, n; 6530 void *ctx; 6531 DM cdm; 6532 PetscBool regular; 6533 PetscErrorCode ierr; 6534 6535 PetscFunctionBegin; 6536 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 6537 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 6538 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 6539 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 6540 6541 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 6542 ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 6543 ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 6544 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 6545 6546 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 6547 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 6548 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 6549 else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 6550 ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 6551 PetscFunctionReturn(0); 6552 } 6553 6554 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 6555 { 6556 PetscSection section; 6557 IS *bcPoints, *bcComps; 6558 PetscBool *isFE; 6559 PetscInt *bcFields, *numComp, *numDof; 6560 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 6561 PetscInt cStart, cEnd, cEndInterior; 6562 PetscErrorCode ierr; 6563 6564 PetscFunctionBegin; 6565 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 6566 /* FE and FV boundary conditions are handled slightly differently */ 6567 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 6568 for (f = 0; f < numFields; ++f) { 6569 PetscObject obj; 6570 PetscClassId id; 6571 6572 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 6573 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 6574 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 6575 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 6576 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f); 6577 } 6578 /* Allocate boundary point storage for FEM boundaries */ 6579 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6580 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6581 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6582 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 6583 ierr = PetscDSGetNumBoundary(dm->prob, &numBd);CHKERRQ(ierr); 6584 if (!numFields && numBd) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "number of fields is zero and number of boundary conditions is nonzero (this should never happen)"); 6585 for (bd = 0; bd < numBd; ++bd) { 6586 PetscInt field; 6587 DMBoundaryConditionType type; 6588 const char *labelName; 6589 DMLabel label; 6590 6591 ierr = PetscDSGetBoundary(dm->prob, bd, &type, NULL, &labelName, &field, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 6592 ierr = DMGetLabel(dm,labelName,&label);CHKERRQ(ierr); 6593 if (label && isFE[field] && (type & DM_BC_ESSENTIAL)) ++numBC; 6594 } 6595 /* Add ghost cell boundaries for FVM */ 6596 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 6597 ierr = PetscCalloc3(numBC,&bcFields,numBC,&bcPoints,numBC,&bcComps);CHKERRQ(ierr); 6598 /* Constrain ghost cells for FV */ 6599 for (f = 0; f < numFields; ++f) { 6600 PetscInt *newidx, c; 6601 6602 if (isFE[f] || cEndInterior < 0) continue; 6603 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 6604 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 6605 bcFields[bc] = f; 6606 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 6607 } 6608 /* Handle FEM Dirichlet boundaries */ 6609 for (bd = 0; bd < numBd; ++bd) { 6610 const char *bdLabel; 6611 DMLabel label; 6612 const PetscInt *comps; 6613 const PetscInt *values; 6614 PetscInt bd2, field, numComps, numValues; 6615 DMBoundaryConditionType type; 6616 PetscBool duplicate = PETSC_FALSE; 6617 6618 ierr = PetscDSGetBoundary(dm->prob, bd, &type, NULL, &bdLabel, &field, &numComps, &comps, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 6619 ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 6620 if (!isFE[field] || !label) continue; 6621 /* Only want to modify label once */ 6622 for (bd2 = 0; bd2 < bd; ++bd2) { 6623 const char *bdname; 6624 ierr = PetscDSGetBoundary(dm->prob, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 6625 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 6626 if (duplicate) break; 6627 } 6628 if (!duplicate && (isFE[field])) { 6629 /* don't complete cells, which are just present to give orientation to the boundary */ 6630 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 6631 } 6632 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 6633 if (type & DM_BC_ESSENTIAL) { 6634 PetscInt *newidx; 6635 PetscInt n, newn = 0, p, v; 6636 6637 bcFields[bc] = field; 6638 if (numComps) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc]);CHKERRQ(ierr);} 6639 for (v = 0; v < numValues; ++v) { 6640 IS tmp; 6641 const PetscInt *idx; 6642 6643 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 6644 if (!tmp) continue; 6645 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 6646 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 6647 if (isFE[field]) { 6648 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 6649 } else { 6650 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 6651 } 6652 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 6653 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 6654 } 6655 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 6656 newn = 0; 6657 for (v = 0; v < numValues; ++v) { 6658 IS tmp; 6659 const PetscInt *idx; 6660 6661 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 6662 if (!tmp) continue; 6663 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 6664 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 6665 if (isFE[field]) { 6666 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 6667 } else { 6668 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 6669 } 6670 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 6671 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 6672 } 6673 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 6674 } 6675 } 6676 /* Handle discretization */ 6677 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 6678 for (f = 0; f < numFields; ++f) { 6679 PetscObject obj; 6680 6681 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 6682 if (isFE[f]) { 6683 PetscFE fe = (PetscFE) obj; 6684 const PetscInt *numFieldDof; 6685 PetscInt d; 6686 6687 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 6688 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 6689 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 6690 } else { 6691 PetscFV fv = (PetscFV) obj; 6692 6693 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 6694 numDof[f*(dim+1)+dim] = numComp[f]; 6695 } 6696 } 6697 for (f = 0; f < numFields; ++f) { 6698 PetscInt d; 6699 for (d = 1; d < dim; ++d) { 6700 if ((numDof[f*(dim+1)+d] > 0) && (depth < dim)) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated when unknowns are specified on edges or faces."); 6701 } 6702 } 6703 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion);CHKERRQ(ierr); 6704 for (f = 0; f < numFields; ++f) { 6705 PetscFE fe; 6706 const char *name; 6707 6708 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 6709 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 6710 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 6711 } 6712 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 6713 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6714 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);ierr = ISDestroy(&bcComps[bc]);CHKERRQ(ierr);} 6715 ierr = PetscFree3(bcFields,bcPoints,bcComps);CHKERRQ(ierr); 6716 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 6717 ierr = PetscFree(isFE);CHKERRQ(ierr); 6718 PetscFunctionReturn(0); 6719 } 6720 6721 /*@ 6722 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 6723 6724 Input Parameter: 6725 . dm - The DMPlex object 6726 6727 Output Parameter: 6728 . regular - The flag 6729 6730 Level: intermediate 6731 6732 .seealso: DMPlexSetRegularRefinement() 6733 @*/ 6734 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 6735 { 6736 PetscFunctionBegin; 6737 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6738 PetscValidPointer(regular, 2); 6739 *regular = ((DM_Plex *) dm->data)->regularRefinement; 6740 PetscFunctionReturn(0); 6741 } 6742 6743 /*@ 6744 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 6745 6746 Input Parameters: 6747 + dm - The DMPlex object 6748 - regular - The flag 6749 6750 Level: intermediate 6751 6752 .seealso: DMPlexGetRegularRefinement() 6753 @*/ 6754 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 6755 { 6756 PetscFunctionBegin; 6757 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6758 ((DM_Plex *) dm->data)->regularRefinement = regular; 6759 PetscFunctionReturn(0); 6760 } 6761 6762 /* anchors */ 6763 /*@ 6764 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 6765 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 6766 6767 not collective 6768 6769 Input Parameters: 6770 . dm - The DMPlex object 6771 6772 Output Parameters: 6773 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 6774 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 6775 6776 6777 Level: intermediate 6778 6779 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 6780 @*/ 6781 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 6782 { 6783 DM_Plex *plex = (DM_Plex *)dm->data; 6784 PetscErrorCode ierr; 6785 6786 PetscFunctionBegin; 6787 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6788 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 6789 if (anchorSection) *anchorSection = plex->anchorSection; 6790 if (anchorIS) *anchorIS = plex->anchorIS; 6791 PetscFunctionReturn(0); 6792 } 6793 6794 /*@ 6795 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 6796 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 6797 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 6798 6799 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 6800 DMGetConstraints() and filling in the entries in the constraint matrix. 6801 6802 collective on dm 6803 6804 Input Parameters: 6805 + dm - The DMPlex object 6806 . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. Must have a local communicator (PETSC_COMM_SELF or derivative). 6807 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 6808 6809 The reference counts of anchorSection and anchorIS are incremented. 6810 6811 Level: intermediate 6812 6813 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 6814 @*/ 6815 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 6816 { 6817 DM_Plex *plex = (DM_Plex *)dm->data; 6818 PetscMPIInt result; 6819 PetscErrorCode ierr; 6820 6821 PetscFunctionBegin; 6822 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6823 if (anchorSection) { 6824 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 6825 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 6826 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 6827 } 6828 if (anchorIS) { 6829 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 6830 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 6831 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 6832 } 6833 6834 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 6835 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 6836 plex->anchorSection = anchorSection; 6837 6838 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 6839 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 6840 plex->anchorIS = anchorIS; 6841 6842 #if defined(PETSC_USE_DEBUG) 6843 if (anchorIS && anchorSection) { 6844 PetscInt size, a, pStart, pEnd; 6845 const PetscInt *anchors; 6846 6847 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 6848 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 6849 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 6850 for (a = 0; a < size; a++) { 6851 PetscInt p; 6852 6853 p = anchors[a]; 6854 if (p >= pStart && p < pEnd) { 6855 PetscInt dof; 6856 6857 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 6858 if (dof) { 6859 PetscErrorCode ierr2; 6860 6861 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 6862 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 6863 } 6864 } 6865 } 6866 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 6867 } 6868 #endif 6869 /* reset the generic constraints */ 6870 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 6871 PetscFunctionReturn(0); 6872 } 6873 6874 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 6875 { 6876 PetscSection anchorSection; 6877 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 6878 PetscErrorCode ierr; 6879 6880 PetscFunctionBegin; 6881 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6882 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 6883 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 6884 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 6885 if (numFields) { 6886 PetscInt f; 6887 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 6888 6889 for (f = 0; f < numFields; f++) { 6890 PetscInt numComp; 6891 6892 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 6893 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 6894 } 6895 } 6896 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 6897 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 6898 pStart = PetscMax(pStart,sStart); 6899 pEnd = PetscMin(pEnd,sEnd); 6900 pEnd = PetscMax(pStart,pEnd); 6901 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 6902 for (p = pStart; p < pEnd; p++) { 6903 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 6904 if (dof) { 6905 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 6906 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 6907 for (f = 0; f < numFields; f++) { 6908 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 6909 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 6910 } 6911 } 6912 } 6913 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 6914 PetscFunctionReturn(0); 6915 } 6916 6917 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 6918 { 6919 PetscSection aSec; 6920 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 6921 const PetscInt *anchors; 6922 PetscInt numFields, f; 6923 IS aIS; 6924 PetscErrorCode ierr; 6925 6926 PetscFunctionBegin; 6927 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6928 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 6929 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 6930 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 6931 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 6932 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 6933 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6934 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6935 /* cSec will be a subset of aSec and section */ 6936 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 6937 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 6938 i[0] = 0; 6939 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 6940 for (p = pStart; p < pEnd; p++) { 6941 PetscInt rDof, rOff, r; 6942 6943 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6944 if (!rDof) continue; 6945 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6946 if (numFields) { 6947 for (f = 0; f < numFields; f++) { 6948 annz = 0; 6949 for (r = 0; r < rDof; r++) { 6950 a = anchors[rOff + r]; 6951 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6952 annz += aDof; 6953 } 6954 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6955 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 6956 for (q = 0; q < dof; q++) { 6957 i[off + q + 1] = i[off + q] + annz; 6958 } 6959 } 6960 } 6961 else { 6962 annz = 0; 6963 for (q = 0; q < dof; q++) { 6964 a = anchors[off + q]; 6965 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6966 annz += aDof; 6967 } 6968 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6969 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 6970 for (q = 0; q < dof; q++) { 6971 i[off + q + 1] = i[off + q] + annz; 6972 } 6973 } 6974 } 6975 nnz = i[m]; 6976 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 6977 offset = 0; 6978 for (p = pStart; p < pEnd; p++) { 6979 if (numFields) { 6980 for (f = 0; f < numFields; f++) { 6981 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6982 for (q = 0; q < dof; q++) { 6983 PetscInt rDof, rOff, r; 6984 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6985 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6986 for (r = 0; r < rDof; r++) { 6987 PetscInt s; 6988 6989 a = anchors[rOff + r]; 6990 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6991 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 6992 for (s = 0; s < aDof; s++) { 6993 j[offset++] = aOff + s; 6994 } 6995 } 6996 } 6997 } 6998 } 6999 else { 7000 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 7001 for (q = 0; q < dof; q++) { 7002 PetscInt rDof, rOff, r; 7003 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 7004 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 7005 for (r = 0; r < rDof; r++) { 7006 PetscInt s; 7007 7008 a = anchors[rOff + r]; 7009 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 7010 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 7011 for (s = 0; s < aDof; s++) { 7012 j[offset++] = aOff + s; 7013 } 7014 } 7015 } 7016 } 7017 } 7018 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 7019 ierr = PetscFree(i);CHKERRQ(ierr); 7020 ierr = PetscFree(j);CHKERRQ(ierr); 7021 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 7022 PetscFunctionReturn(0); 7023 } 7024 7025 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 7026 { 7027 DM_Plex *plex = (DM_Plex *)dm->data; 7028 PetscSection anchorSection, section, cSec; 7029 Mat cMat; 7030 PetscErrorCode ierr; 7031 7032 PetscFunctionBegin; 7033 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7034 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 7035 if (anchorSection) { 7036 PetscDS ds; 7037 PetscInt nf; 7038 7039 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 7040 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 7041 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 7042 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 7043 ierr = PetscDSGetNumFields(ds,&nf);CHKERRQ(ierr); 7044 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 7045 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 7046 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 7047 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 7048 } 7049 PetscFunctionReturn(0); 7050 } 7051