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