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