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