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