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