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