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