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