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