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