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