1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 #include <petsc-private/vecimpl.h> 4 #include <petsc-private/isimpl.h> 5 6 /* Logging support */ 7 PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 8 9 extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 10 extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "VecView_Plex_Local" 14 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 15 { 16 DM dm; 17 PetscBool isvtk; 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 22 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 23 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 24 if (isvtk) { 25 PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 26 PetscSection section; 27 PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 28 29 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 30 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 31 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 32 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, NULL);CHKERRQ(ierr); 33 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, NULL);CHKERRQ(ierr); 34 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 35 /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 36 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 37 if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 38 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 39 if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 40 ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 41 } else if (cdof && vdof) { 42 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 43 } else if (cdof) { 44 /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 45 * vector or just happens to have the same number of dofs as the dimension. */ 46 if (cdof == dim) { 47 ft = PETSC_VTK_CELL_VECTOR_FIELD; 48 } else { 49 ft = PETSC_VTK_CELL_FIELD; 50 } 51 } else if (vdof) { 52 if (vdof == dim) { 53 ft = PETSC_VTK_POINT_VECTOR_FIELD; 54 } else { 55 ft = PETSC_VTK_POINT_FIELD; 56 } 57 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 58 59 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 60 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 61 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 62 } else { 63 PetscBool isseq; 64 65 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 66 if (isseq) { 67 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 68 } else { 69 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 70 } 71 } 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "VecView_Plex" 77 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 78 { 79 DM dm; 80 PetscBool isvtk; 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 85 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 86 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 87 if (isvtk) { 88 Vec locv; 89 const char *name; 90 91 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 92 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 93 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 94 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 95 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 96 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 97 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 98 } else { 99 PetscBool isseq; 100 101 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 102 if (isseq) { 103 ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 104 } else { 105 ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 106 } 107 } 108 PetscFunctionReturn(0); 109 } 110 111 #undef __FUNCT__ 112 #define __FUNCT__ "DMPlexView_Ascii" 113 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 114 { 115 DM_Plex *mesh = (DM_Plex*) dm->data; 116 DM cdm; 117 DMLabel markers; 118 PetscSection coordSection; 119 Vec coordinates; 120 PetscViewerFormat format; 121 PetscErrorCode ierr; 122 123 PetscFunctionBegin; 124 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 125 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 126 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 127 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 128 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 129 const char *name; 130 PetscInt maxConeSize, maxSupportSize; 131 PetscInt pStart, pEnd, p; 132 PetscMPIInt rank, size; 133 134 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 135 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 136 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 137 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 138 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 139 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 140 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 141 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 142 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 143 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 144 for (p = pStart; p < pEnd; ++p) { 145 PetscInt dof, off, s; 146 147 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 148 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 149 for (s = off; s < off+dof; ++s) { 150 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 151 } 152 } 153 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 154 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 155 for (p = pStart; p < pEnd; ++p) { 156 PetscInt dof, off, c; 157 158 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 159 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 160 for (c = off; c < off+dof; ++c) { 161 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 162 } 163 } 164 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 165 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 166 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 167 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 168 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 169 if (size > 1) { 170 PetscSF sf; 171 172 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 173 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 174 } 175 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 176 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 177 const char *name; 178 const char *colors[3] = {"red", "blue", "green"}; 179 const int numColors = 3; 180 PetscReal scale = 2.0; 181 PetscScalar *coords; 182 PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 183 PetscMPIInt rank, size; 184 185 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 186 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 187 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 188 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190 ierr = PetscViewerASCIIPrintf(viewer, "\ 191 \\documentclass[crop,multi=false]{standalone}\n\n\ 192 \\usepackage{tikz}\n\ 193 \\usepackage{pgflibraryshapes}\n\ 194 \\usetikzlibrary{backgrounds}\n\ 195 \\usetikzlibrary{arrows}\n\ 196 \\begin{document}\n\ 197 \\section{%s}\n\ 198 \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 200 for (p = 0; p < size; ++p) { 201 if (p > 0 && p == size-1) { 202 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 203 } else if (p > 0) { 204 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 205 } 206 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 207 } 208 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\ 209 \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr); 210 /* Plot vertices */ 211 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214 for (v = vStart; v < vEnd; ++v) { 215 PetscInt off, dof, d; 216 217 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220 for (d = 0; d < dof; ++d) { 221 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223 } 224 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225 } 226 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229 /* Plot edges */ 230 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233 for (e = eStart; e < eEnd; ++e) { 234 const PetscInt *cone; 235 PetscInt coneSize, offA, offB, dof, d; 236 237 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 239 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 240 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 241 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 242 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 243 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 244 for (d = 0; d < dof; ++d) { 245 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 246 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 247 } 248 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 249 } 250 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 251 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 252 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 253 /* Plot cells */ 254 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 255 for (c = cStart; c < cEnd; ++c) { 256 PetscInt *closure = NULL; 257 PetscInt closureSize, firstPoint = -1; 258 259 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261 for (p = 0; p < closureSize*2; p += 2) { 262 const PetscInt point = closure[p]; 263 264 if ((point < vStart) || (point >= vEnd)) continue; 265 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267 if (firstPoint < 0) firstPoint = point; 268 } 269 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 276 } else { 277 MPI_Comm comm; 278 PetscInt *sizes; 279 PetscInt locDepth, depth, dim, d; 280 PetscInt pStart, pEnd, p; 281 PetscInt numLabels, l; 282 PetscMPIInt size; 283 284 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 285 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 286 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 287 ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 288 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 289 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 290 ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 291 if (depth == 1) { 292 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 293 pEnd = pEnd - pStart; 294 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 295 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 296 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 297 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 298 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 299 pEnd = pEnd - pStart; 300 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 301 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 302 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 303 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 304 } else { 305 for (d = 0; d <= dim; d++) { 306 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 307 pEnd = pEnd - pStart; 308 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 309 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 310 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 311 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 312 } 313 } 314 ierr = PetscFree(sizes);CHKERRQ(ierr); 315 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 316 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 317 for (l = 0; l < numLabels; ++l) { 318 DMLabel label; 319 const char *name; 320 IS valueIS; 321 const PetscInt *values; 322 PetscInt numValues, v; 323 324 ierr = DMPlexGetLabelName(dm, l, &name);CHKERRQ(ierr); 325 ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr); 326 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 327 ierr = PetscViewerASCIIPrintf(viewer, " %s: %d strata of sizes (", name, numValues);CHKERRQ(ierr); 328 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 329 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 330 for (v = 0; v < numValues; ++v) { 331 PetscInt size; 332 333 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 334 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 335 ierr = PetscViewerASCIIPrintf(viewer, "%d", size);CHKERRQ(ierr); 336 } 337 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 338 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 339 } 340 } 341 PetscFunctionReturn(0); 342 } 343 344 #undef __FUNCT__ 345 #define __FUNCT__ "DMView_Plex" 346 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 347 { 348 PetscBool iascii, isbinary; 349 PetscErrorCode ierr; 350 351 PetscFunctionBegin; 352 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 353 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 354 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 355 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 356 if (iascii) { 357 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 358 #if 0 359 } else if (isbinary) { 360 ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 361 #endif 362 } 363 PetscFunctionReturn(0); 364 } 365 366 #undef __FUNCT__ 367 #define __FUNCT__ "DMDestroy_Plex" 368 PetscErrorCode DMDestroy_Plex(DM dm) 369 { 370 DM_Plex *mesh = (DM_Plex*) dm->data; 371 DMLabel next = mesh->labels; 372 PetscErrorCode ierr; 373 374 PetscFunctionBegin; 375 if (--mesh->refct > 0) PetscFunctionReturn(0); 376 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 377 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 378 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 379 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 380 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 381 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 382 while (next) { 383 DMLabel tmp = next->next; 384 385 ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 386 next = tmp; 387 } 388 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 389 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 390 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 391 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 392 ierr = PetscFree(mesh);CHKERRQ(ierr); 393 PetscFunctionReturn(0); 394 } 395 396 #undef __FUNCT__ 397 #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 398 PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 399 { 400 const PetscInt *support = NULL; 401 PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 402 PetscErrorCode ierr; 403 404 PetscFunctionBegin; 405 if (useClosure) { 406 ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 407 ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 408 for (s = 0; s < supportSize; ++s) { 409 const PetscInt *cone = NULL; 410 PetscInt coneSize, c, q; 411 412 ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 413 ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 414 for (c = 0; c < coneSize; ++c) { 415 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 416 if (cone[c] == adj[q]) break; 417 } 418 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 419 } 420 } 421 } else { 422 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 423 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 424 for (s = 0; s < supportSize; ++s) { 425 const PetscInt *cone = NULL; 426 PetscInt coneSize, c, q; 427 428 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 429 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 430 for (c = 0; c < coneSize; ++c) { 431 for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 432 if (cone[c] == adj[q]) break; 433 } 434 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 435 } 436 } 437 } 438 *adjSize = numAdj; 439 PetscFunctionReturn(0); 440 } 441 442 #undef __FUNCT__ 443 #define __FUNCT__ "DMPlexGetAdjacency_Private" 444 PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 445 { 446 const PetscInt *star = tmpClosure; 447 PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 448 PetscErrorCode ierr; 449 450 PetscFunctionBegin; 451 ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt**) &star);CHKERRQ(ierr); 452 for (s = 2; s < starSize*2; s += 2) { 453 const PetscInt *closure = NULL; 454 PetscInt closureSize, c, q; 455 456 ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 457 for (c = 0; c < closureSize*2; c += 2) { 458 for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 459 if (closure[c] == adj[q]) break; 460 } 461 if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 462 } 463 ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 464 } 465 *adjSize = numAdj; 466 PetscFunctionReturn(0); 467 } 468 469 #undef __FUNCT__ 470 #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 471 PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 472 { 473 DM_Plex *mesh = (DM_Plex*) dm->data; 474 475 PetscFunctionBegin; 476 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 477 mesh->preallocCenterDim = preallocCenterDim; 478 PetscFunctionReturn(0); 479 } 480 481 #undef __FUNCT__ 482 #define __FUNCT__ "DMPlexPreallocateOperator" 483 PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 484 { 485 DM_Plex *mesh = (DM_Plex*) dm->data; 486 MPI_Comm comm; 487 PetscSF sf, sfDof, sfAdj; 488 PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 489 PetscInt nleaves, l, p; 490 const PetscInt *leaves; 491 const PetscSFNode *remotes; 492 PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 493 PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 494 PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 495 PetscLayout rLayout; 496 PetscInt locRows, rStart, rEnd, r; 497 PetscMPIInt size; 498 PetscBool useClosure, debug = PETSC_FALSE; 499 PetscErrorCode ierr; 500 501 PetscFunctionBegin; 502 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 503 ierr = PetscOptionsGetBool(NULL, "-dm_view_preallocation", &debug, NULL);CHKERRQ(ierr); 504 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 505 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 506 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 507 /* Create dof SF based on point SF */ 508 if (debug) { 509 ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 510 ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 511 ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 512 ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 513 ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 514 ierr = PetscSFView(sf, NULL);CHKERRQ(ierr); 515 } 516 ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 517 ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 518 if (debug) { 519 ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 520 ierr = PetscSFView(sfDof, NULL);CHKERRQ(ierr); 521 } 522 /* Create section for dof adjacency (dof ==> # adj dof) */ 523 /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 524 /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 525 /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 526 if (mesh->preallocCenterDim == dim) { 527 useClosure = PETSC_FALSE; 528 } else if (mesh->preallocCenterDim == 0) { 529 useClosure = PETSC_TRUE; 530 } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 531 532 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 533 ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 534 ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 535 ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 536 ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 537 ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 538 /* Fill in the ghost dofs on the interface */ 539 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 540 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 541 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 542 543 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)) + 2; 544 maxAdjSize = PetscPowInt(mesh->maxConeSize,depth) * PetscPowInt(mesh->maxSupportSize,depth) + 1; 545 546 ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 547 548 /* 549 ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 550 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 551 Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 552 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 553 Create sfAdj connecting rootSectionAdj and leafSectionAdj 554 3. Visit unowned points on interface, write adjacencies to adj 555 Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 556 4. Visit owned points on interface, write adjacencies to rootAdj 557 Remove redundancy in rootAdj 558 ** The last two traversals use transitive closure 559 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 560 Allocate memory addressed by sectionAdj (cols) 561 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 562 ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 563 */ 564 565 for (l = 0; l < nleaves; ++l) { 566 PetscInt dof, off, d, q; 567 PetscInt p = leaves[l], numAdj = maxAdjSize; 568 569 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 570 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 571 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 572 for (q = 0; q < numAdj; ++q) { 573 const PetscInt padj = tmpAdj[q]; 574 PetscInt ndof, ncdof; 575 576 if ((padj < pStart) || (padj >= pEnd)) continue; 577 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 578 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 579 for (d = off; d < off+dof; ++d) { 580 ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 581 } 582 } 583 } 584 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 585 if (debug) { 586 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 587 ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 588 } 589 /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 590 if (size > 1) { 591 ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 592 ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 593 } 594 if (debug) { 595 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 596 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 597 } 598 /* Add in local adjacency sizes for owned dofs on interface (roots) */ 599 for (p = pStart; p < pEnd; ++p) { 600 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 601 602 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 603 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 604 if (!dof) continue; 605 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 606 if (adof <= 0) continue; 607 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 608 for (q = 0; q < numAdj; ++q) { 609 const PetscInt padj = tmpAdj[q]; 610 PetscInt ndof, ncdof; 611 612 if ((padj < pStart) || (padj >= pEnd)) continue; 613 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 614 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 615 for (d = off; d < off+dof; ++d) { 616 ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 617 } 618 } 619 } 620 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 621 if (debug) { 622 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 623 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 624 } 625 /* Create adj SF based on dof SF */ 626 ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 627 ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 628 if (debug) { 629 ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 630 ierr = PetscSFView(sfAdj, NULL);CHKERRQ(ierr); 631 } 632 ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 633 /* Create leaf adjacency */ 634 ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 635 ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 636 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 637 ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 638 for (l = 0; l < nleaves; ++l) { 639 PetscInt dof, off, d, q; 640 PetscInt p = leaves[l], numAdj = maxAdjSize; 641 642 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 643 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 644 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 645 for (d = off; d < off+dof; ++d) { 646 PetscInt aoff, i = 0; 647 648 ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 649 for (q = 0; q < numAdj; ++q) { 650 const PetscInt padj = tmpAdj[q]; 651 PetscInt ndof, ncdof, ngoff, nd; 652 653 if ((padj < pStart) || (padj >= pEnd)) continue; 654 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 655 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 656 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 657 for (nd = 0; nd < ndof-ncdof; ++nd) { 658 adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 659 ++i; 660 } 661 } 662 } 663 } 664 /* Debugging */ 665 if (debug) { 666 IS tmp; 667 ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 668 ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 669 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 670 } 671 /* Gather adjacenct indices to root */ 672 ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 673 ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 674 for (r = 0; r < adjSize; ++r) rootAdj[r] = -1; 675 if (size > 1) { 676 ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 677 ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 678 } 679 ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 680 ierr = PetscFree(adj);CHKERRQ(ierr); 681 /* Debugging */ 682 if (debug) { 683 IS tmp; 684 ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 685 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 686 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 687 } 688 /* Add in local adjacency indices for owned dofs on interface (roots) */ 689 for (p = pStart; p < pEnd; ++p) { 690 PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 691 692 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 693 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 694 if (!dof) continue; 695 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 696 if (adof <= 0) continue; 697 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 698 for (d = off; d < off+dof; ++d) { 699 PetscInt adof, aoff, i; 700 701 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 702 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 703 i = adof-1; 704 for (q = 0; q < numAdj; ++q) { 705 const PetscInt padj = tmpAdj[q]; 706 PetscInt ndof, ncdof, ngoff, nd; 707 708 if ((padj < pStart) || (padj >= pEnd)) continue; 709 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 710 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 711 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 712 for (nd = 0; nd < ndof-ncdof; ++nd) { 713 rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 714 --i; 715 } 716 } 717 } 718 } 719 /* Debugging */ 720 if (debug) { 721 IS tmp; 722 ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 723 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 724 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 725 } 726 /* Compress indices */ 727 ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 728 for (p = pStart; p < pEnd; ++p) { 729 PetscInt dof, cdof, off, d; 730 PetscInt adof, aoff; 731 732 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 733 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 734 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 735 if (!dof) continue; 736 ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 737 if (adof <= 0) continue; 738 for (d = off; d < off+dof-cdof; ++d) { 739 ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 740 ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 741 ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 742 ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 743 } 744 } 745 /* Debugging */ 746 if (debug) { 747 IS tmp; 748 ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 749 ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 750 ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 751 ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 752 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 753 } 754 /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 755 ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 756 ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 757 ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 758 for (p = pStart; p < pEnd; ++p) { 759 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 760 PetscBool found = PETSC_TRUE; 761 762 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 763 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 764 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 765 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 766 for (d = 0; d < dof-cdof; ++d) { 767 PetscInt ldof, rdof; 768 769 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 770 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 771 if (ldof > 0) { 772 /* We do not own this point */ 773 } else if (rdof > 0) { 774 ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 775 } else { 776 found = PETSC_FALSE; 777 } 778 } 779 if (found) continue; 780 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 781 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 782 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 783 for (q = 0; q < numAdj; ++q) { 784 const PetscInt padj = tmpAdj[q]; 785 PetscInt ndof, ncdof, noff; 786 787 if ((padj < pStart) || (padj >= pEnd)) continue; 788 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 789 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 790 ierr = PetscSectionGetOffset(section, padj, &noff);CHKERRQ(ierr); 791 for (d = goff; d < goff+dof-cdof; ++d) { 792 ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 793 } 794 } 795 } 796 ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 797 if (debug) { 798 ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 799 ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 800 } 801 /* Get adjacent indices */ 802 ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 803 ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 804 for (p = pStart; p < pEnd; ++p) { 805 PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 806 PetscBool found = PETSC_TRUE; 807 808 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 809 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 810 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 811 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 812 for (d = 0; d < dof-cdof; ++d) { 813 PetscInt ldof, rdof; 814 815 ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 816 ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 817 if (ldof > 0) { 818 /* We do not own this point */ 819 } else if (rdof > 0) { 820 PetscInt aoff, roff; 821 822 ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 823 ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 824 ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 825 } else { 826 found = PETSC_FALSE; 827 } 828 } 829 if (found) continue; 830 ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 831 for (d = goff; d < goff+dof-cdof; ++d) { 832 PetscInt adof, aoff, i = 0; 833 834 ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 835 ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 836 for (q = 0; q < numAdj; ++q) { 837 const PetscInt padj = tmpAdj[q]; 838 PetscInt ndof, ncdof, ngoff, nd; 839 const PetscInt *ncind; 840 841 /* Adjacent points may not be in the section chart */ 842 if ((padj < pStart) || (padj >= pEnd)) continue; 843 ierr = PetscSectionGetDof(section, padj, &ndof);CHKERRQ(ierr); 844 ierr = PetscSectionGetConstraintDof(section, padj, &ncdof);CHKERRQ(ierr); 845 ierr = PetscSectionGetConstraintIndices(section, padj, &ncind);CHKERRQ(ierr); 846 ierr = PetscSectionGetOffset(sectionGlobal, padj, &ngoff);CHKERRQ(ierr); 847 for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 848 cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd : ngoff+nd; 849 } 850 } 851 if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 852 } 853 } 854 ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 855 ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 856 ierr = PetscFree(rootAdj);CHKERRQ(ierr); 857 ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 858 /* Debugging */ 859 if (debug) { 860 IS tmp; 861 ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 862 ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 863 ierr = ISView(tmp, NULL);CHKERRQ(ierr); 864 } 865 /* Create allocation vectors from adjacency graph */ 866 ierr = MatGetLocalSize(A, &locRows, NULL);CHKERRQ(ierr); 867 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)A), &rLayout);CHKERRQ(ierr); 868 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 869 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 870 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 871 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 872 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 873 /* Only loop over blocks of rows */ 874 if (rStart%bs || rEnd%bs) SETERRQ3(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 875 for (r = rStart/bs; r < rEnd/bs; ++r) { 876 const PetscInt row = r*bs; 877 PetscInt numCols, cStart, c; 878 879 ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 880 ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 881 for (c = cStart; c < cStart+numCols; ++c) { 882 if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 883 ++dnz[r-rStart]; 884 if (cols[c] >= row) ++dnzu[r-rStart]; 885 } else { 886 ++onz[r-rStart]; 887 if (cols[c] >= row) ++onzu[r-rStart]; 888 } 889 } 890 } 891 if (bs > 1) { 892 for (r = 0; r < locRows/bs; ++r) { 893 dnz[r] /= bs; 894 onz[r] /= bs; 895 dnzu[r] /= bs; 896 onzu[r] /= bs; 897 } 898 } 899 /* Set matrix pattern */ 900 ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 901 ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 902 /* Fill matrix with zeros */ 903 if (fillMatrix) { 904 PetscScalar *values; 905 PetscInt maxRowLen = 0; 906 907 for (r = rStart; r < rEnd; ++r) { 908 PetscInt len; 909 910 ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 911 maxRowLen = PetscMax(maxRowLen, len); 912 } 913 ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 914 ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 915 for (r = rStart; r < rEnd; ++r) { 916 PetscInt numCols, cStart; 917 918 ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 919 ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 920 ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 921 } 922 ierr = PetscFree(values);CHKERRQ(ierr); 923 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 924 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 925 } 926 ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 927 ierr = PetscFree(cols);CHKERRQ(ierr); 928 PetscFunctionReturn(0); 929 } 930 931 #if 0 932 #undef __FUNCT__ 933 #define __FUNCT__ "DMPlexPreallocateOperator_2" 934 PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 935 { 936 PetscInt *tmpClosure,*tmpAdj,*visits; 937 PetscInt c,cStart,cEnd,pStart,pEnd; 938 PetscErrorCode ierr; 939 940 PetscFunctionBegin; 941 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 942 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 943 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 944 945 maxClosureSize = 2*PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)); 946 947 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 948 npoints = pEnd - pStart; 949 950 ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 951 ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 952 ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 953 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 954 for (c=cStart; c<cEnd; c++) { 955 PetscInt *support = tmpClosure; 956 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 957 for (p=0; p<supportSize; p++) lvisits[support[p]]++; 958 } 959 ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 960 ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 961 ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 962 ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 963 964 ierr = PetscSFGetRanks();CHKERRQ(ierr); 965 966 967 ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 968 for (c=cStart; c<cEnd; c++) { 969 ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 970 /* 971 Depth-first walk of transitive closure. 972 At each leaf frame f of transitive closure that we see, add 1/visits[f] to each pair (p,q) not marked as done in cellmat. 973 This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 974 */ 975 } 976 977 ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 978 ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 979 PetscFunctionReturn(0); 980 } 981 #endif 982 983 #undef __FUNCT__ 984 #define __FUNCT__ "DMCreateMatrix_Plex" 985 PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 986 { 987 PetscSection section, sectionGlobal; 988 PetscInt bs = -1; 989 PetscInt localSize; 990 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 991 PetscErrorCode ierr; 992 993 PetscFunctionBegin; 994 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 995 ierr = MatInitializePackage(NULL);CHKERRQ(ierr); 996 #endif 997 if (!mtype) mtype = MATAIJ; 998 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 999 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1000 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 1001 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 1002 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 1003 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1004 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 1005 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 1006 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 1007 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 1008 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 1009 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 1010 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 1011 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 1012 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 1013 /* Check for symmetric storage */ 1014 isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 1015 if (isSymmetric) { 1016 ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 1017 } 1018 if (!isShell) { 1019 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 1020 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 1021 1022 if (bs < 0) { 1023 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 1024 PetscInt pStart, pEnd, p, dof, cdof; 1025 1026 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1027 for (p = pStart; p < pEnd; ++p) { 1028 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 1029 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 1030 if (dof-cdof) { 1031 if (bs < 0) { 1032 bs = dof-cdof; 1033 } else if (bs != dof-cdof) { 1034 /* Layout does not admit a pointwise block size */ 1035 bs = 1; 1036 break; 1037 } 1038 } 1039 } 1040 /* Must have same blocksize on all procs (some might have no points) */ 1041 bsLocal = bs; 1042 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1043 bsLocal = bs < 0 ? bsMax : bs; 1044 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1045 if (bsMin != bsMax) { 1046 bs = 1; 1047 } else { 1048 bs = bsMax; 1049 } 1050 } else { 1051 bs = 1; 1052 } 1053 } 1054 ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1055 ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1056 ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1057 ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1058 ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1059 ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1060 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1061 } 1062 PetscFunctionReturn(0); 1063 } 1064 1065 #undef __FUNCT__ 1066 #define __FUNCT__ "DMPlexGetDimension" 1067 /*@ 1068 DMPlexGetDimension - Return the topological mesh dimension 1069 1070 Not collective 1071 1072 Input Parameter: 1073 . mesh - The DMPlex 1074 1075 Output Parameter: 1076 . dim - The topological mesh dimension 1077 1078 Level: beginner 1079 1080 .seealso: DMPlexCreate() 1081 @*/ 1082 PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1083 { 1084 DM_Plex *mesh = (DM_Plex*) dm->data; 1085 1086 PetscFunctionBegin; 1087 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1088 PetscValidPointer(dim, 2); 1089 *dim = mesh->dim; 1090 PetscFunctionReturn(0); 1091 } 1092 1093 #undef __FUNCT__ 1094 #define __FUNCT__ "DMPlexSetDimension" 1095 /*@ 1096 DMPlexSetDimension - Set the topological mesh dimension 1097 1098 Collective on mesh 1099 1100 Input Parameters: 1101 + mesh - The DMPlex 1102 - dim - The topological mesh dimension 1103 1104 Level: beginner 1105 1106 .seealso: DMPlexCreate() 1107 @*/ 1108 PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1109 { 1110 DM_Plex *mesh = (DM_Plex*) dm->data; 1111 1112 PetscFunctionBegin; 1113 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1114 PetscValidLogicalCollectiveInt(dm, dim, 2); 1115 mesh->dim = dim; 1116 mesh->preallocCenterDim = dim; 1117 PetscFunctionReturn(0); 1118 } 1119 1120 #undef __FUNCT__ 1121 #define __FUNCT__ "DMPlexGetChart" 1122 /*@ 1123 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1124 1125 Not collective 1126 1127 Input Parameter: 1128 . mesh - The DMPlex 1129 1130 Output Parameters: 1131 + pStart - The first mesh point 1132 - pEnd - The upper bound for mesh points 1133 1134 Level: beginner 1135 1136 .seealso: DMPlexCreate(), DMPlexSetChart() 1137 @*/ 1138 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1139 { 1140 DM_Plex *mesh = (DM_Plex*) dm->data; 1141 PetscErrorCode ierr; 1142 1143 PetscFunctionBegin; 1144 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1145 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1146 PetscFunctionReturn(0); 1147 } 1148 1149 #undef __FUNCT__ 1150 #define __FUNCT__ "DMPlexSetChart" 1151 /*@ 1152 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1153 1154 Not collective 1155 1156 Input Parameters: 1157 + mesh - The DMPlex 1158 . pStart - The first mesh point 1159 - pEnd - The upper bound for mesh points 1160 1161 Output Parameters: 1162 1163 Level: beginner 1164 1165 .seealso: DMPlexCreate(), DMPlexGetChart() 1166 @*/ 1167 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1168 { 1169 DM_Plex *mesh = (DM_Plex*) dm->data; 1170 PetscErrorCode ierr; 1171 1172 PetscFunctionBegin; 1173 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1174 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1175 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1176 PetscFunctionReturn(0); 1177 } 1178 1179 #undef __FUNCT__ 1180 #define __FUNCT__ "DMPlexGetConeSize" 1181 /*@ 1182 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1183 1184 Not collective 1185 1186 Input Parameters: 1187 + mesh - The DMPlex 1188 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1189 1190 Output Parameter: 1191 . size - The cone size for point p 1192 1193 Level: beginner 1194 1195 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1196 @*/ 1197 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1198 { 1199 DM_Plex *mesh = (DM_Plex*) dm->data; 1200 PetscErrorCode ierr; 1201 1202 PetscFunctionBegin; 1203 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1204 PetscValidPointer(size, 3); 1205 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1206 PetscFunctionReturn(0); 1207 } 1208 1209 #undef __FUNCT__ 1210 #define __FUNCT__ "DMPlexSetConeSize" 1211 /*@ 1212 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1213 1214 Not collective 1215 1216 Input Parameters: 1217 + mesh - The DMPlex 1218 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1219 - size - The cone size for point p 1220 1221 Output Parameter: 1222 1223 Note: 1224 This should be called after DMPlexSetChart(). 1225 1226 Level: beginner 1227 1228 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1229 @*/ 1230 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1231 { 1232 DM_Plex *mesh = (DM_Plex*) dm->data; 1233 PetscErrorCode ierr; 1234 1235 PetscFunctionBegin; 1236 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1237 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1238 1239 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1240 PetscFunctionReturn(0); 1241 } 1242 1243 #undef __FUNCT__ 1244 #define __FUNCT__ "DMPlexGetCone" 1245 /*@C 1246 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1247 1248 Not collective 1249 1250 Input Parameters: 1251 + mesh - The DMPlex 1252 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1253 1254 Output Parameter: 1255 . cone - An array of points which are on the in-edges for point p 1256 1257 Level: beginner 1258 1259 Note: 1260 This routine is not available in Fortran. 1261 1262 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1263 @*/ 1264 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1265 { 1266 DM_Plex *mesh = (DM_Plex*) dm->data; 1267 PetscInt off; 1268 PetscErrorCode ierr; 1269 1270 PetscFunctionBegin; 1271 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1272 PetscValidPointer(cone, 3); 1273 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1274 *cone = &mesh->cones[off]; 1275 PetscFunctionReturn(0); 1276 } 1277 1278 #undef __FUNCT__ 1279 #define __FUNCT__ "DMPlexSetCone" 1280 /*@ 1281 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1282 1283 Not collective 1284 1285 Input Parameters: 1286 + mesh - The DMPlex 1287 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1288 - cone - An array of points which are on the in-edges for point p 1289 1290 Output Parameter: 1291 1292 Note: 1293 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1294 1295 Level: beginner 1296 1297 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1298 @*/ 1299 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1300 { 1301 DM_Plex *mesh = (DM_Plex*) dm->data; 1302 PetscInt pStart, pEnd; 1303 PetscInt dof, off, c; 1304 PetscErrorCode ierr; 1305 1306 PetscFunctionBegin; 1307 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1308 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1309 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1310 if (dof) PetscValidPointer(cone, 3); 1311 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1312 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); 1313 for (c = 0; c < dof; ++c) { 1314 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); 1315 mesh->cones[off+c] = cone[c]; 1316 } 1317 PetscFunctionReturn(0); 1318 } 1319 1320 #undef __FUNCT__ 1321 #define __FUNCT__ "DMPlexGetConeOrientation" 1322 /*@C 1323 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1324 1325 Not collective 1326 1327 Input Parameters: 1328 + mesh - The DMPlex 1329 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1330 1331 Output Parameter: 1332 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1333 integer giving the prescription for cone traversal. If it is negative, the cone is 1334 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1335 the index of the cone point on which to start. 1336 1337 Level: beginner 1338 1339 Note: 1340 This routine is not available in Fortran. 1341 1342 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1343 @*/ 1344 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1345 { 1346 DM_Plex *mesh = (DM_Plex*) dm->data; 1347 PetscInt off; 1348 PetscErrorCode ierr; 1349 1350 PetscFunctionBegin; 1351 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1352 #if defined(PETSC_USE_DEBUG) 1353 { 1354 PetscInt dof; 1355 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1356 if (dof) PetscValidPointer(coneOrientation, 3); 1357 } 1358 #endif 1359 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1360 1361 *coneOrientation = &mesh->coneOrientations[off]; 1362 PetscFunctionReturn(0); 1363 } 1364 1365 #undef __FUNCT__ 1366 #define __FUNCT__ "DMPlexSetConeOrientation" 1367 /*@ 1368 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1369 1370 Not collective 1371 1372 Input Parameters: 1373 + mesh - The DMPlex 1374 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1375 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1376 integer giving the prescription for cone traversal. If it is negative, the cone is 1377 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1378 the index of the cone point on which to start. 1379 1380 Output Parameter: 1381 1382 Note: 1383 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1384 1385 Level: beginner 1386 1387 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1388 @*/ 1389 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1390 { 1391 DM_Plex *mesh = (DM_Plex*) dm->data; 1392 PetscInt pStart, pEnd; 1393 PetscInt dof, off, c; 1394 PetscErrorCode ierr; 1395 1396 PetscFunctionBegin; 1397 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1398 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1399 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1400 if (dof) PetscValidPointer(coneOrientation, 3); 1401 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1402 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); 1403 for (c = 0; c < dof; ++c) { 1404 PetscInt cdof, o = coneOrientation[c]; 1405 1406 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1407 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); 1408 mesh->coneOrientations[off+c] = o; 1409 } 1410 PetscFunctionReturn(0); 1411 } 1412 1413 #undef __FUNCT__ 1414 #define __FUNCT__ "DMPlexInsertCone" 1415 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1416 { 1417 DM_Plex *mesh = (DM_Plex*) dm->data; 1418 PetscInt pStart, pEnd; 1419 PetscInt dof, off; 1420 PetscErrorCode ierr; 1421 1422 PetscFunctionBegin; 1423 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1424 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1425 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); 1426 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); 1427 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1428 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1429 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); 1430 mesh->cones[off+conePos] = conePoint; 1431 PetscFunctionReturn(0); 1432 } 1433 1434 #undef __FUNCT__ 1435 #define __FUNCT__ "DMPlexInsertConeOrientation" 1436 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 1437 { 1438 DM_Plex *mesh = (DM_Plex*) dm->data; 1439 PetscInt pStart, pEnd; 1440 PetscInt dof, off; 1441 PetscErrorCode ierr; 1442 1443 PetscFunctionBegin; 1444 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1445 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1446 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); 1447 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1448 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1449 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); 1450 mesh->coneOrientations[off+conePos] = coneOrientation; 1451 PetscFunctionReturn(0); 1452 } 1453 1454 #undef __FUNCT__ 1455 #define __FUNCT__ "DMPlexGetSupportSize" 1456 /*@ 1457 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1458 1459 Not collective 1460 1461 Input Parameters: 1462 + mesh - The DMPlex 1463 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1464 1465 Output Parameter: 1466 . size - The support size for point p 1467 1468 Level: beginner 1469 1470 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1471 @*/ 1472 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1473 { 1474 DM_Plex *mesh = (DM_Plex*) dm->data; 1475 PetscErrorCode ierr; 1476 1477 PetscFunctionBegin; 1478 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1479 PetscValidPointer(size, 3); 1480 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1481 PetscFunctionReturn(0); 1482 } 1483 1484 #undef __FUNCT__ 1485 #define __FUNCT__ "DMPlexSetSupportSize" 1486 /*@ 1487 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1488 1489 Not collective 1490 1491 Input Parameters: 1492 + mesh - The DMPlex 1493 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1494 - size - The support size for point p 1495 1496 Output Parameter: 1497 1498 Note: 1499 This should be called after DMPlexSetChart(). 1500 1501 Level: beginner 1502 1503 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1504 @*/ 1505 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1506 { 1507 DM_Plex *mesh = (DM_Plex*) dm->data; 1508 PetscErrorCode ierr; 1509 1510 PetscFunctionBegin; 1511 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1512 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1513 1514 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1515 PetscFunctionReturn(0); 1516 } 1517 1518 #undef __FUNCT__ 1519 #define __FUNCT__ "DMPlexGetSupport" 1520 /*@C 1521 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1522 1523 Not collective 1524 1525 Input Parameters: 1526 + mesh - The DMPlex 1527 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1528 1529 Output Parameter: 1530 . support - An array of points which are on the out-edges for point p 1531 1532 Level: beginner 1533 1534 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1535 @*/ 1536 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1537 { 1538 DM_Plex *mesh = (DM_Plex*) dm->data; 1539 PetscInt off; 1540 PetscErrorCode ierr; 1541 1542 PetscFunctionBegin; 1543 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1544 PetscValidPointer(support, 3); 1545 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1546 *support = &mesh->supports[off]; 1547 PetscFunctionReturn(0); 1548 } 1549 1550 #undef __FUNCT__ 1551 #define __FUNCT__ "DMPlexSetSupport" 1552 /*@ 1553 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1554 1555 Not collective 1556 1557 Input Parameters: 1558 + mesh - The DMPlex 1559 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1560 - support - An array of points which are on the in-edges for point p 1561 1562 Output Parameter: 1563 1564 Note: 1565 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1566 1567 Level: beginner 1568 1569 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1570 @*/ 1571 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1572 { 1573 DM_Plex *mesh = (DM_Plex*) dm->data; 1574 PetscInt pStart, pEnd; 1575 PetscInt dof, off, c; 1576 PetscErrorCode ierr; 1577 1578 PetscFunctionBegin; 1579 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1580 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1581 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1582 if (dof) PetscValidPointer(support, 3); 1583 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1584 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); 1585 for (c = 0; c < dof; ++c) { 1586 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); 1587 mesh->supports[off+c] = support[c]; 1588 } 1589 PetscFunctionReturn(0); 1590 } 1591 1592 #undef __FUNCT__ 1593 #define __FUNCT__ "DMPlexInsertSupport" 1594 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1595 { 1596 DM_Plex *mesh = (DM_Plex*) dm->data; 1597 PetscInt pStart, pEnd; 1598 PetscInt dof, off; 1599 PetscErrorCode ierr; 1600 1601 PetscFunctionBegin; 1602 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1603 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1604 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1605 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1606 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); 1607 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); 1608 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); 1609 mesh->supports[off+supportPos] = supportPoint; 1610 PetscFunctionReturn(0); 1611 } 1612 1613 #undef __FUNCT__ 1614 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1615 /*@C 1616 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1617 1618 Not collective 1619 1620 Input Parameters: 1621 + mesh - The DMPlex 1622 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1623 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1624 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1625 1626 Output Parameters: 1627 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1628 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1629 1630 Note: 1631 If using internal storage (points is NULL on input), each call overwrites the last output. 1632 1633 Level: beginner 1634 1635 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1636 @*/ 1637 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1638 { 1639 DM_Plex *mesh = (DM_Plex*) dm->data; 1640 PetscInt *closure, *fifo; 1641 const PetscInt *tmp = NULL, *tmpO = NULL; 1642 PetscInt tmpSize, t; 1643 PetscInt depth = 0, maxSize; 1644 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1645 PetscErrorCode ierr; 1646 1647 PetscFunctionBegin; 1648 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1649 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1650 maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth),PetscPowInt(mesh->maxSupportSize,depth)),depth) + 2; 1651 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1652 if (*points) { 1653 closure = *points; 1654 } else { 1655 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1656 } 1657 closure[0] = p; closure[1] = 0; 1658 /* This is only 1-level */ 1659 if (useCone) { 1660 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1661 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1662 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1663 } else { 1664 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1665 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1666 } 1667 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1668 const PetscInt cp = tmp[t]; 1669 const PetscInt co = tmpO ? tmpO[t] : 0; 1670 1671 closure[closureSize] = cp; 1672 closure[closureSize+1] = co; 1673 fifo[fifoSize] = cp; 1674 fifo[fifoSize+1] = co; 1675 } 1676 while (fifoSize - fifoStart) { 1677 const PetscInt q = fifo[fifoStart]; 1678 const PetscInt o = fifo[fifoStart+1]; 1679 const PetscInt rev = o >= 0 ? 0 : 1; 1680 const PetscInt off = rev ? -(o+1) : o; 1681 1682 if (useCone) { 1683 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1684 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1685 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1686 } else { 1687 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1688 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1689 tmpO = NULL; 1690 } 1691 for (t = 0; t < tmpSize; ++t) { 1692 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1693 const PetscInt cp = tmp[i]; 1694 /* Must propogate orientation */ 1695 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1696 PetscInt c; 1697 1698 /* Check for duplicate */ 1699 for (c = 0; c < closureSize; c += 2) { 1700 if (closure[c] == cp) break; 1701 } 1702 if (c == closureSize) { 1703 closure[closureSize] = cp; 1704 closure[closureSize+1] = co; 1705 fifo[fifoSize] = cp; 1706 fifo[fifoSize+1] = co; 1707 closureSize += 2; 1708 fifoSize += 2; 1709 } 1710 } 1711 fifoStart += 2; 1712 } 1713 if (numPoints) *numPoints = closureSize/2; 1714 if (points) *points = closure; 1715 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1716 PetscFunctionReturn(0); 1717 } 1718 1719 #undef __FUNCT__ 1720 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1721 /*@C 1722 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1723 1724 Not collective 1725 1726 Input Parameters: 1727 + mesh - The DMPlex 1728 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1729 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1730 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1731 1732 Output Parameters: 1733 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1734 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1735 1736 Note: 1737 If not using internal storage (points is not NULL on input), this call is unnecessary 1738 1739 Level: beginner 1740 1741 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1742 @*/ 1743 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1744 { 1745 PetscErrorCode ierr; 1746 1747 PetscFunctionBegin; 1748 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1749 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1750 PetscFunctionReturn(0); 1751 } 1752 1753 #undef __FUNCT__ 1754 #define __FUNCT__ "DMPlexGetMaxSizes" 1755 /*@ 1756 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1757 1758 Not collective 1759 1760 Input Parameter: 1761 . mesh - The DMPlex 1762 1763 Output Parameters: 1764 + maxConeSize - The maximum number of in-edges 1765 - maxSupportSize - The maximum number of out-edges 1766 1767 Level: beginner 1768 1769 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1770 @*/ 1771 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1772 { 1773 DM_Plex *mesh = (DM_Plex*) dm->data; 1774 1775 PetscFunctionBegin; 1776 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1777 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1778 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1779 PetscFunctionReturn(0); 1780 } 1781 1782 #undef __FUNCT__ 1783 #define __FUNCT__ "DMSetUp_Plex" 1784 PetscErrorCode DMSetUp_Plex(DM dm) 1785 { 1786 DM_Plex *mesh = (DM_Plex*) dm->data; 1787 PetscInt size; 1788 PetscErrorCode ierr; 1789 1790 PetscFunctionBegin; 1791 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1792 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1793 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1794 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1795 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1796 ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1797 if (mesh->maxSupportSize) { 1798 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1799 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1800 ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1801 } 1802 PetscFunctionReturn(0); 1803 } 1804 1805 #undef __FUNCT__ 1806 #define __FUNCT__ "DMCreateSubDM_Plex" 1807 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1808 { 1809 PetscSection section, sectionGlobal; 1810 PetscInt *subIndices; 1811 PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1812 PetscErrorCode ierr; 1813 1814 PetscFunctionBegin; 1815 if (!numFields) PetscFunctionReturn(0); 1816 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1817 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1818 if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1819 if (!sectionGlobal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1820 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1821 if (numFields > nF) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1822 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1823 for (p = pStart; p < pEnd; ++p) { 1824 PetscInt gdof; 1825 1826 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1827 if (gdof > 0) { 1828 for (f = 0; f < numFields; ++f) { 1829 PetscInt fdof, fcdof; 1830 1831 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1832 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1833 subSize += fdof-fcdof; 1834 } 1835 } 1836 } 1837 ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1838 for (p = pStart; p < pEnd; ++p) { 1839 PetscInt gdof, goff; 1840 1841 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1842 if (gdof > 0) { 1843 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1844 for (f = 0; f < numFields; ++f) { 1845 PetscInt fdof, fcdof, fc, f2, poff = 0; 1846 1847 /* Can get rid of this loop by storing field information in the global section */ 1848 for (f2 = 0; f2 < fields[f]; ++f2) { 1849 ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1850 ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1851 poff += fdof-fcdof; 1852 } 1853 ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1854 ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1855 for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1856 subIndices[subOff] = goff+poff+fc; 1857 } 1858 } 1859 } 1860 } 1861 if (is) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1862 if (subdm) { 1863 PetscSection subsection; 1864 PetscBool haveNull = PETSC_FALSE; 1865 PetscInt f, nf = 0; 1866 1867 ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1868 ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1869 ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1870 ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 1871 for (f = 0; f < numFields; ++f) { 1872 (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1873 if ((*subdm)->nullspaceConstructors[f]) { 1874 haveNull = PETSC_TRUE; 1875 nf = f; 1876 } 1877 } 1878 if (haveNull) { 1879 MatNullSpace nullSpace; 1880 1881 ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1882 ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1883 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1884 } 1885 if (dm->fields) { 1886 if (nF != dm->numFields) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); 1887 ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1888 for (f = 0; f < numFields; ++f) { 1889 ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); 1890 } 1891 if (numFields == 1) { 1892 MatNullSpace space; 1893 Mat pmat; 1894 1895 ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); 1896 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1897 ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); 1898 if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1899 ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); 1900 if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1901 } 1902 } 1903 } 1904 PetscFunctionReturn(0); 1905 } 1906 1907 #undef __FUNCT__ 1908 #define __FUNCT__ "DMPlexSymmetrize" 1909 /*@ 1910 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1911 1912 Not collective 1913 1914 Input Parameter: 1915 . mesh - The DMPlex 1916 1917 Output Parameter: 1918 1919 Note: 1920 This should be called after all calls to DMPlexSetCone() 1921 1922 Level: beginner 1923 1924 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1925 @*/ 1926 PetscErrorCode DMPlexSymmetrize(DM dm) 1927 { 1928 DM_Plex *mesh = (DM_Plex*) dm->data; 1929 PetscInt *offsets; 1930 PetscInt supportSize; 1931 PetscInt pStart, pEnd, p; 1932 PetscErrorCode ierr; 1933 1934 PetscFunctionBegin; 1935 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1936 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1937 /* Calculate support sizes */ 1938 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1939 for (p = pStart; p < pEnd; ++p) { 1940 PetscInt dof, off, c; 1941 1942 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1943 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1944 for (c = off; c < off+dof; ++c) { 1945 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1946 } 1947 } 1948 for (p = pStart; p < pEnd; ++p) { 1949 PetscInt dof; 1950 1951 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1952 1953 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1954 } 1955 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1956 /* Calculate supports */ 1957 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1958 ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1959 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1960 ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1961 for (p = pStart; p < pEnd; ++p) { 1962 PetscInt dof, off, c; 1963 1964 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1965 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1966 for (c = off; c < off+dof; ++c) { 1967 const PetscInt q = mesh->cones[c]; 1968 PetscInt offS; 1969 1970 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1971 1972 mesh->supports[offS+offsets[q]] = p; 1973 ++offsets[q]; 1974 } 1975 } 1976 ierr = PetscFree(offsets);CHKERRQ(ierr); 1977 PetscFunctionReturn(0); 1978 } 1979 1980 #undef __FUNCT__ 1981 #define __FUNCT__ "DMPlexSetDepth_Private" 1982 PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1983 { 1984 PetscInt d; 1985 PetscErrorCode ierr; 1986 1987 PetscFunctionBegin; 1988 ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1989 if (d < 0) { 1990 /* We are guaranteed that the point has a cone since the depth was not yet set */ 1991 const PetscInt *cone = NULL; 1992 PetscInt dCone; 1993 1994 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1995 ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 1996 d = dCone+1; 1997 ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 1998 } 1999 *depth = d; 2000 PetscFunctionReturn(0); 2001 } 2002 2003 #undef __FUNCT__ 2004 #define __FUNCT__ "DMPlexStratify" 2005 /*@ 2006 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2007 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2008 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2009 the DAG. 2010 2011 Not collective 2012 2013 Input Parameter: 2014 . mesh - The DMPlex 2015 2016 Output Parameter: 2017 2018 Notes: 2019 The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2020 have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2021 2022 This should be called after all calls to DMPlexSymmetrize() 2023 2024 Level: beginner 2025 2026 .seealso: DMPlexCreate(), DMPlexSymmetrize() 2027 @*/ 2028 PetscErrorCode DMPlexStratify(DM dm) 2029 { 2030 DM_Plex *mesh = (DM_Plex*) dm->data; 2031 PetscInt pStart, pEnd, p; 2032 PetscInt numRoots = 0, numLeaves = 0; 2033 PetscErrorCode ierr; 2034 2035 PetscFunctionBegin; 2036 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2037 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2038 /* Calculate depth */ 2039 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2040 /* Initialize roots and count leaves */ 2041 for (p = pStart; p < pEnd; ++p) { 2042 PetscInt coneSize, supportSize; 2043 2044 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2045 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2046 if (!coneSize && supportSize) { 2047 ++numRoots; 2048 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2049 } else if (!supportSize && coneSize) { 2050 ++numLeaves; 2051 } else if (!supportSize && !coneSize) { 2052 /* Isolated points */ 2053 ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2054 } 2055 } 2056 if (numRoots + numLeaves == (pEnd - pStart)) { 2057 for (p = pStart; p < pEnd; ++p) { 2058 PetscInt coneSize, supportSize; 2059 2060 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2061 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2062 if (!supportSize && coneSize) { 2063 ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2064 } 2065 } 2066 } else { 2067 /* This might be slow since lookup is not fast */ 2068 for (p = pStart; p < pEnd; ++p) { 2069 PetscInt depth; 2070 2071 ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2072 } 2073 } 2074 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2075 PetscFunctionReturn(0); 2076 } 2077 2078 #undef __FUNCT__ 2079 #define __FUNCT__ "DMPlexGetJoin" 2080 /*@C 2081 DMPlexGetJoin - Get an array for the join of the set of points 2082 2083 Not Collective 2084 2085 Input Parameters: 2086 + dm - The DMPlex object 2087 . numPoints - The number of input points for the join 2088 - points - The input points 2089 2090 Output Parameters: 2091 + numCoveredPoints - The number of points in the join 2092 - coveredPoints - The points in the join 2093 2094 Level: intermediate 2095 2096 Note: Currently, this is restricted to a single level join 2097 2098 .keywords: mesh 2099 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2100 @*/ 2101 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2102 { 2103 DM_Plex *mesh = (DM_Plex*) dm->data; 2104 PetscInt *join[2]; 2105 PetscInt joinSize, i = 0; 2106 PetscInt dof, off, p, c, m; 2107 PetscErrorCode ierr; 2108 2109 PetscFunctionBegin; 2110 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2111 PetscValidPointer(points, 2); 2112 PetscValidPointer(numCoveredPoints, 3); 2113 PetscValidPointer(coveredPoints, 4); 2114 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2115 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2116 /* Copy in support of first point */ 2117 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2118 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2119 for (joinSize = 0; joinSize < dof; ++joinSize) { 2120 join[i][joinSize] = mesh->supports[off+joinSize]; 2121 } 2122 /* Check each successive support */ 2123 for (p = 1; p < numPoints; ++p) { 2124 PetscInt newJoinSize = 0; 2125 2126 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2127 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2128 for (c = 0; c < dof; ++c) { 2129 const PetscInt point = mesh->supports[off+c]; 2130 2131 for (m = 0; m < joinSize; ++m) { 2132 if (point == join[i][m]) { 2133 join[1-i][newJoinSize++] = point; 2134 break; 2135 } 2136 } 2137 } 2138 joinSize = newJoinSize; 2139 i = 1-i; 2140 } 2141 *numCoveredPoints = joinSize; 2142 *coveredPoints = join[i]; 2143 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2144 PetscFunctionReturn(0); 2145 } 2146 2147 #undef __FUNCT__ 2148 #define __FUNCT__ "DMPlexRestoreJoin" 2149 /*@C 2150 DMPlexRestoreJoin - Restore an array for the join of the set of points 2151 2152 Not Collective 2153 2154 Input Parameters: 2155 + dm - The DMPlex object 2156 . numPoints - The number of input points for the join 2157 - points - The input points 2158 2159 Output Parameters: 2160 + numCoveredPoints - The number of points in the join 2161 - coveredPoints - The points in the join 2162 2163 Level: intermediate 2164 2165 .keywords: mesh 2166 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2167 @*/ 2168 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2169 { 2170 PetscErrorCode ierr; 2171 2172 PetscFunctionBegin; 2173 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2174 PetscValidPointer(coveredPoints, 4); 2175 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2176 PetscFunctionReturn(0); 2177 } 2178 2179 #undef __FUNCT__ 2180 #define __FUNCT__ "DMPlexGetFullJoin" 2181 /*@C 2182 DMPlexGetFullJoin - Get an array for the join of the set of points 2183 2184 Not Collective 2185 2186 Input Parameters: 2187 + dm - The DMPlex object 2188 . numPoints - The number of input points for the join 2189 - points - The input points 2190 2191 Output Parameters: 2192 + numCoveredPoints - The number of points in the join 2193 - coveredPoints - The points in the join 2194 2195 Level: intermediate 2196 2197 .keywords: mesh 2198 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2199 @*/ 2200 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2201 { 2202 DM_Plex *mesh = (DM_Plex*) dm->data; 2203 PetscInt *offsets, **closures; 2204 PetscInt *join[2]; 2205 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2206 PetscInt p, d, c, m; 2207 PetscErrorCode ierr; 2208 2209 PetscFunctionBegin; 2210 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2211 PetscValidPointer(points, 2); 2212 PetscValidPointer(numCoveredPoints, 3); 2213 PetscValidPointer(coveredPoints, 4); 2214 2215 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2216 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2217 ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2218 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2219 maxSize = PetscPowInt(mesh->maxSupportSize,depth); 2220 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2221 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2222 2223 for (p = 0; p < numPoints; ++p) { 2224 PetscInt closureSize; 2225 2226 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2227 2228 offsets[p*(depth+2)+0] = 0; 2229 for (d = 0; d < depth+1; ++d) { 2230 PetscInt pStart, pEnd, i; 2231 2232 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2233 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2234 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2235 offsets[p*(depth+2)+d+1] = i; 2236 break; 2237 } 2238 } 2239 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2240 } 2241 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); 2242 } 2243 for (d = 0; d < depth+1; ++d) { 2244 PetscInt dof; 2245 2246 /* Copy in support of first point */ 2247 dof = offsets[d+1] - offsets[d]; 2248 for (joinSize = 0; joinSize < dof; ++joinSize) { 2249 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2250 } 2251 /* Check each successive cone */ 2252 for (p = 1; p < numPoints && joinSize; ++p) { 2253 PetscInt newJoinSize = 0; 2254 2255 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2256 for (c = 0; c < dof; ++c) { 2257 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2258 2259 for (m = 0; m < joinSize; ++m) { 2260 if (point == join[i][m]) { 2261 join[1-i][newJoinSize++] = point; 2262 break; 2263 } 2264 } 2265 } 2266 joinSize = newJoinSize; 2267 i = 1-i; 2268 } 2269 if (joinSize) break; 2270 } 2271 *numCoveredPoints = joinSize; 2272 *coveredPoints = join[i]; 2273 for (p = 0; p < numPoints; ++p) { 2274 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2275 } 2276 ierr = PetscFree(closures);CHKERRQ(ierr); 2277 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2278 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2279 PetscFunctionReturn(0); 2280 } 2281 2282 #undef __FUNCT__ 2283 #define __FUNCT__ "DMPlexGetMeet" 2284 /*@C 2285 DMPlexGetMeet - Get an array for the meet of the set of points 2286 2287 Not Collective 2288 2289 Input Parameters: 2290 + dm - The DMPlex object 2291 . numPoints - The number of input points for the meet 2292 - points - The input points 2293 2294 Output Parameters: 2295 + numCoveredPoints - The number of points in the meet 2296 - coveredPoints - The points in the meet 2297 2298 Level: intermediate 2299 2300 Note: Currently, this is restricted to a single level meet 2301 2302 .keywords: mesh 2303 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2304 @*/ 2305 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2306 { 2307 DM_Plex *mesh = (DM_Plex*) dm->data; 2308 PetscInt *meet[2]; 2309 PetscInt meetSize, i = 0; 2310 PetscInt dof, off, p, c, m; 2311 PetscErrorCode ierr; 2312 2313 PetscFunctionBegin; 2314 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2315 PetscValidPointer(points, 2); 2316 PetscValidPointer(numCoveringPoints, 3); 2317 PetscValidPointer(coveringPoints, 4); 2318 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2319 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2320 /* Copy in cone of first point */ 2321 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2322 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2323 for (meetSize = 0; meetSize < dof; ++meetSize) { 2324 meet[i][meetSize] = mesh->cones[off+meetSize]; 2325 } 2326 /* Check each successive cone */ 2327 for (p = 1; p < numPoints; ++p) { 2328 PetscInt newMeetSize = 0; 2329 2330 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2331 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2332 for (c = 0; c < dof; ++c) { 2333 const PetscInt point = mesh->cones[off+c]; 2334 2335 for (m = 0; m < meetSize; ++m) { 2336 if (point == meet[i][m]) { 2337 meet[1-i][newMeetSize++] = point; 2338 break; 2339 } 2340 } 2341 } 2342 meetSize = newMeetSize; 2343 i = 1-i; 2344 } 2345 *numCoveringPoints = meetSize; 2346 *coveringPoints = meet[i]; 2347 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2348 PetscFunctionReturn(0); 2349 } 2350 2351 #undef __FUNCT__ 2352 #define __FUNCT__ "DMPlexRestoreMeet" 2353 /*@C 2354 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2355 2356 Not Collective 2357 2358 Input Parameters: 2359 + dm - The DMPlex object 2360 . numPoints - The number of input points for the meet 2361 - points - The input points 2362 2363 Output Parameters: 2364 + numCoveredPoints - The number of points in the meet 2365 - coveredPoints - The points in the meet 2366 2367 Level: intermediate 2368 2369 .keywords: mesh 2370 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2371 @*/ 2372 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2373 { 2374 PetscErrorCode ierr; 2375 2376 PetscFunctionBegin; 2377 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2378 PetscValidPointer(coveredPoints, 4); 2379 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2380 PetscFunctionReturn(0); 2381 } 2382 2383 #undef __FUNCT__ 2384 #define __FUNCT__ "DMPlexGetFullMeet" 2385 /*@C 2386 DMPlexGetFullMeet - Get an array for the meet of the set of points 2387 2388 Not Collective 2389 2390 Input Parameters: 2391 + dm - The DMPlex object 2392 . numPoints - The number of input points for the meet 2393 - points - The input points 2394 2395 Output Parameters: 2396 + numCoveredPoints - The number of points in the meet 2397 - coveredPoints - The points in the meet 2398 2399 Level: intermediate 2400 2401 .keywords: mesh 2402 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2403 @*/ 2404 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2405 { 2406 DM_Plex *mesh = (DM_Plex*) dm->data; 2407 PetscInt *offsets, **closures; 2408 PetscInt *meet[2]; 2409 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2410 PetscInt p, h, c, m; 2411 PetscErrorCode ierr; 2412 2413 PetscFunctionBegin; 2414 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2415 PetscValidPointer(points, 2); 2416 PetscValidPointer(numCoveredPoints, 3); 2417 PetscValidPointer(coveredPoints, 4); 2418 2419 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2420 ierr = PetscMalloc(numPoints * sizeof(PetscInt*), &closures);CHKERRQ(ierr); 2421 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2422 maxSize = PetscPowInt(mesh->maxConeSize,height); 2423 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2424 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2425 2426 for (p = 0; p < numPoints; ++p) { 2427 PetscInt closureSize; 2428 2429 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2430 2431 offsets[p*(height+2)+0] = 0; 2432 for (h = 0; h < height+1; ++h) { 2433 PetscInt pStart, pEnd, i; 2434 2435 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2436 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2437 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2438 offsets[p*(height+2)+h+1] = i; 2439 break; 2440 } 2441 } 2442 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2443 } 2444 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); 2445 } 2446 for (h = 0; h < height+1; ++h) { 2447 PetscInt dof; 2448 2449 /* Copy in cone of first point */ 2450 dof = offsets[h+1] - offsets[h]; 2451 for (meetSize = 0; meetSize < dof; ++meetSize) { 2452 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2453 } 2454 /* Check each successive cone */ 2455 for (p = 1; p < numPoints && meetSize; ++p) { 2456 PetscInt newMeetSize = 0; 2457 2458 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2459 for (c = 0; c < dof; ++c) { 2460 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2461 2462 for (m = 0; m < meetSize; ++m) { 2463 if (point == meet[i][m]) { 2464 meet[1-i][newMeetSize++] = point; 2465 break; 2466 } 2467 } 2468 } 2469 meetSize = newMeetSize; 2470 i = 1-i; 2471 } 2472 if (meetSize) break; 2473 } 2474 *numCoveredPoints = meetSize; 2475 *coveredPoints = meet[i]; 2476 for (p = 0; p < numPoints; ++p) { 2477 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2478 } 2479 ierr = PetscFree(closures);CHKERRQ(ierr); 2480 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2481 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2482 PetscFunctionReturn(0); 2483 } 2484 2485 #undef __FUNCT__ 2486 #define __FUNCT__ "DMPlexGetNumFaceVertices_Internal" 2487 PetscErrorCode DMPlexGetNumFaceVertices_Internal(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 2488 { 2489 MPI_Comm comm; 2490 PetscErrorCode ierr; 2491 2492 PetscFunctionBegin; 2493 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2494 PetscValidPointer(numFaceVertices,3); 2495 switch (cellDim) { 2496 case 0: 2497 *numFaceVertices = 0; 2498 break; 2499 case 1: 2500 *numFaceVertices = 1; 2501 break; 2502 case 2: 2503 switch (numCorners) { 2504 case 3: /* triangle */ 2505 *numFaceVertices = 2; /* Edge has 2 vertices */ 2506 break; 2507 case 4: /* quadrilateral */ 2508 *numFaceVertices = 2; /* Edge has 2 vertices */ 2509 break; 2510 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2511 *numFaceVertices = 3; /* Edge has 3 vertices */ 2512 break; 2513 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2514 *numFaceVertices = 3; /* Edge has 3 vertices */ 2515 break; 2516 default: 2517 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2518 } 2519 break; 2520 case 3: 2521 switch (numCorners) { 2522 case 4: /* tetradehdron */ 2523 *numFaceVertices = 3; /* Face has 3 vertices */ 2524 break; 2525 case 6: /* tet cohesive cells */ 2526 *numFaceVertices = 4; /* Face has 4 vertices */ 2527 break; 2528 case 8: /* hexahedron */ 2529 *numFaceVertices = 4; /* Face has 4 vertices */ 2530 break; 2531 case 9: /* tet cohesive Lagrange cells */ 2532 *numFaceVertices = 6; /* Face has 6 vertices */ 2533 break; 2534 case 10: /* quadratic tetrahedron */ 2535 *numFaceVertices = 6; /* Face has 6 vertices */ 2536 break; 2537 case 12: /* hex cohesive Lagrange cells */ 2538 *numFaceVertices = 6; /* Face has 6 vertices */ 2539 break; 2540 case 18: /* quadratic tet cohesive Lagrange cells */ 2541 *numFaceVertices = 6; /* Face has 6 vertices */ 2542 break; 2543 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2544 *numFaceVertices = 9; /* Face has 9 vertices */ 2545 break; 2546 default: 2547 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2548 } 2549 break; 2550 default: 2551 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2552 } 2553 PetscFunctionReturn(0); 2554 } 2555 2556 #undef __FUNCT__ 2557 #define __FUNCT__ "DMPlexCreateNeighborCSR" 2558 PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) 2559 { 2560 const PetscInt maxFaceCases = 30; 2561 PetscInt numFaceCases = 0; 2562 PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2563 PetscInt *off, *adj; 2564 PetscInt *neighborCells, *tmpClosure; 2565 PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2566 PetscInt dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell; 2567 PetscErrorCode ierr; 2568 2569 PetscFunctionBegin; 2570 /* For parallel partitioning, I think you have to communicate supports */ 2571 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2572 cellDim = dim - cellHeight; 2573 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2574 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 2575 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2576 if (cEnd - cStart == 0) { 2577 if (numVertices) *numVertices = 0; 2578 if (offsets) *offsets = NULL; 2579 if (adjacency) *adjacency = NULL; 2580 PetscFunctionReturn(0); 2581 } 2582 numCells = cEnd - cStart; 2583 faceDepth = depth - cellHeight; 2584 /* Setup face recognition */ 2585 if (faceDepth == 1) { 2586 PetscInt cornersSeen[30] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Could use PetscBT */ 2587 2588 for (c = cStart; c < cEnd; ++c) { 2589 PetscInt corners; 2590 2591 ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2592 if (!cornersSeen[corners]) { 2593 PetscInt nFV; 2594 2595 if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2596 cornersSeen[corners] = 1; 2597 2598 ierr = DMPlexGetNumFaceVertices_Internal(dm, cellDim, corners, &nFV);CHKERRQ(ierr); 2599 2600 numFaceVertices[numFaceCases++] = nFV; 2601 } 2602 } 2603 } 2604 maxClosure = 2*PetscMax(PetscPowInt(maxConeSize,depth),PetscPowInt(maxSupportSize,depth)); 2605 maxNeighbors = PetscPowInt(maxConeSize,depth)*PetscPowInt(maxSupportSize,depth); 2606 ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2607 ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2608 ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2609 /* Count neighboring cells */ 2610 for (cell = cStart; cell < cEnd; ++cell) { 2611 PetscInt numNeighbors = maxNeighbors, n; 2612 2613 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2614 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2615 for (n = 0; n < numNeighbors; ++n) { 2616 PetscInt cellPair[2]; 2617 PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 2618 PetscInt meetSize = 0; 2619 const PetscInt *meet = NULL; 2620 2621 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2622 if (cellPair[0] == cellPair[1]) continue; 2623 if (!found) { 2624 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2625 if (meetSize) { 2626 PetscInt f; 2627 2628 for (f = 0; f < numFaceCases; ++f) { 2629 if (numFaceVertices[f] == meetSize) { 2630 found = PETSC_TRUE; 2631 break; 2632 } 2633 } 2634 } 2635 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2636 } 2637 if (found) ++off[cell-cStart+1]; 2638 } 2639 } 2640 /* Prefix sum */ 2641 for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1]; 2642 2643 if (adjacency) { 2644 ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2645 /* Get neighboring cells */ 2646 for (cell = cStart; cell < cEnd; ++cell) { 2647 PetscInt numNeighbors = maxNeighbors, n; 2648 PetscInt cellOffset = 0; 2649 2650 ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2651 /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2652 for (n = 0; n < numNeighbors; ++n) { 2653 PetscInt cellPair[2]; 2654 PetscBool found = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE; 2655 PetscInt meetSize = 0; 2656 const PetscInt *meet = NULL; 2657 2658 cellPair[0] = cell; cellPair[1] = neighborCells[n]; 2659 if (cellPair[0] == cellPair[1]) continue; 2660 if (!found) { 2661 ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2662 if (meetSize) { 2663 PetscInt f; 2664 2665 for (f = 0; f < numFaceCases; ++f) { 2666 if (numFaceVertices[f] == meetSize) { 2667 found = PETSC_TRUE; 2668 break; 2669 } 2670 } 2671 } 2672 ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2673 } 2674 if (found) { 2675 adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2676 ++cellOffset; 2677 } 2678 } 2679 } 2680 } 2681 ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2682 if (numVertices) *numVertices = numCells; 2683 if (offsets) *offsets = off; 2684 if (adjacency) *adjacency = adj; 2685 PetscFunctionReturn(0); 2686 } 2687 2688 #if defined(PETSC_HAVE_CHACO) 2689 #if defined(PETSC_HAVE_UNISTD_H) 2690 #include <unistd.h> 2691 #endif 2692 /* Chaco does not have an include file */ 2693 PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2694 float *ewgts, float *x, float *y, float *z, char *outassignname, 2695 char *outfilename, short *assignment, int architecture, int ndims_tot, 2696 int mesh_dims[3], double *goal, int global_method, int local_method, 2697 int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2698 2699 extern int FREE_GRAPH; 2700 2701 #undef __FUNCT__ 2702 #define __FUNCT__ "DMPlexPartition_Chaco" 2703 PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2704 { 2705 enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2706 MPI_Comm comm; 2707 int nvtxs = numVertices; /* number of vertices in full graph */ 2708 int *vwgts = NULL; /* weights for all vertices */ 2709 float *ewgts = NULL; /* weights for all edges */ 2710 float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2711 char *outassignname = NULL; /* name of assignment output file */ 2712 char *outfilename = NULL; /* output file name */ 2713 int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2714 int ndims_tot = 0; /* total number of cube dimensions to divide */ 2715 int mesh_dims[3]; /* dimensions of mesh of processors */ 2716 double *goal = NULL; /* desired set sizes for each set */ 2717 int global_method = 1; /* global partitioning algorithm */ 2718 int local_method = 1; /* local partitioning algorithm */ 2719 int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2720 int vmax = 200; /* how many vertices to coarsen down to? */ 2721 int ndims = 1; /* number of eigenvectors (2^d sets) */ 2722 double eigtol = 0.001; /* tolerance on eigenvectors */ 2723 long seed = 123636512; /* for random graph mutations */ 2724 short int *assignment; /* Output partition */ 2725 int fd_stdout, fd_pipe[2]; 2726 PetscInt *points; 2727 PetscMPIInt commSize; 2728 int i, v, p; 2729 PetscErrorCode ierr; 2730 2731 PetscFunctionBegin; 2732 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2733 ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2734 if (!numVertices) { 2735 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2736 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2737 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2738 ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2739 PetscFunctionReturn(0); 2740 } 2741 FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2742 for (i = 0; i < start[numVertices]; ++i) ++adjacency[i]; 2743 2744 if (global_method == INERTIAL_METHOD) { 2745 /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2746 SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2747 } 2748 mesh_dims[0] = commSize; 2749 mesh_dims[1] = 1; 2750 mesh_dims[2] = 1; 2751 ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2752 /* Chaco outputs to stdout. We redirect this to a buffer. */ 2753 /* TODO: check error codes for UNIX calls */ 2754 #if defined(PETSC_HAVE_UNISTD_H) 2755 { 2756 int piperet; 2757 piperet = pipe(fd_pipe); 2758 if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe"); 2759 fd_stdout = dup(1); 2760 close(1); 2761 dup2(fd_pipe[1], 1); 2762 } 2763 #endif 2764 ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2765 assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2766 vmax, ndims, eigtol, seed); 2767 #if defined(PETSC_HAVE_UNISTD_H) 2768 { 2769 char msgLog[10000]; 2770 int count; 2771 2772 fflush(stdout); 2773 count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2774 if (count < 0) count = 0; 2775 msgLog[count] = 0; 2776 close(1); 2777 dup2(fd_stdout, 1); 2778 close(fd_stdout); 2779 close(fd_pipe[0]); 2780 close(fd_pipe[1]); 2781 if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2782 } 2783 #endif 2784 /* Convert to PetscSection+IS */ 2785 ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2786 ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2787 for (v = 0; v < nvtxs; ++v) { 2788 ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2789 } 2790 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2791 ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2792 for (p = 0, i = 0; p < commSize; ++p) { 2793 for (v = 0; v < nvtxs; ++v) { 2794 if (assignment[v] == p) points[i++] = v; 2795 } 2796 } 2797 if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2798 ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2799 if (global_method == INERTIAL_METHOD) { 2800 /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2801 } 2802 ierr = PetscFree(assignment);CHKERRQ(ierr); 2803 for (i = 0; i < start[numVertices]; ++i) --adjacency[i]; 2804 PetscFunctionReturn(0); 2805 } 2806 #endif 2807 2808 #if defined(PETSC_HAVE_PARMETIS) 2809 #undef __FUNCT__ 2810 #define __FUNCT__ "DMPlexPartition_ParMetis" 2811 PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2812 { 2813 PetscFunctionBegin; 2814 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ParMetis not yet supported"); 2815 PetscFunctionReturn(0); 2816 } 2817 #endif 2818 2819 #undef __FUNCT__ 2820 #define __FUNCT__ "DMPlexEnlargePartition" 2821 /* Expand the partition by BFS on the adjacency graph */ 2822 PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) 2823 { 2824 PetscHashI h; 2825 const PetscInt *points; 2826 PetscInt **tmpPoints, *newPoints, totPoints = 0; 2827 PetscInt pStart, pEnd, part, q; 2828 PetscErrorCode ierr; 2829 2830 PetscFunctionBegin; 2831 PetscHashICreate(h); 2832 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2833 ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2834 ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2835 ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2836 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt*), &tmpPoints);CHKERRQ(ierr); 2837 for (part = pStart; part < pEnd; ++part) { 2838 PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2839 2840 PetscHashIClear(h); 2841 ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2842 ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2843 /* Add all existing points to h */ 2844 for (p = 0; p < numPoints; ++p) { 2845 const PetscInt point = points[off+p]; 2846 PetscHashIAdd(h, point, 1); 2847 } 2848 PetscHashISize(h, nP); 2849 if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2850 /* Add all points in next BFS level */ 2851 /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2852 for (p = 0; p < numPoints; ++p) { 2853 const PetscInt point = points[off+p]; 2854 PetscInt s = start[point], e = start[point+1], a; 2855 2856 for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1); 2857 } 2858 PetscHashISize(h, numNewPoints); 2859 ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2860 ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2861 if (numNewPoints) PetscHashIGetKeys(h, n, tmpPoints[part]); /* Should not need this conditional */ 2862 totPoints += numNewPoints; 2863 } 2864 ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2865 PetscHashIDestroy(h); 2866 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2867 ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2868 for (part = pStart, q = 0; part < pEnd; ++part) { 2869 PetscInt numPoints, p; 2870 2871 ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2872 for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p]; 2873 ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2874 } 2875 ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2876 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2877 PetscFunctionReturn(0); 2878 } 2879 2880 #undef __FUNCT__ 2881 #define __FUNCT__ "DMPlexCreatePartition" 2882 /* 2883 DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2884 2885 Collective on DM 2886 2887 Input Parameters: 2888 + dm - The DM 2889 . height - The height for points in the partition 2890 - enlarge - Expand each partition with neighbors 2891 2892 Output Parameters: 2893 + partSection - The PetscSection giving the division of points by partition 2894 . partition - The list of points by partition 2895 . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL 2896 - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL 2897 2898 Level: developer 2899 2900 .seealso DMPlexDistribute() 2901 */ 2902 PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) 2903 { 2904 PetscMPIInt size; 2905 PetscErrorCode ierr; 2906 2907 PetscFunctionBegin; 2908 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 2909 2910 *origPartSection = NULL; 2911 *origPartition = NULL; 2912 if (size == 1) { 2913 PetscInt *points; 2914 PetscInt cStart, cEnd, c; 2915 2916 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2917 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr); 2918 ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2919 ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2920 ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2921 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2922 for (c = cStart; c < cEnd; ++c) points[c] = c; 2923 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2924 PetscFunctionReturn(0); 2925 } 2926 if (height == 0) { 2927 PetscInt numVertices; 2928 PetscInt *start = NULL; 2929 PetscInt *adjacency = NULL; 2930 2931 ierr = DMPlexCreateNeighborCSR(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2932 if (1) { 2933 #if defined(PETSC_HAVE_CHACO) 2934 ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2935 #endif 2936 } else { 2937 #if defined(PETSC_HAVE_PARMETIS) 2938 ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2939 #endif 2940 } 2941 if (enlarge) { 2942 *origPartSection = *partSection; 2943 *origPartition = *partition; 2944 2945 ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2946 } 2947 ierr = PetscFree(start);CHKERRQ(ierr); 2948 ierr = PetscFree(adjacency);CHKERRQ(ierr); 2949 # if 0 2950 } else if (height == 1) { 2951 /* Build the dual graph for faces and partition the hypergraph */ 2952 PetscInt numEdges; 2953 2954 buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2955 GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2956 destroyCSR(numEdges, start, adjacency); 2957 #endif 2958 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2959 PetscFunctionReturn(0); 2960 } 2961 2962 #undef __FUNCT__ 2963 #define __FUNCT__ "DMPlexCreatePartitionClosure" 2964 PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) 2965 { 2966 /* const PetscInt height = 0; */ 2967 const PetscInt *partArray; 2968 PetscInt *allPoints, *partPoints = NULL; 2969 PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2970 PetscErrorCode ierr; 2971 2972 PetscFunctionBegin; 2973 ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2974 ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2975 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2976 ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2977 for (rank = rStart; rank < rEnd; ++rank) { 2978 PetscInt partSize = 0; 2979 PetscInt numPoints, offset, p; 2980 2981 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2982 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2983 for (p = 0; p < numPoints; ++p) { 2984 PetscInt point = partArray[offset+p], closureSize, c; 2985 PetscInt *closure = NULL; 2986 2987 /* TODO Include support for height > 0 case */ 2988 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2989 /* Merge into existing points */ 2990 if (partSize+closureSize > maxPartSize) { 2991 PetscInt *tmpPoints; 2992 2993 maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2994 ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2995 ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 2996 ierr = PetscFree(partPoints);CHKERRQ(ierr); 2997 2998 partPoints = tmpPoints; 2999 } 3000 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3001 partSize += closureSize; 3002 3003 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3004 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3005 } 3006 ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3007 } 3008 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3009 ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3010 ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3011 3012 for (rank = rStart; rank < rEnd; ++rank) { 3013 PetscInt partSize = 0, newOffset; 3014 PetscInt numPoints, offset, p; 3015 3016 ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3017 ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3018 for (p = 0; p < numPoints; ++p) { 3019 PetscInt point = partArray[offset+p], closureSize, c; 3020 PetscInt *closure = NULL; 3021 3022 /* TODO Include support for height > 0 case */ 3023 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3024 /* Merge into existing points */ 3025 for (c = 0; c < closureSize; ++c) partPoints[partSize+c] = closure[c*2]; 3026 partSize += closureSize; 3027 3028 ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3029 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3030 } 3031 ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3032 ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3033 } 3034 ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3035 ierr = PetscFree(partPoints);CHKERRQ(ierr); 3036 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3037 PetscFunctionReturn(0); 3038 } 3039 3040 #undef __FUNCT__ 3041 #define __FUNCT__ "DMPlexDistributeField" 3042 /* 3043 Input Parameters: 3044 . originalSection 3045 , originalVec 3046 3047 Output Parameters: 3048 . newSection 3049 . newVec 3050 */ 3051 PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3052 { 3053 PetscSF fieldSF; 3054 PetscInt *remoteOffsets, fieldSize; 3055 PetscScalar *originalValues, *newValues; 3056 PetscErrorCode ierr; 3057 3058 PetscFunctionBegin; 3059 ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3060 3061 ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3062 ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3063 ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3064 3065 ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3066 ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3067 ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3068 ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3069 ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3070 ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3071 ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3072 ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3073 PetscFunctionReturn(0); 3074 } 3075 3076 #undef __FUNCT__ 3077 #define __FUNCT__ "DMPlexDistribute" 3078 /*@C 3079 DMPlexDistribute - Distributes the mesh and any associated sections. 3080 3081 Not Collective 3082 3083 Input Parameter: 3084 + dm - The original DMPlex object 3085 . partitioner - The partitioning package, or NULL for the default 3086 - overlap - The overlap of partitions, 0 is the default 3087 3088 Output Parameter: 3089 . parallelMesh - The distributed DMPlex object, or NULL 3090 3091 Note: If the mesh was not distributed, the return value is NULL 3092 3093 Level: intermediate 3094 3095 .keywords: mesh, elements 3096 .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3097 @*/ 3098 PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3099 { 3100 DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 3101 MPI_Comm comm; 3102 const PetscInt height = 0; 3103 PetscInt dim, numRemoteRanks; 3104 IS origCellPart, cellPart, part; 3105 PetscSection origCellPartSection, cellPartSection, partSection; 3106 PetscSFNode *remoteRanks; 3107 PetscSF partSF, pointSF, coneSF; 3108 ISLocalToGlobalMapping renumbering; 3109 PetscSection originalConeSection, newConeSection; 3110 PetscInt *remoteOffsets; 3111 PetscInt *cones, *newCones, newConesSize; 3112 PetscBool flg; 3113 PetscMPIInt rank, numProcs, p; 3114 PetscErrorCode ierr; 3115 3116 PetscFunctionBegin; 3117 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3118 PetscValidPointer(dmParallel,4); 3119 3120 ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3121 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3122 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3123 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3124 3125 *dmParallel = NULL; 3126 if (numProcs == 1) PetscFunctionReturn(0); 3127 3128 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3129 /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3130 if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3131 ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3132 /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3133 if (!rank) numRemoteRanks = numProcs; 3134 else numRemoteRanks = 0; 3135 ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3136 for (p = 0; p < numRemoteRanks; ++p) { 3137 remoteRanks[p].rank = p; 3138 remoteRanks[p].index = 0; 3139 } 3140 ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3141 ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3142 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3143 if (flg) { 3144 ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3145 ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3146 ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 3147 if (origCellPart) { 3148 ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3149 ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3150 ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 3151 } 3152 ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 3153 } 3154 /* Close the partition over the mesh */ 3155 ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3156 ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3157 ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3158 /* Create new mesh */ 3159 ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3160 ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3161 ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3162 pmesh = (DM_Plex*) (*dmParallel)->data; 3163 /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3164 ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3165 if (flg) { 3166 ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3167 ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3168 ierr = ISView(part, NULL);CHKERRQ(ierr); 3169 ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 3170 ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3171 ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 3172 } 3173 /* Distribute cone section */ 3174 ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3175 ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3176 ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3177 ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3178 { 3179 PetscInt pStart, pEnd, p; 3180 3181 ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3182 for (p = pStart; p < pEnd; ++p) { 3183 PetscInt coneSize; 3184 ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3185 pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3186 } 3187 } 3188 /* Communicate and renumber cones */ 3189 ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3190 ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3191 ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3192 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3193 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3194 ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3195 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 3196 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3197 if (flg) { 3198 ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3199 ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3200 ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3201 ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3202 ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 3203 } 3204 ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3205 ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3206 ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3207 ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3208 ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3209 /* Create supports and stratify sieve */ 3210 { 3211 PetscInt pStart, pEnd; 3212 3213 ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3214 ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3215 } 3216 ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3217 ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3218 /* Distribute Coordinates */ 3219 { 3220 PetscSection originalCoordSection, newCoordSection; 3221 Vec originalCoordinates, newCoordinates; 3222 const char *name; 3223 3224 ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3225 ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3226 ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3227 ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3228 ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3229 ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3230 3231 ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3232 ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3233 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3234 } 3235 /* Distribute labels */ 3236 { 3237 DMLabel next = mesh->labels, newNext = pmesh->labels; 3238 PetscInt numLabels = 0, l; 3239 3240 /* Bcast number of labels */ 3241 while (next) { 3242 ++numLabels; next = next->next; 3243 } 3244 ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3245 next = mesh->labels; 3246 for (l = 0; l < numLabels; ++l) { 3247 DMLabel newLabel; 3248 const PetscInt *partArray; 3249 char *name; 3250 PetscInt *stratumSizes = NULL, *points = NULL; 3251 PetscMPIInt *sendcnts = NULL, *offsets = NULL, *displs = NULL; 3252 PetscInt nameSize, s, p; 3253 PetscBool isdepth; 3254 size_t len = 0; 3255 3256 /* Bcast name (could filter for no points) */ 3257 if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3258 nameSize = len; 3259 ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3260 ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3261 if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3262 ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3263 ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3264 if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3265 ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3266 newLabel->name = name; 3267 /* Bcast numStrata (could filter for no points in stratum) */ 3268 if (!rank) newLabel->numStrata = next->numStrata; 3269 ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3270 ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3271 newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3272 newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3273 /* Bcast stratumValues (could filter for no points in stratum) */ 3274 if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3275 ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3276 /* Find size on each process and Scatter */ 3277 if (!rank) { 3278 ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3279 ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3280 ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3281 for (s = 0; s < next->numStrata; ++s) { 3282 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3283 const PetscInt point = next->points[p]; 3284 PetscInt proc; 3285 3286 for (proc = 0; proc < numProcs; ++proc) { 3287 PetscInt dof, off, pPart; 3288 3289 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3290 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3291 for (pPart = off; pPart < off+dof; ++pPart) { 3292 if (partArray[pPart] == point) { 3293 ++stratumSizes[proc*next->numStrata+s]; 3294 break; 3295 } 3296 } 3297 } 3298 } 3299 } 3300 ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3301 } 3302 ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3303 /* Calculate stratumOffsets */ 3304 newLabel->stratumOffsets[0] = 0; 3305 for (s = 0; s < newLabel->numStrata; ++s) { 3306 newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3307 } 3308 /* Pack points and Scatter */ 3309 if (!rank) { 3310 ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3311 displs[0] = 0; 3312 for (p = 0; p < numProcs; ++p) { 3313 sendcnts[p] = 0; 3314 for (s = 0; s < next->numStrata; ++s) { 3315 sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3316 } 3317 offsets[p] = displs[p]; 3318 displs[p+1] = displs[p] + sendcnts[p]; 3319 } 3320 ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3321 for (s = 0; s < next->numStrata; ++s) { 3322 for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3323 const PetscInt point = next->points[p]; 3324 PetscInt proc; 3325 3326 for (proc = 0; proc < numProcs; ++proc) { 3327 PetscInt dof, off, pPart; 3328 3329 ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3330 ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3331 for (pPart = off; pPart < off+dof; ++pPart) { 3332 if (partArray[pPart] == point) { 3333 points[offsets[proc]++] = point; 3334 break; 3335 } 3336 } 3337 } 3338 } 3339 } 3340 } 3341 ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3342 ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3343 ierr = PetscFree(points);CHKERRQ(ierr); 3344 ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3345 ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3346 /* Renumber points */ 3347 ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, NULL, newLabel->points);CHKERRQ(ierr); 3348 /* Sort points */ 3349 for (s = 0; s < newLabel->numStrata; ++s) { 3350 ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3351 } 3352 /* Insert into list */ 3353 if (newNext) newNext->next = newLabel; 3354 else pmesh->labels = newLabel; 3355 newNext = newLabel; 3356 if (!rank) next = next->next; 3357 } 3358 } 3359 /* Cleanup Partition */ 3360 ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3361 ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3362 ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3363 ierr = ISDestroy(&part);CHKERRQ(ierr); 3364 /* Create point SF for parallel mesh */ 3365 { 3366 const PetscInt *leaves; 3367 PetscSFNode *remotePoints, *rowners, *lowners; 3368 PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3369 PetscInt pStart, pEnd; 3370 3371 ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3372 ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 3373 ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3374 for (p=0; p<numRoots; p++) { 3375 rowners[p].rank = -1; 3376 rowners[p].index = -1; 3377 } 3378 if (origCellPart) { 3379 /* Make sure cells in the original partition are not assigned to other procs */ 3380 const PetscInt *origCells; 3381 3382 ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3383 for (p = 0; p < numProcs; ++p) { 3384 PetscInt dof, off, d; 3385 3386 ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3387 ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3388 for (d = off; d < off+dof; ++d) { 3389 rowners[origCells[d]].rank = p; 3390 } 3391 } 3392 ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3393 } 3394 ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3395 ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3396 3397 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3398 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3399 for (p = 0; p < numLeaves; ++p) { 3400 if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3401 lowners[p].rank = rank; 3402 lowners[p].index = leaves ? leaves[p] : p; 3403 } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3404 lowners[p].rank = -2; 3405 lowners[p].index = -2; 3406 } 3407 } 3408 for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3409 rowners[p].rank = -3; 3410 rowners[p].index = -3; 3411 } 3412 ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3413 ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3414 ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3415 ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3416 for (p = 0; p < numLeaves; ++p) { 3417 if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3418 if (lowners[p].rank != rank) ++numGhostPoints; 3419 } 3420 ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3421 ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3422 for (p = 0, gp = 0; p < numLeaves; ++p) { 3423 if (lowners[p].rank != rank) { 3424 ghostPoints[gp] = leaves ? leaves[p] : p; 3425 remotePoints[gp].rank = lowners[p].rank; 3426 remotePoints[gp].index = lowners[p].index; 3427 ++gp; 3428 } 3429 } 3430 ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3431 ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3432 ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3433 } 3434 /* Cleanup */ 3435 ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3436 ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3437 ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3438 PetscFunctionReturn(0); 3439 } 3440 3441 #undef __FUNCT__ 3442 #define __FUNCT__ "DMPlexRenumber_Private" 3443 /* 3444 Reasons to renumber: 3445 3446 1) Permute points, e.g. bandwidth reduction (Renumber) 3447 3448 a) Must not mix strata 3449 3450 2) Shift numbers for point insertion (Shift) 3451 3452 a) Want operation brken into parts so that insertion can be interleaved 3453 3454 renumbering - An IS which provides the new numbering 3455 */ 3456 PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3457 { 3458 PetscFunctionBegin; 3459 PetscFunctionReturn(0); 3460 } 3461 3462 #undef __FUNCT__ 3463 #define __FUNCT__ "DMPlexShiftPoint_Private" 3464 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3465 { 3466 if (depth < 0) return p; 3467 /* Cells */ if (p < depthEnd[depth]) return p; 3468 /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3469 /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3470 /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3471 } 3472 3473 #undef __FUNCT__ 3474 #define __FUNCT__ "DMPlexShiftSizes_Private" 3475 PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3476 { 3477 PetscInt *depthEnd; 3478 PetscInt depth = 0, d, pStart, pEnd, p; 3479 PetscErrorCode ierr; 3480 3481 PetscFunctionBegin; 3482 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3483 if (depth < 0) PetscFunctionReturn(0); 3484 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3485 /* Step 1: Expand chart */ 3486 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3487 for (d = 0; d <= depth; ++d) { 3488 pEnd += depthShift[d]; 3489 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3490 } 3491 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3492 /* Step 2: Set cone and support sizes */ 3493 for (d = 0; d <= depth; ++d) { 3494 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3495 for (p = pStart; p < pEnd; ++p) { 3496 PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3497 PetscInt size; 3498 3499 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3500 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3501 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3502 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3503 } 3504 } 3505 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3506 PetscFunctionReturn(0); 3507 } 3508 3509 #undef __FUNCT__ 3510 #define __FUNCT__ "DMPlexShiftPoints_Private" 3511 PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3512 { 3513 PetscInt *depthEnd, *newpoints; 3514 PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3515 PetscErrorCode ierr; 3516 3517 PetscFunctionBegin; 3518 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3519 if (depth < 0) PetscFunctionReturn(0); 3520 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3521 ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3522 for (d = 0; d <= depth; ++d) { 3523 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3524 } 3525 /* Step 5: Set cones and supports */ 3526 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3527 for (p = pStart; p < pEnd; ++p) { 3528 const PetscInt *points = NULL, *orientations = NULL; 3529 PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3530 3531 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3532 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3533 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3534 for (i = 0; i < size; ++i) { 3535 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3536 } 3537 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3538 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3539 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3540 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3541 for (i = 0; i < size; ++i) { 3542 newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3543 } 3544 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3545 } 3546 ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3547 PetscFunctionReturn(0); 3548 } 3549 3550 #undef __FUNCT__ 3551 #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3552 PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3553 { 3554 PetscSection coordSection, newCoordSection; 3555 Vec coordinates, newCoordinates; 3556 PetscScalar *coords, *newCoords; 3557 PetscInt *depthEnd, coordSize; 3558 PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v; 3559 PetscErrorCode ierr; 3560 3561 PetscFunctionBegin; 3562 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3563 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3564 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3565 for (d = 0; d <= depth; ++d) { 3566 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3567 } 3568 /* Step 8: Convert coordinates */ 3569 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3570 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3571 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3572 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newCoordSection);CHKERRQ(ierr); 3573 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3574 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3575 ierr = PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);CHKERRQ(ierr); 3576 for (v = vStartNew; v < vEndNew; ++v) { 3577 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 3578 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 3579 } 3580 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3581 ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3582 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 3583 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &newCoordinates);CHKERRQ(ierr); 3584 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 3585 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3586 ierr = VecSetFromOptions(newCoordinates);CHKERRQ(ierr); 3587 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 3588 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3589 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3590 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3591 for (v = vStart; v < vEnd; ++v) { 3592 PetscInt dof, off, noff, d; 3593 3594 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 3595 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 3596 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift), &noff);CHKERRQ(ierr); 3597 for (d = 0; d < dof; ++d) { 3598 newCoords[noff+d] = coords[off+d]; 3599 } 3600 } 3601 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3602 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 3603 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3604 ierr = PetscSectionDestroy(&newCoordSection);CHKERRQ(ierr); 3605 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3606 PetscFunctionReturn(0); 3607 } 3608 3609 #undef __FUNCT__ 3610 #define __FUNCT__ "DMPlexShiftSF_Private" 3611 PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3612 { 3613 PetscInt *depthEnd; 3614 PetscInt depth = 0, d; 3615 PetscSF sfPoint, sfPointNew; 3616 const PetscSFNode *remotePoints; 3617 PetscSFNode *gremotePoints; 3618 const PetscInt *localPoints; 3619 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3620 PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3621 PetscMPIInt numProcs; 3622 PetscErrorCode ierr; 3623 3624 PetscFunctionBegin; 3625 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3626 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3627 for (d = 0; d <= depth; ++d) { 3628 totShift += depthShift[d]; 3629 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3630 } 3631 /* Step 9: Convert pointSF */ 3632 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 3633 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3634 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3635 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3636 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3637 if (numRoots >= 0) { 3638 ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3639 for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3640 ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3641 ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3642 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3643 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3644 for (l = 0; l < numLeaves; ++l) { 3645 glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3646 gremotePoints[l].rank = remotePoints[l].rank; 3647 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3648 } 3649 ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3650 ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3651 } 3652 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3653 PetscFunctionReturn(0); 3654 } 3655 3656 #undef __FUNCT__ 3657 #define __FUNCT__ "DMPlexShiftLabels_Private" 3658 PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3659 { 3660 PetscSF sfPoint; 3661 DMLabel vtkLabel, ghostLabel; 3662 PetscInt *depthEnd; 3663 const PetscSFNode *leafRemote; 3664 const PetscInt *leafLocal; 3665 PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3666 PetscMPIInt rank; 3667 PetscErrorCode ierr; 3668 3669 PetscFunctionBegin; 3670 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3671 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3672 for (d = 0; d <= depth; ++d) { 3673 ierr = DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);CHKERRQ(ierr); 3674 } 3675 /* Step 10: Convert labels */ 3676 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3677 for (l = 0; l < numLabels; ++l) { 3678 DMLabel label, newlabel; 3679 const char *lname; 3680 PetscBool isDepth; 3681 IS valueIS; 3682 const PetscInt *values; 3683 PetscInt numValues, val; 3684 3685 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3686 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3687 if (isDepth) continue; 3688 ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3689 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3690 ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3691 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3692 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3693 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3694 for (val = 0; val < numValues; ++val) { 3695 IS pointIS; 3696 const PetscInt *points; 3697 PetscInt numPoints, p; 3698 3699 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3700 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3701 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3702 for (p = 0; p < numPoints; ++p) { 3703 const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3704 3705 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3706 } 3707 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3708 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3709 } 3710 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3711 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3712 } 3713 ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3714 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3715 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 3716 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3717 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3718 ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3719 ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3720 ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3721 ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3722 ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3723 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3724 for (; c < leafLocal[l] && c < cEnd; ++c) { 3725 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3726 } 3727 if (leafLocal[l] >= cEnd) break; 3728 if (leafRemote[l].rank == rank) { 3729 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3730 } else { 3731 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3732 } 3733 } 3734 for (; c < cEnd; ++c) { 3735 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3736 } 3737 if (0) { 3738 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3739 ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3740 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3741 } 3742 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3743 for (f = fStart; f < fEnd; ++f) { 3744 PetscInt numCells; 3745 3746 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3747 if (numCells < 2) { 3748 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3749 } else { 3750 const PetscInt *cells = NULL; 3751 PetscInt vA, vB; 3752 3753 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3754 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3755 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3756 if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3757 } 3758 } 3759 if (0) { 3760 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3761 ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3762 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3763 } 3764 PetscFunctionReturn(0); 3765 } 3766 3767 #undef __FUNCT__ 3768 #define __FUNCT__ "DMPlexConstructGhostCells_Internal" 3769 static PetscErrorCode DMPlexConstructGhostCells_Internal(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3770 { 3771 DMLabel label; 3772 IS valueIS; 3773 const PetscInt *values; 3774 PetscInt *depthShift; 3775 PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3776 PetscErrorCode ierr; 3777 3778 PetscFunctionBegin; 3779 /* Count ghost cells */ 3780 ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3781 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3782 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3783 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3784 3785 *numGhostCells = 0; 3786 for (fs = 0; fs < numFS; ++fs) { 3787 PetscInt numBdFaces; 3788 3789 ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3790 3791 *numGhostCells += numBdFaces; 3792 } 3793 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3794 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3795 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3796 if (depth >= 0) depthShift[depth] = *numGhostCells; 3797 ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3798 /* Step 3: Set cone/support sizes for new points */ 3799 ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr); 3800 for (c = cEnd; c < cEnd + *numGhostCells; ++c) { 3801 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3802 } 3803 for (fs = 0; fs < numFS; ++fs) { 3804 IS faceIS; 3805 const PetscInt *faces; 3806 PetscInt numFaces, f; 3807 3808 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3809 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3810 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3811 for (f = 0; f < numFaces; ++f) { 3812 PetscInt size; 3813 3814 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3815 if (size != 1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3816 ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3817 } 3818 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3819 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3820 } 3821 /* Step 4: Setup ghosted DM */ 3822 ierr = DMSetUp(gdm);CHKERRQ(ierr); 3823 ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3824 /* Step 6: Set cones and supports for new points */ 3825 ghostCell = cEnd; 3826 for (fs = 0; fs < numFS; ++fs) { 3827 IS faceIS; 3828 const PetscInt *faces; 3829 PetscInt numFaces, f; 3830 3831 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3832 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3833 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3834 for (f = 0; f < numFaces; ++f, ++ghostCell) { 3835 PetscInt newFace = faces[f] + *numGhostCells; 3836 3837 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3838 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3839 } 3840 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3841 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3842 } 3843 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3844 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3845 /* Step 7: Stratify */ 3846 ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3847 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3848 ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3849 ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3850 ierr = PetscFree(depthShift);CHKERRQ(ierr); 3851 PetscFunctionReturn(0); 3852 } 3853 3854 #undef __FUNCT__ 3855 #define __FUNCT__ "DMPlexConstructGhostCells" 3856 /*@C 3857 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3858 3859 Collective on dm 3860 3861 Input Parameters: 3862 + dm - The original DM 3863 - labelName - The label specifying the boundary faces, or "Face Sets" if this is NULL 3864 3865 Output Parameters: 3866 + numGhostCells - The number of ghost cells added to the DM 3867 - dmGhosted - The new DM 3868 3869 Level: developer 3870 3871 .seealso: DMCreate() 3872 */ 3873 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3874 { 3875 DM gdm; 3876 PetscInt dim; 3877 PetscErrorCode ierr; 3878 3879 PetscFunctionBegin; 3880 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3881 PetscValidPointer(numGhostCells, 3); 3882 PetscValidPointer(dmGhosted, 4); 3883 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &gdm);CHKERRQ(ierr); 3884 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3885 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3886 ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3887 ierr = DMPlexConstructGhostCells_Internal(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3888 ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3889 *dmGhosted = gdm; 3890 PetscFunctionReturn(0); 3891 } 3892 3893 #undef __FUNCT__ 3894 #define __FUNCT__ "DMPlexConstructCohesiveCells_Private" 3895 PetscErrorCode DMPlexConstructCohesiveCells_Private(DM dm, DMLabel label, DM sdm) 3896 { 3897 MPI_Comm comm; 3898 IS valueIS, *pointIS; 3899 const PetscInt *values, **splitPoints; 3900 PetscSection coordSection; 3901 Vec coordinates; 3902 PetscScalar *coords; 3903 PetscInt *depthShift, *depthOffset, *pMaxNew, *numSplitPoints, *coneNew, *supportNew; 3904 PetscInt shift = 100, depth = 0, dep, dim, d, numSP = 0, sp, maxConeSize, maxSupportSize, numLabels, p, v; 3905 PetscErrorCode ierr; 3906 3907 PetscFunctionBegin; 3908 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3909 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3910 /* Count split points and add cohesive cells */ 3911 if (label) { 3912 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3913 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 3914 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3915 } 3916 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3917 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3918 ierr = PetscMalloc5(depth+1,PetscInt,&depthShift,depth+1,PetscInt,&depthOffset,depth+1,PetscInt,&pMaxNew,maxConeSize*3,PetscInt,&coneNew,maxSupportSize,PetscInt,&supportNew);CHKERRQ(ierr); 3919 ierr = PetscMalloc3(depth+1,IS,&pointIS,depth+1,PetscInt,&numSplitPoints,depth+1,const PetscInt*,&splitPoints);CHKERRQ(ierr); 3920 ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3921 for (d = 0; d <= depth; ++d) { 3922 ierr = DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);CHKERRQ(ierr); 3923 numSplitPoints[d] = 0; 3924 splitPoints[d] = NULL; 3925 pointIS[d] = NULL; 3926 } 3927 for (sp = 0; sp < numSP; ++sp) { 3928 const PetscInt dep = values[sp]; 3929 3930 if ((dep < 0) || (dep > depth)) continue; 3931 ierr = DMLabelGetStratumSize(label, dep, &depthShift[dep]);CHKERRQ(ierr); 3932 ierr = DMLabelGetStratumIS(label, dep, &pointIS[dep]);CHKERRQ(ierr); 3933 if (pointIS[dep]) { 3934 ierr = ISGetLocalSize(pointIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 3935 ierr = ISGetIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 3936 } 3937 } 3938 if (depth >= 0) { 3939 /* Calculate number of additional points */ 3940 depthShift[depth] = depthShift[depth-1]; /* There is a cohesive cell for every split face */ 3941 depthShift[1] += depthShift[0]; /* There is a cohesive edge for every split vertex */ 3942 /* Calculate hybrid bound for each dimension */ 3943 pMaxNew[0] += depthShift[depth]; 3944 if (depth > 1) pMaxNew[dim-1] += depthShift[depth] + depthShift[0]; 3945 if (depth > 2) pMaxNew[1] += depthShift[depth] + depthShift[0] + depthShift[dim-1]; 3946 3947 /* Calculate point offset for each dimension */ 3948 depthOffset[depth] = 0; 3949 depthOffset[0] = depthOffset[depth] + depthShift[depth]; 3950 if (depth > 1) depthOffset[dim-1] = depthOffset[0] + depthShift[0]; 3951 if (depth > 2) depthOffset[1] = depthOffset[dim-1] + depthShift[dim-1]; 3952 } 3953 ierr = DMPlexShiftSizes_Private(dm, depthShift, sdm);CHKERRQ(ierr); 3954 /* Step 3: Set cone/support sizes for new points */ 3955 for (dep = 0; dep <= depth; ++dep) { 3956 for (p = 0; p < numSplitPoints[dep]; ++p) { 3957 const PetscInt oldp = splitPoints[dep][p]; 3958 const PetscInt newp = depthOffset[dep] + oldp; 3959 const PetscInt splitp = pMaxNew[dep] + p; 3960 const PetscInt *support; 3961 PetscInt coneSize, supportSize, q, e; 3962 3963 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 3964 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 3965 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 3966 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 3967 if (dep == depth-1) { 3968 const PetscInt ccell = pMaxNew[depth] + p; 3969 /* Add cohesive cells, they are prisms */ 3970 ierr = DMPlexSetConeSize(sdm, ccell, 2 + coneSize);CHKERRQ(ierr); 3971 } else if (dep == 0) { 3972 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 3973 3974 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3975 /* Split old vertex: Edges in old split faces and new cohesive edge */ 3976 for (e = 0, q = 0; e < supportSize; ++e) { 3977 PetscInt val; 3978 3979 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3980 if ((val == 1) || (val == (shift + 1))) ++q; 3981 } 3982 ierr = DMPlexSetSupportSize(sdm, newp, q+1);CHKERRQ(ierr); 3983 /* Split new vertex: Edges in new split faces and new cohesive edge */ 3984 for (e = 0, q = 0; e < supportSize; ++e) { 3985 PetscInt val; 3986 3987 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 3988 if ((val == 1) || (val == -(shift + 1))) ++q; 3989 } 3990 ierr = DMPlexSetSupportSize(sdm, splitp, q+1);CHKERRQ(ierr); 3991 /* Add cohesive edges */ 3992 ierr = DMPlexSetConeSize(sdm, cedge, 2);CHKERRQ(ierr); 3993 /* Punt for now on support, you loop over closure, extract faces, check which ones are in the label */ 3994 } else if (dep == dim-2) { 3995 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 3996 /* Split old edge: Faces in positive side cells and old split faces */ 3997 for (e = 0, q = 0; e < supportSize; ++e) { 3998 PetscInt val; 3999 4000 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4001 if ((val == dim-1) || (val == (shift + dim-1))) ++q; 4002 } 4003 ierr = DMPlexSetSupportSize(sdm, newp, q);CHKERRQ(ierr); 4004 /* Split new edge: Faces in negative side cells and new split faces */ 4005 for (e = 0, q = 0; e < supportSize; ++e) { 4006 PetscInt val; 4007 4008 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4009 if ((val == dim-1) || (val == -(shift + dim-1))) ++q; 4010 } 4011 ierr = DMPlexSetSupportSize(sdm, splitp, q);CHKERRQ(ierr); 4012 } 4013 } 4014 } 4015 /* Step 4: Setup split DM */ 4016 ierr = DMSetUp(sdm);CHKERRQ(ierr); 4017 ierr = DMPlexShiftPoints_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4018 /* Step 6: Set cones and supports for new points */ 4019 for (dep = 0; dep <= depth; ++dep) { 4020 for (p = 0; p < numSplitPoints[dep]; ++p) { 4021 const PetscInt oldp = splitPoints[dep][p]; 4022 const PetscInt newp = depthOffset[dep] + oldp; 4023 const PetscInt splitp = pMaxNew[dep] + p; 4024 const PetscInt *cone, *support, *ornt; 4025 PetscInt coneSize, supportSize, q, v, e, s; 4026 4027 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 4028 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 4029 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 4030 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 4031 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 4032 if (dep == depth-1) { 4033 const PetscInt ccell = pMaxNew[depth] + p; 4034 const PetscInt *supportF; 4035 4036 /* Split face: copy in old face to new face to start */ 4037 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 4038 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 4039 /* Split old face: old vertices/edges in cone so no change */ 4040 /* Split new face: new vertices/edges in cone */ 4041 for (q = 0; q < coneSize; ++q) { 4042 ierr = PetscFindInt(cone[q], numSplitPoints[dim-2], splitPoints[dim-2], &v);CHKERRQ(ierr); 4043 4044 coneNew[2+q] = pMaxNew[dim-2] + v; 4045 } 4046 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 4047 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 4048 /* Cohesive cell: Old and new split face, then new cohesive edges */ 4049 coneNew[0] = newp; 4050 coneNew[1] = splitp; 4051 for (q = 0; q < coneSize; ++q) { 4052 coneNew[2+q] = (pMaxNew[1] - pMaxNew[dim-2]) + (depthShift[1] - depthShift[0]) + coneNew[2+q]; 4053 } 4054 ierr = DMPlexSetCone(sdm, ccell, coneNew);CHKERRQ(ierr); 4055 4056 4057 for (s = 0; s < supportSize; ++s) { 4058 PetscInt val; 4059 4060 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 4061 if (val < 0) { 4062 /* Split old face: Replace negative side cell with cohesive cell */ 4063 ierr = DMPlexInsertSupport(sdm, newp, s, ccell);CHKERRQ(ierr); 4064 } else { 4065 /* Split new face: Replace positive side cell with cohesive cell */ 4066 ierr = DMPlexInsertSupport(sdm, splitp, s, ccell);CHKERRQ(ierr); 4067 } 4068 } 4069 } else if (dep == 0) { 4070 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4071 4072 /* Split old vertex: Edges in old split faces and new cohesive edge */ 4073 for (e = 0, q = 0; e < supportSize; ++e) { 4074 PetscInt val; 4075 4076 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4077 if ((val == 1) || (val == (shift + 1))) { 4078 supportNew[q++] = depthOffset[1] + support[e]; 4079 } 4080 } 4081 supportNew[q] = cedge; 4082 4083 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4084 /* Split new vertex: Edges in new split faces and new cohesive edge */ 4085 for (e = 0, q = 0; e < supportSize; ++e) { 4086 PetscInt val, edge; 4087 4088 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4089 if (val == 1) { 4090 ierr = PetscFindInt(support[e], numSplitPoints[1], splitPoints[1], &edge);CHKERRQ(ierr); 4091 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 4092 supportNew[q++] = pMaxNew[1] + edge; 4093 } else if (val == -(shift + 1)) { 4094 supportNew[q++] = depthOffset[1] + support[e]; 4095 } 4096 } 4097 supportNew[q] = cedge; 4098 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4099 /* Cohesive edge: Old and new split vertex, punting on support */ 4100 coneNew[0] = newp; 4101 coneNew[1] = splitp; 4102 ierr = DMPlexSetCone(sdm, cedge, coneNew);CHKERRQ(ierr); 4103 } else if (dep == dim-2) { 4104 /* Split old edge: old vertices in cone so no change */ 4105 /* Split new edge: new vertices in cone */ 4106 for (q = 0; q < coneSize; ++q) { 4107 ierr = PetscFindInt(cone[q], numSplitPoints[dim-3], splitPoints[dim-3], &v);CHKERRQ(ierr); 4108 4109 coneNew[q] = pMaxNew[dim-3] + v; 4110 } 4111 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 4112 /* Split old edge: Faces in positive side cells and old split faces */ 4113 for (e = 0, q = 0; e < supportSize; ++e) { 4114 PetscInt val; 4115 4116 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4117 if ((val == dim-1) || (val == (shift + dim-1))) { 4118 supportNew[q++] = depthOffset[dim-1] + support[e]; 4119 } 4120 } 4121 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 4122 /* Split new edge: Faces in negative side cells and new split faces */ 4123 for (e = 0, q = 0; e < supportSize; ++e) { 4124 PetscInt val, face; 4125 4126 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 4127 if (val == dim-1) { 4128 ierr = PetscFindInt(support[e], numSplitPoints[dim-1], splitPoints[dim-1], &face);CHKERRQ(ierr); 4129 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 4130 supportNew[q++] = pMaxNew[dim-1] + face; 4131 } else if (val == -(shift + dim-1)) { 4132 supportNew[q++] = depthOffset[dim-1] + support[e]; 4133 } 4134 } 4135 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 4136 } 4137 } 4138 } 4139 /* Step 6b: Replace split points in negative side cones */ 4140 for (sp = 0; sp < numSP; ++sp) { 4141 PetscInt dep = values[sp]; 4142 IS pIS; 4143 PetscInt numPoints; 4144 const PetscInt *points; 4145 4146 if (dep >= 0) continue; 4147 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 4148 if (!pIS) continue; 4149 dep = -dep - shift; 4150 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 4151 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 4152 for (p = 0; p < numPoints; ++p) { 4153 const PetscInt oldp = points[p]; 4154 const PetscInt newp = depthOffset[dep] + oldp; 4155 const PetscInt *cone; 4156 PetscInt coneSize, c; 4157 PetscBool replaced = PETSC_FALSE; 4158 4159 /* Negative edge: replace split vertex */ 4160 /* Negative cell: replace split face */ 4161 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 4162 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 4163 for (c = 0; c < coneSize; ++c) { 4164 const PetscInt coldp = cone[c] - depthOffset[dep-1]; 4165 PetscInt csplitp, cp, val; 4166 4167 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 4168 if (val == dep-1) { 4169 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 4170 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 4171 csplitp = pMaxNew[dep-1] + cp; 4172 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 4173 replaced = PETSC_TRUE; 4174 } 4175 } 4176 if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); 4177 } 4178 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 4179 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 4180 } 4181 /* Step 7: Stratify */ 4182 ierr = DMPlexStratify(sdm);CHKERRQ(ierr); 4183 /* Step 8: Coordinates */ 4184 ierr = DMPlexShiftCoordinates_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4185 ierr = DMPlexGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 4186 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 4187 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4188 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 4189 const PetscInt newp = depthOffset[0] + splitPoints[0][v]; 4190 const PetscInt splitp = pMaxNew[0] + v; 4191 PetscInt dof, off, soff, d; 4192 4193 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 4194 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 4195 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 4196 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 4197 } 4198 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4199 /* Step 9: SF, if I can figure this out we can split the mesh in parallel */ 4200 ierr = DMPlexShiftSF_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4201 /* Step 10: Labels */ 4202 ierr = DMPlexShiftLabels_Private(dm, depthShift, sdm);CHKERRQ(ierr); 4203 ierr = DMPlexGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 4204 for (dep = 0; dep <= depth; ++dep) { 4205 for (p = 0; p < numSplitPoints[dep]; ++p) { 4206 const PetscInt newp = depthOffset[dep] + splitPoints[dep][p]; 4207 const PetscInt splitp = pMaxNew[dep] + p; 4208 PetscInt l; 4209 4210 for (l = 0; l < numLabels; ++l) { 4211 DMLabel mlabel; 4212 const char *lname; 4213 PetscInt val; 4214 4215 ierr = DMPlexGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 4216 ierr = DMPlexGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 4217 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 4218 if (val >= 0) { 4219 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 4220 if (dep == 0) { 4221 const PetscInt cedge = pMaxNew[1] + (depthShift[1] - depthShift[0]) + p; 4222 ierr = DMLabelSetValue(mlabel, cedge, val);CHKERRQ(ierr); 4223 } 4224 } 4225 } 4226 } 4227 } 4228 for (sp = 0; sp < numSP; ++sp) { 4229 const PetscInt dep = values[sp]; 4230 4231 if ((dep < 0) || (dep > depth)) continue; 4232 if (pointIS[dep]) {ierr = ISRestoreIndices(pointIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 4233 ierr = ISDestroy(&pointIS[dep]);CHKERRQ(ierr); 4234 } 4235 if (label) { 4236 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4237 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4238 } 4239 ierr = PetscFree5(depthShift, depthOffset, pMaxNew, coneNew, supportNew);CHKERRQ(ierr); 4240 ierr = PetscFree3(pointIS, numSplitPoints, splitPoints);CHKERRQ(ierr); 4241 PetscFunctionReturn(0); 4242 } 4243 4244 #undef __FUNCT__ 4245 #define __FUNCT__ "DMPlexConstructCohesiveCells" 4246 /*@C 4247 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 4248 4249 Collective on dm 4250 4251 Input Parameters: 4252 + dm - The original DM 4253 - labelName - The label specifying the boundary faces (this could be auto-generated) 4254 4255 Output Parameters: 4256 - dmSplit - The new DM 4257 4258 Level: developer 4259 4260 .seealso: DMCreate() 4261 */ 4262 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit) 4263 { 4264 DM sdm; 4265 PetscInt dim; 4266 PetscErrorCode ierr; 4267 4268 PetscFunctionBegin; 4269 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4270 PetscValidPointer(dmSplit, 4); 4271 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &sdm);CHKERRQ(ierr); 4272 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 4273 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4274 ierr = DMPlexSetDimension(sdm, dim);CHKERRQ(ierr); 4275 switch (dim) { 4276 case 2: 4277 case 3: 4278 ierr = DMPlexConstructCohesiveCells_Private(dm, label, sdm);CHKERRQ(ierr); 4279 break; 4280 default: 4281 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 4282 } 4283 *dmSplit = sdm; 4284 PetscFunctionReturn(0); 4285 } 4286 4287 #undef __FUNCT__ 4288 #define __FUNCT__ "DMLabelCohesiveComplete" 4289 PetscErrorCode DMLabelCohesiveComplete(DM dm, DMLabel label) 4290 { 4291 IS dimIS; 4292 const PetscInt *points; 4293 PetscInt shift = 100, dim, dep, cStart, cEnd, numPoints, p, val; 4294 PetscErrorCode ierr; 4295 4296 PetscFunctionBegin; 4297 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4298 /* Cell orientation for face gives the side of the fault */ 4299 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 4300 if (!dimIS) PetscFunctionReturn(0); 4301 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4302 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4303 for (p = 0; p < numPoints; ++p) { 4304 const PetscInt *support; 4305 PetscInt supportSize, s; 4306 4307 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 4308 if (supportSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize); 4309 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 4310 for (s = 0; s < supportSize; ++s) { 4311 const PetscInt *cone, *ornt; 4312 PetscInt coneSize, c; 4313 PetscBool pos = PETSC_TRUE; 4314 4315 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 4316 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 4317 ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr); 4318 for (c = 0; c < coneSize; ++c) { 4319 if (cone[c] == points[p]) { 4320 if (ornt[c] >= 0) { 4321 ierr = DMLabelSetValue(label, support[s], shift+dim);CHKERRQ(ierr); 4322 } else { 4323 ierr = DMLabelSetValue(label, support[s], -(shift+dim));CHKERRQ(ierr); 4324 pos = PETSC_FALSE; 4325 } 4326 break; 4327 } 4328 } 4329 if (c == coneSize) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cell split face %d support does not have it in the cone", points[p]); 4330 /* Put faces touching the fault in the label */ 4331 for (c = 0; c < coneSize; ++c) { 4332 const PetscInt point = cone[c]; 4333 4334 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4335 if (val == -1) { 4336 PetscInt *closure = NULL; 4337 PetscInt closureSize, cl; 4338 4339 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4340 for (cl = 0; cl < closureSize*2; cl += 2) { 4341 const PetscInt clp = closure[cl]; 4342 4343 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 4344 if ((val >= 0) && (val < dim-1)) { 4345 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 4346 break; 4347 } 4348 } 4349 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4350 } 4351 } 4352 } 4353 } 4354 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4355 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4356 /* Search for other cells/faces/edges connected to the fault by a vertex */ 4357 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4358 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 4359 if (!dimIS) PetscFunctionReturn(0); 4360 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 4361 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 4362 for (p = 0; p < numPoints; ++p) { 4363 PetscInt *star = NULL; 4364 PetscInt starSize, s; 4365 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 4366 4367 /* First mark cells connected to the fault */ 4368 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4369 while (again) { 4370 if (again > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 4371 again = 0; 4372 for (s = 0; s < starSize*2; s += 2) { 4373 const PetscInt point = star[s]; 4374 const PetscInt *cone; 4375 PetscInt coneSize, c; 4376 4377 if ((point < cStart) || (point >= cEnd)) continue; 4378 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4379 if (val != -1) continue; 4380 again = 2; 4381 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 4382 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4383 for (c = 0; c < coneSize; ++c) { 4384 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 4385 if (val != -1) { 4386 if (abs(val) < shift) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Face %d on cell %d has an invalid label %d", cone[c], point, val); 4387 if (val > 0) { 4388 ierr = DMLabelSetValue(label, point, shift+dim);CHKERRQ(ierr); 4389 } else { 4390 ierr = DMLabelSetValue(label, point, -(shift+dim));CHKERRQ(ierr); 4391 } 4392 again = 1; 4393 break; 4394 } 4395 } 4396 } 4397 } 4398 /* Classify the rest by cell membership */ 4399 for (s = 0; s < starSize*2; s += 2) { 4400 const PetscInt point = star[s]; 4401 4402 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 4403 if (val == -1) { 4404 PetscInt *sstar = NULL; 4405 PetscInt sstarSize, ss; 4406 PetscBool marked = PETSC_FALSE; 4407 4408 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4409 for (ss = 0; ss < sstarSize*2; ss += 2) { 4410 const PetscInt spoint = sstar[ss]; 4411 4412 if ((spoint < cStart) || (spoint >= cEnd)) continue; 4413 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 4414 if (val == -1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 4415 ierr = DMPlexGetLabelValue(dm, "depth", point, &dep);CHKERRQ(ierr); 4416 if (val > 0) { 4417 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 4418 } else { 4419 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 4420 } 4421 marked = PETSC_TRUE; 4422 break; 4423 } 4424 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 4425 if (!marked) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d could not be classified", point); 4426 } 4427 } 4428 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 4429 } 4430 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 4431 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 4432 PetscFunctionReturn(0); 4433 } 4434 4435 #if defined(PETSC_HAVE_TRIANGLE) 4436 #include <triangle.h> 4437 4438 #undef __FUNCT__ 4439 #define __FUNCT__ "InitInput_Triangle" 4440 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 4441 { 4442 PetscFunctionBegin; 4443 inputCtx->numberofpoints = 0; 4444 inputCtx->numberofpointattributes = 0; 4445 inputCtx->pointlist = NULL; 4446 inputCtx->pointattributelist = NULL; 4447 inputCtx->pointmarkerlist = NULL; 4448 inputCtx->numberofsegments = 0; 4449 inputCtx->segmentlist = NULL; 4450 inputCtx->segmentmarkerlist = NULL; 4451 inputCtx->numberoftriangleattributes = 0; 4452 inputCtx->trianglelist = NULL; 4453 inputCtx->numberofholes = 0; 4454 inputCtx->holelist = NULL; 4455 inputCtx->numberofregions = 0; 4456 inputCtx->regionlist = NULL; 4457 PetscFunctionReturn(0); 4458 } 4459 4460 #undef __FUNCT__ 4461 #define __FUNCT__ "InitOutput_Triangle" 4462 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 4463 { 4464 PetscFunctionBegin; 4465 outputCtx->numberofpoints = 0; 4466 outputCtx->pointlist = NULL; 4467 outputCtx->pointattributelist = NULL; 4468 outputCtx->pointmarkerlist = NULL; 4469 outputCtx->numberoftriangles = 0; 4470 outputCtx->trianglelist = NULL; 4471 outputCtx->triangleattributelist = NULL; 4472 outputCtx->neighborlist = NULL; 4473 outputCtx->segmentlist = NULL; 4474 outputCtx->segmentmarkerlist = NULL; 4475 outputCtx->numberofedges = 0; 4476 outputCtx->edgelist = NULL; 4477 outputCtx->edgemarkerlist = NULL; 4478 PetscFunctionReturn(0); 4479 } 4480 4481 #undef __FUNCT__ 4482 #define __FUNCT__ "FiniOutput_Triangle" 4483 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 4484 { 4485 PetscFunctionBegin; 4486 free(outputCtx->pointmarkerlist); 4487 free(outputCtx->edgelist); 4488 free(outputCtx->edgemarkerlist); 4489 free(outputCtx->trianglelist); 4490 free(outputCtx->neighborlist); 4491 PetscFunctionReturn(0); 4492 } 4493 4494 #undef __FUNCT__ 4495 #define __FUNCT__ "DMPlexGenerate_Triangle" 4496 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4497 { 4498 MPI_Comm comm; 4499 PetscInt dim = 2; 4500 const PetscBool createConvexHull = PETSC_FALSE; 4501 const PetscBool constrained = PETSC_FALSE; 4502 struct triangulateio in; 4503 struct triangulateio out; 4504 PetscInt vStart, vEnd, v, eStart, eEnd, e; 4505 PetscMPIInt rank; 4506 PetscErrorCode ierr; 4507 4508 PetscFunctionBegin; 4509 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4510 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4511 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4512 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4513 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4514 4515 in.numberofpoints = vEnd - vStart; 4516 if (in.numberofpoints > 0) { 4517 PetscSection coordSection; 4518 Vec coordinates; 4519 PetscScalar *array; 4520 4521 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4522 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4523 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4524 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4525 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4526 for (v = vStart; v < vEnd; ++v) { 4527 const PetscInt idx = v - vStart; 4528 PetscInt off, d; 4529 4530 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4531 for (d = 0; d < dim; ++d) { 4532 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4533 } 4534 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4535 } 4536 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4537 } 4538 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4539 in.numberofsegments = eEnd - eStart; 4540 if (in.numberofsegments > 0) { 4541 ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4542 ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4543 for (e = eStart; e < eEnd; ++e) { 4544 const PetscInt idx = e - eStart; 4545 const PetscInt *cone; 4546 4547 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4548 4549 in.segmentlist[idx*2+0] = cone[0] - vStart; 4550 in.segmentlist[idx*2+1] = cone[1] - vStart; 4551 4552 ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4553 } 4554 } 4555 #if 0 /* Do not currently support holes */ 4556 PetscReal *holeCoords; 4557 PetscInt h, d; 4558 4559 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4560 if (in.numberofholes > 0) { 4561 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4562 for (h = 0; h < in.numberofholes; ++h) { 4563 for (d = 0; d < dim; ++d) { 4564 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4565 } 4566 } 4567 } 4568 #endif 4569 if (!rank) { 4570 char args[32]; 4571 4572 /* Take away 'Q' for verbose output */ 4573 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4574 if (createConvexHull) { 4575 ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4576 } 4577 if (constrained) { 4578 ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4579 } 4580 triangulate(args, &in, &out, NULL); 4581 } 4582 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4583 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4584 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4585 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4586 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4587 4588 { 4589 const PetscInt numCorners = 3; 4590 const PetscInt numCells = out.numberoftriangles; 4591 const PetscInt numVertices = out.numberofpoints; 4592 const int *cells = out.trianglelist; 4593 const double *meshCoords = out.pointlist; 4594 4595 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 4596 /* Set labels */ 4597 for (v = 0; v < numVertices; ++v) { 4598 if (out.pointmarkerlist[v]) { 4599 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4600 } 4601 } 4602 if (interpolate) { 4603 for (e = 0; e < out.numberofedges; e++) { 4604 if (out.edgemarkerlist[e]) { 4605 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4606 const PetscInt *edges; 4607 PetscInt numEdges; 4608 4609 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4610 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4611 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4612 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4613 } 4614 } 4615 } 4616 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4617 } 4618 #if 0 /* Do not currently support holes */ 4619 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4620 #endif 4621 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4622 PetscFunctionReturn(0); 4623 } 4624 4625 #undef __FUNCT__ 4626 #define __FUNCT__ "DMPlexRefine_Triangle" 4627 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4628 { 4629 MPI_Comm comm; 4630 PetscInt dim = 2; 4631 struct triangulateio in; 4632 struct triangulateio out; 4633 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4634 PetscMPIInt rank; 4635 PetscErrorCode ierr; 4636 4637 PetscFunctionBegin; 4638 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4639 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4640 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4641 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4642 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4643 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4644 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4645 4646 in.numberofpoints = vEnd - vStart; 4647 if (in.numberofpoints > 0) { 4648 PetscSection coordSection; 4649 Vec coordinates; 4650 PetscScalar *array; 4651 4652 ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4653 ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4654 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4655 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4656 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4657 for (v = vStart; v < vEnd; ++v) { 4658 const PetscInt idx = v - vStart; 4659 PetscInt off, d; 4660 4661 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4662 for (d = 0; d < dim; ++d) { 4663 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4664 } 4665 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4666 } 4667 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4668 } 4669 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4670 4671 in.numberofcorners = 3; 4672 in.numberoftriangles = cEnd - cStart; 4673 4674 in.trianglearealist = (double*) maxVolumes; 4675 if (in.numberoftriangles > 0) { 4676 ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4677 for (c = cStart; c < cEnd; ++c) { 4678 const PetscInt idx = c - cStart; 4679 PetscInt *closure = NULL; 4680 PetscInt closureSize; 4681 4682 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4683 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4684 for (v = 0; v < 3; ++v) { 4685 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4686 } 4687 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4688 } 4689 } 4690 /* TODO: Segment markers are missing on input */ 4691 #if 0 /* Do not currently support holes */ 4692 PetscReal *holeCoords; 4693 PetscInt h, d; 4694 4695 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4696 if (in.numberofholes > 0) { 4697 ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4698 for (h = 0; h < in.numberofholes; ++h) { 4699 for (d = 0; d < dim; ++d) { 4700 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4701 } 4702 } 4703 } 4704 #endif 4705 if (!rank) { 4706 char args[32]; 4707 4708 /* Take away 'Q' for verbose output */ 4709 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4710 triangulate(args, &in, &out, NULL); 4711 } 4712 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4713 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4714 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4715 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4716 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4717 4718 { 4719 const PetscInt numCorners = 3; 4720 const PetscInt numCells = out.numberoftriangles; 4721 const PetscInt numVertices = out.numberofpoints; 4722 const int *cells = out.trianglelist; 4723 const double *meshCoords = out.pointlist; 4724 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4725 4726 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 4727 /* Set labels */ 4728 for (v = 0; v < numVertices; ++v) { 4729 if (out.pointmarkerlist[v]) { 4730 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4731 } 4732 } 4733 if (interpolate) { 4734 PetscInt e; 4735 4736 for (e = 0; e < out.numberofedges; e++) { 4737 if (out.edgemarkerlist[e]) { 4738 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4739 const PetscInt *edges; 4740 PetscInt numEdges; 4741 4742 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4743 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4744 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4745 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4746 } 4747 } 4748 } 4749 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4750 } 4751 #if 0 /* Do not currently support holes */ 4752 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4753 #endif 4754 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4755 PetscFunctionReturn(0); 4756 } 4757 #endif 4758 4759 #if defined(PETSC_HAVE_TETGEN) 4760 #include <tetgen.h> 4761 #undef __FUNCT__ 4762 #define __FUNCT__ "DMPlexGenerate_Tetgen" 4763 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4764 { 4765 MPI_Comm comm; 4766 const PetscInt dim = 3; 4767 ::tetgenio in; 4768 ::tetgenio out; 4769 PetscInt vStart, vEnd, v, fStart, fEnd, f; 4770 PetscMPIInt rank; 4771 PetscErrorCode ierr; 4772 4773 PetscFunctionBegin; 4774 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 4775 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4776 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4777 in.numberofpoints = vEnd - vStart; 4778 if (in.numberofpoints > 0) { 4779 PetscSection coordSection; 4780 Vec coordinates; 4781 PetscScalar *array; 4782 4783 in.pointlist = new double[in.numberofpoints*dim]; 4784 in.pointmarkerlist = new int[in.numberofpoints]; 4785 4786 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4787 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4788 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4789 for (v = vStart; v < vEnd; ++v) { 4790 const PetscInt idx = v - vStart; 4791 PetscInt off, d; 4792 4793 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4794 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 4795 ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4796 } 4797 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4798 } 4799 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4800 4801 in.numberoffacets = fEnd - fStart; 4802 if (in.numberoffacets > 0) { 4803 in.facetlist = new tetgenio::facet[in.numberoffacets]; 4804 in.facetmarkerlist = new int[in.numberoffacets]; 4805 for (f = fStart; f < fEnd; ++f) { 4806 const PetscInt idx = f - fStart; 4807 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 4808 4809 in.facetlist[idx].numberofpolygons = 1; 4810 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4811 in.facetlist[idx].numberofholes = 0; 4812 in.facetlist[idx].holelist = NULL; 4813 4814 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4815 for (p = 0; p < numPoints*2; p += 2) { 4816 const PetscInt point = points[p]; 4817 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 4818 } 4819 4820 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4821 poly->numberofvertices = numVertices; 4822 poly->vertexlist = new int[poly->numberofvertices]; 4823 for (v = 0; v < numVertices; ++v) { 4824 const PetscInt vIdx = points[v] - vStart; 4825 poly->vertexlist[v] = vIdx; 4826 } 4827 ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4828 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4829 } 4830 } 4831 if (!rank) { 4832 char args[32]; 4833 4834 /* Take away 'Q' for verbose output */ 4835 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4836 ::tetrahedralize(args, &in, &out); 4837 } 4838 { 4839 const PetscInt numCorners = 4; 4840 const PetscInt numCells = out.numberoftetrahedra; 4841 const PetscInt numVertices = out.numberofpoints; 4842 const int *cells = out.tetrahedronlist; 4843 const double *meshCoords = out.pointlist; 4844 4845 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 4846 /* Set labels */ 4847 for (v = 0; v < numVertices; ++v) { 4848 if (out.pointmarkerlist[v]) { 4849 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4850 } 4851 } 4852 if (interpolate) { 4853 PetscInt e; 4854 4855 for (e = 0; e < out.numberofedges; e++) { 4856 if (out.edgemarkerlist[e]) { 4857 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4858 const PetscInt *edges; 4859 PetscInt numEdges; 4860 4861 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4862 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4863 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4864 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4865 } 4866 } 4867 for (f = 0; f < out.numberoftrifaces; f++) { 4868 if (out.trifacemarkerlist[f]) { 4869 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4870 const PetscInt *faces; 4871 PetscInt numFaces; 4872 4873 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4874 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4875 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4876 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4877 } 4878 } 4879 } 4880 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4881 } 4882 PetscFunctionReturn(0); 4883 } 4884 4885 #undef __FUNCT__ 4886 #define __FUNCT__ "DMPlexRefine_Tetgen" 4887 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4888 { 4889 MPI_Comm comm; 4890 const PetscInt dim = 3; 4891 ::tetgenio in; 4892 ::tetgenio out; 4893 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4894 PetscMPIInt rank; 4895 PetscErrorCode ierr; 4896 4897 PetscFunctionBegin; 4898 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4899 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4900 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4901 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4902 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4903 4904 in.numberofpoints = vEnd - vStart; 4905 if (in.numberofpoints > 0) { 4906 PetscSection coordSection; 4907 Vec coordinates; 4908 PetscScalar *array; 4909 4910 in.pointlist = new double[in.numberofpoints*dim]; 4911 in.pointmarkerlist = new int[in.numberofpoints]; 4912 4913 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4914 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4915 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4916 for (v = vStart; v < vEnd; ++v) { 4917 const PetscInt idx = v - vStart; 4918 PetscInt off, d; 4919 4920 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4921 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d]; 4922 ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4923 } 4924 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4925 } 4926 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4927 4928 in.numberofcorners = 4; 4929 in.numberoftetrahedra = cEnd - cStart; 4930 in.tetrahedronvolumelist = (double*) maxVolumes; 4931 if (in.numberoftetrahedra > 0) { 4932 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 4933 for (c = cStart; c < cEnd; ++c) { 4934 const PetscInt idx = c - cStart; 4935 PetscInt *closure = NULL; 4936 PetscInt closureSize; 4937 4938 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4939 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 4940 for (v = 0; v < 4; ++v) { 4941 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 4942 } 4943 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4944 } 4945 } 4946 /* TODO: Put in boundary faces with markers */ 4947 if (!rank) { 4948 char args[32]; 4949 4950 /* Take away 'Q' for verbose output */ 4951 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 4952 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 4953 ::tetrahedralize(args, &in, &out); 4954 } 4955 in.tetrahedronvolumelist = NULL; 4956 4957 { 4958 const PetscInt numCorners = 4; 4959 const PetscInt numCells = out.numberoftetrahedra; 4960 const PetscInt numVertices = out.numberofpoints; 4961 const int *cells = out.tetrahedronlist; 4962 const double *meshCoords = out.pointlist; 4963 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4964 4965 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 4966 /* Set labels */ 4967 for (v = 0; v < numVertices; ++v) { 4968 if (out.pointmarkerlist[v]) { 4969 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4970 } 4971 } 4972 if (interpolate) { 4973 PetscInt e, f; 4974 4975 for (e = 0; e < out.numberofedges; e++) { 4976 if (out.edgemarkerlist[e]) { 4977 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4978 const PetscInt *edges; 4979 PetscInt numEdges; 4980 4981 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4982 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4983 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4984 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4985 } 4986 } 4987 for (f = 0; f < out.numberoftrifaces; f++) { 4988 if (out.trifacemarkerlist[f]) { 4989 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4990 const PetscInt *faces; 4991 PetscInt numFaces; 4992 4993 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4994 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4995 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4996 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4997 } 4998 } 4999 } 5000 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5001 } 5002 PetscFunctionReturn(0); 5003 } 5004 #endif 5005 5006 #if defined(PETSC_HAVE_CTETGEN) 5007 #include "ctetgen.h" 5008 5009 #undef __FUNCT__ 5010 #define __FUNCT__ "DMPlexGenerate_CTetgen" 5011 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 5012 { 5013 MPI_Comm comm; 5014 const PetscInt dim = 3; 5015 PLC *in, *out; 5016 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 5017 PetscMPIInt rank; 5018 PetscErrorCode ierr; 5019 5020 PetscFunctionBegin; 5021 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 5022 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5023 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5024 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 5025 ierr = PLCCreate(&in);CHKERRQ(ierr); 5026 ierr = PLCCreate(&out);CHKERRQ(ierr); 5027 5028 in->numberofpoints = vEnd - vStart; 5029 if (in->numberofpoints > 0) { 5030 PetscSection coordSection; 5031 Vec coordinates; 5032 PetscScalar *array; 5033 5034 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5035 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5036 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 5037 ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 5038 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5039 for (v = vStart; v < vEnd; ++v) { 5040 const PetscInt idx = v - vStart; 5041 PetscInt off, d, m; 5042 5043 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5044 for (d = 0; d < dim; ++d) { 5045 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5046 } 5047 ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 5048 5049 in->pointmarkerlist[idx] = (int) m; 5050 } 5051 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5052 } 5053 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 5054 5055 in->numberoffacets = fEnd - fStart; 5056 if (in->numberoffacets > 0) { 5057 ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 5058 ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 5059 for (f = fStart; f < fEnd; ++f) { 5060 const PetscInt idx = f - fStart; 5061 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m; 5062 polygon *poly; 5063 5064 in->facetlist[idx].numberofpolygons = 1; 5065 5066 ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 5067 5068 in->facetlist[idx].numberofholes = 0; 5069 in->facetlist[idx].holelist = NULL; 5070 5071 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5072 for (p = 0; p < numPoints*2; p += 2) { 5073 const PetscInt point = points[p]; 5074 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 5075 } 5076 5077 poly = in->facetlist[idx].polygonlist; 5078 poly->numberofvertices = numVertices; 5079 ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 5080 for (v = 0; v < numVertices; ++v) { 5081 const PetscInt vIdx = points[v] - vStart; 5082 poly->vertexlist[v] = vIdx; 5083 } 5084 ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 5085 in->facetmarkerlist[idx] = (int) m; 5086 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 5087 } 5088 } 5089 if (!rank) { 5090 TetGenOpts t; 5091 5092 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5093 t.in = boundary; /* Should go away */ 5094 t.plc = 1; 5095 t.quality = 1; 5096 t.edgesout = 1; 5097 t.zeroindex = 1; 5098 t.quiet = 1; 5099 t.verbose = verbose; 5100 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5101 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5102 } 5103 { 5104 const PetscInt numCorners = 4; 5105 const PetscInt numCells = out->numberoftetrahedra; 5106 const PetscInt numVertices = out->numberofpoints; 5107 const int *cells = out->tetrahedronlist; 5108 const double *meshCoords = out->pointlist; 5109 5110 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 5111 /* Set labels */ 5112 for (v = 0; v < numVertices; ++v) { 5113 if (out->pointmarkerlist[v]) { 5114 ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5115 } 5116 } 5117 if (interpolate) { 5118 PetscInt e; 5119 5120 for (e = 0; e < out->numberofedges; e++) { 5121 if (out->edgemarkerlist[e]) { 5122 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5123 const PetscInt *edges; 5124 PetscInt numEdges; 5125 5126 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5127 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5128 ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5129 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5130 } 5131 } 5132 for (f = 0; f < out->numberoftrifaces; f++) { 5133 if (out->trifacemarkerlist[f]) { 5134 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5135 const PetscInt *faces; 5136 PetscInt numFaces; 5137 5138 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5139 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5140 ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5141 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5142 } 5143 } 5144 } 5145 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5146 } 5147 5148 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5149 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5150 PetscFunctionReturn(0); 5151 } 5152 5153 #undef __FUNCT__ 5154 #define __FUNCT__ "DMPlexRefine_CTetgen" 5155 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5156 { 5157 MPI_Comm comm; 5158 const PetscInt dim = 3; 5159 PLC *in, *out; 5160 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5161 PetscMPIInt rank; 5162 PetscErrorCode ierr; 5163 5164 PetscFunctionBegin; 5165 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 5166 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 5167 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5168 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5169 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5170 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5171 ierr = PLCCreate(&in);CHKERRQ(ierr); 5172 ierr = PLCCreate(&out);CHKERRQ(ierr); 5173 5174 in->numberofpoints = vEnd - vStart; 5175 if (in->numberofpoints > 0) { 5176 PetscSection coordSection; 5177 Vec coordinates; 5178 PetscScalar *array; 5179 5180 ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5181 ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5182 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5183 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5184 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5185 for (v = vStart; v < vEnd; ++v) { 5186 const PetscInt idx = v - vStart; 5187 PetscInt off, d, m; 5188 5189 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5190 for (d = 0; d < dim; ++d) { 5191 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5192 } 5193 ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5194 5195 in->pointmarkerlist[idx] = (int) m; 5196 } 5197 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5198 } 5199 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5200 5201 in->numberofcorners = 4; 5202 in->numberoftetrahedra = cEnd - cStart; 5203 in->tetrahedronvolumelist = maxVolumes; 5204 if (in->numberoftetrahedra > 0) { 5205 ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5206 for (c = cStart; c < cEnd; ++c) { 5207 const PetscInt idx = c - cStart; 5208 PetscInt *closure = NULL; 5209 PetscInt closureSize; 5210 5211 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5212 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5213 for (v = 0; v < 4; ++v) { 5214 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5215 } 5216 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5217 } 5218 } 5219 if (!rank) { 5220 TetGenOpts t; 5221 5222 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5223 5224 t.in = dm; /* Should go away */ 5225 t.refine = 1; 5226 t.varvolume = 1; 5227 t.quality = 1; 5228 t.edgesout = 1; 5229 t.zeroindex = 1; 5230 t.quiet = 1; 5231 t.verbose = verbose; /* Change this */ 5232 5233 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5234 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5235 } 5236 { 5237 const PetscInt numCorners = 4; 5238 const PetscInt numCells = out->numberoftetrahedra; 5239 const PetscInt numVertices = out->numberofpoints; 5240 const int *cells = out->tetrahedronlist; 5241 const double *meshCoords = out->pointlist; 5242 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5243 5244 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 5245 /* Set labels */ 5246 for (v = 0; v < numVertices; ++v) { 5247 if (out->pointmarkerlist[v]) { 5248 ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5249 } 5250 } 5251 if (interpolate) { 5252 PetscInt e, f; 5253 5254 for (e = 0; e < out->numberofedges; e++) { 5255 if (out->edgemarkerlist[e]) { 5256 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5257 const PetscInt *edges; 5258 PetscInt numEdges; 5259 5260 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5261 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5262 ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5263 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5264 } 5265 } 5266 for (f = 0; f < out->numberoftrifaces; f++) { 5267 if (out->trifacemarkerlist[f]) { 5268 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5269 const PetscInt *faces; 5270 PetscInt numFaces; 5271 5272 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5273 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5274 ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5275 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5276 } 5277 } 5278 } 5279 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5280 } 5281 ierr = PLCDestroy(&in);CHKERRQ(ierr); 5282 ierr = PLCDestroy(&out);CHKERRQ(ierr); 5283 PetscFunctionReturn(0); 5284 } 5285 #endif 5286 5287 #undef __FUNCT__ 5288 #define __FUNCT__ "DMPlexGenerate" 5289 /*@C 5290 DMPlexGenerate - Generates a mesh. 5291 5292 Not Collective 5293 5294 Input Parameters: 5295 + boundary - The DMPlex boundary object 5296 . name - The mesh generation package name 5297 - interpolate - Flag to create intermediate mesh elements 5298 5299 Output Parameter: 5300 . mesh - The DMPlex object 5301 5302 Level: intermediate 5303 5304 .keywords: mesh, elements 5305 .seealso: DMPlexCreate(), DMRefine() 5306 @*/ 5307 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5308 { 5309 PetscInt dim; 5310 char genname[1024]; 5311 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5312 PetscErrorCode ierr; 5313 5314 PetscFunctionBegin; 5315 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5316 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5317 ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5318 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5319 if (flg) name = genname; 5320 if (name) { 5321 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5322 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5323 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5324 } 5325 switch (dim) { 5326 case 1: 5327 if (!name || isTriangle) { 5328 #if defined(PETSC_HAVE_TRIANGLE) 5329 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5330 #else 5331 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5332 #endif 5333 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5334 break; 5335 case 2: 5336 if (!name || isCTetgen) { 5337 #if defined(PETSC_HAVE_CTETGEN) 5338 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5339 #else 5340 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5341 #endif 5342 } else if (isTetgen) { 5343 #if defined(PETSC_HAVE_TETGEN) 5344 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5345 #else 5346 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5347 #endif 5348 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5349 break; 5350 default: 5351 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5352 } 5353 PetscFunctionReturn(0); 5354 } 5355 5356 typedef PetscInt CellRefiner; 5357 5358 #undef __FUNCT__ 5359 #define __FUNCT__ "GetDepthStart_Private" 5360 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5361 { 5362 PetscFunctionBegin; 5363 if (cStart) *cStart = 0; 5364 if (vStart) *vStart = depthSize[depth]; 5365 if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5366 if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5367 PetscFunctionReturn(0); 5368 } 5369 5370 #undef __FUNCT__ 5371 #define __FUNCT__ "GetDepthEnd_Private" 5372 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5373 { 5374 PetscFunctionBegin; 5375 if (cEnd) *cEnd = depthSize[depth]; 5376 if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5377 if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5378 if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5379 PetscFunctionReturn(0); 5380 } 5381 5382 #undef __FUNCT__ 5383 #define __FUNCT__ "CellRefinerGetSizes" 5384 PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5385 { 5386 PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax; 5387 PetscErrorCode ierr; 5388 5389 PetscFunctionBegin; 5390 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5391 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5392 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5393 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5394 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5395 switch (refiner) { 5396 case 1: 5397 /* Simplicial 2D */ 5398 depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5399 depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5400 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5401 break; 5402 case 3: 5403 /* Hybrid 2D */ 5404 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5405 cMax = PetscMin(cEnd, cMax); 5406 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5407 fMax = PetscMin(fEnd, fMax); 5408 depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */ 5409 depthSize[1] = 2*(fMax - fStart) + 3*(cMax - cStart) + (fEnd - fMax) + (cEnd - cMax); /* Every interior face is split into 2 faces, 3 faces are added for each interior cell, and one in each hybrid cell */ 5410 depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */ 5411 break; 5412 case 2: 5413 /* Hex 2D */ 5414 depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5415 depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5416 depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5417 break; 5418 default: 5419 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5420 } 5421 PetscFunctionReturn(0); 5422 } 5423 5424 #undef __FUNCT__ 5425 #define __FUNCT__ "CellRefinerSetConeSizes" 5426 PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5427 { 5428 PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r; 5429 PetscErrorCode ierr; 5430 5431 PetscFunctionBegin; 5432 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5433 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5434 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5435 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5436 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5437 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5438 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5439 switch (refiner) { 5440 case 1: 5441 /* Simplicial 2D */ 5442 /* All cells have 3 faces */ 5443 for (c = cStart; c < cEnd; ++c) { 5444 for (r = 0; r < 4; ++r) { 5445 const PetscInt newp = (c - cStart)*4 + r; 5446 5447 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5448 } 5449 } 5450 /* Split faces have 2 vertices and the same cells as the parent */ 5451 for (f = fStart; f < fEnd; ++f) { 5452 for (r = 0; r < 2; ++r) { 5453 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5454 PetscInt size; 5455 5456 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5457 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5458 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5459 } 5460 } 5461 /* Interior faces have 2 vertices and 2 cells */ 5462 for (c = cStart; c < cEnd; ++c) { 5463 for (r = 0; r < 3; ++r) { 5464 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5465 5466 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5467 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5468 } 5469 } 5470 /* Old vertices have identical supports */ 5471 for (v = vStart; v < vEnd; ++v) { 5472 const PetscInt newp = vStartNew + (v - vStart); 5473 PetscInt size; 5474 5475 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5476 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5477 } 5478 /* Face vertices have 2 + cells*2 supports */ 5479 for (f = fStart; f < fEnd; ++f) { 5480 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5481 PetscInt size; 5482 5483 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5484 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5485 } 5486 break; 5487 case 2: 5488 /* Hex 2D */ 5489 /* All cells have 4 faces */ 5490 for (c = cStart; c < cEnd; ++c) { 5491 for (r = 0; r < 4; ++r) { 5492 const PetscInt newp = (c - cStart)*4 + r; 5493 5494 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5495 } 5496 } 5497 /* Split faces have 2 vertices and the same cells as the parent */ 5498 for (f = fStart; f < fEnd; ++f) { 5499 for (r = 0; r < 2; ++r) { 5500 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5501 PetscInt size; 5502 5503 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5504 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5505 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5506 } 5507 } 5508 /* Interior faces have 2 vertices and 2 cells */ 5509 for (c = cStart; c < cEnd; ++c) { 5510 for (r = 0; r < 4; ++r) { 5511 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5512 5513 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5514 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5515 } 5516 } 5517 /* Old vertices have identical supports */ 5518 for (v = vStart; v < vEnd; ++v) { 5519 const PetscInt newp = vStartNew + (v - vStart); 5520 PetscInt size; 5521 5522 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5523 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5524 } 5525 /* Face vertices have 2 + cells supports */ 5526 for (f = fStart; f < fEnd; ++f) { 5527 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5528 PetscInt size; 5529 5530 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5531 ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5532 } 5533 /* Cell vertices have 4 supports */ 5534 for (c = cStart; c < cEnd; ++c) { 5535 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5536 5537 ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5538 } 5539 break; 5540 case 3: 5541 /* Hybrid 2D */ 5542 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 5543 cMax = PetscMin(cEnd, cMax); 5544 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 5545 fMax = PetscMin(fEnd, fMax); 5546 ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5547 /* Interior cells have 3 faces */ 5548 for (c = cStart; c < cMax; ++c) { 5549 for (r = 0; r < 4; ++r) { 5550 const PetscInt newp = cStartNew + (c - cStart)*4 + r; 5551 5552 ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5553 } 5554 } 5555 /* Hybrid cells have 4 faces */ 5556 for (c = cMax; c < cEnd; ++c) { 5557 for (r = 0; r < 2; ++r) { 5558 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r; 5559 5560 ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5561 } 5562 } 5563 /* Interior split faces have 2 vertices and the same cells as the parent */ 5564 for (f = fStart; f < fMax; ++f) { 5565 for (r = 0; r < 2; ++r) { 5566 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5567 PetscInt size; 5568 5569 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5570 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5571 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5572 } 5573 } 5574 /* Interior cell faces have 2 vertices and 2 cells */ 5575 for (c = cStart; c < cMax; ++c) { 5576 for (r = 0; r < 3; ++r) { 5577 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 5578 5579 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5580 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5581 } 5582 } 5583 /* Hybrid faces have 2 vertices and the same cells */ 5584 for (f = fMax; f < fEnd; ++f) { 5585 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 5586 PetscInt size; 5587 5588 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5589 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5590 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5591 } 5592 /* Hybrid cell faces have 2 vertices and 2 cells */ 5593 for (c = cMax; c < cEnd; ++c) { 5594 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 5595 5596 ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5597 ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5598 } 5599 /* Old vertices have identical supports */ 5600 for (v = vStart; v < vEnd; ++v) { 5601 const PetscInt newp = vStartNew + (v - vStart); 5602 PetscInt size; 5603 5604 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5605 ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5606 } 5607 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 5608 for (f = fStart; f < fMax; ++f) { 5609 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5610 const PetscInt *support; 5611 PetscInt size, newSize = 2, s; 5612 5613 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5614 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5615 for (s = 0; s < size; ++s) { 5616 if (support[s] >= cMax) newSize += 1; 5617 else newSize += 2; 5618 } 5619 ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr); 5620 } 5621 break; 5622 default: 5623 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5624 } 5625 PetscFunctionReturn(0); 5626 } 5627 5628 #undef __FUNCT__ 5629 #define __FUNCT__ "CellRefinerSetCones" 5630 PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5631 { 5632 PetscInt depth, cStart, cEnd, cMax, cStartNew, cEndNew, c, vStart, vEnd, vMax, vStartNew, vEndNew, v, fStart, fEnd, fMax, fStartNew, fEndNew, f, eStart, eEnd, eMax, eStartNew, eEndNew, r, p; 5633 PetscInt maxSupportSize, *supportRef; 5634 PetscErrorCode ierr; 5635 5636 PetscFunctionBegin; 5637 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5638 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5639 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5640 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5641 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5642 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 5643 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5644 ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5645 switch (refiner) { 5646 case 1: 5647 /* Simplicial 2D */ 5648 /* 5649 2 5650 |\ 5651 | \ 5652 | \ 5653 | \ 5654 | C \ 5655 | \ 5656 | \ 5657 2---1---1 5658 |\ D / \ 5659 | 2 0 \ 5660 |A \ / B \ 5661 0---0-------1 5662 */ 5663 /* All cells have 3 faces */ 5664 for (c = cStart; c < cEnd; ++c) { 5665 const PetscInt newp = cStartNew + (c - cStart)*4; 5666 const PetscInt *cone, *ornt; 5667 PetscInt coneNew[3], orntNew[3]; 5668 5669 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5670 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5671 /* A triangle */ 5672 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5673 orntNew[0] = ornt[0]; 5674 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5675 orntNew[1] = -2; 5676 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5677 orntNew[2] = ornt[2]; 5678 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5679 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5680 #if 1 5681 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 5682 for (p = 0; p < 3; ++p) { 5683 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5684 } 5685 #endif 5686 /* B triangle */ 5687 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5688 orntNew[0] = ornt[0]; 5689 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5690 orntNew[1] = ornt[1]; 5691 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5692 orntNew[2] = -2; 5693 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5694 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5695 #if 1 5696 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 5697 for (p = 0; p < 3; ++p) { 5698 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5699 } 5700 #endif 5701 /* C triangle */ 5702 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5703 orntNew[0] = -2; 5704 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5705 orntNew[1] = ornt[1]; 5706 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5707 orntNew[2] = ornt[2]; 5708 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5709 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5710 #if 1 5711 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 5712 for (p = 0; p < 3; ++p) { 5713 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5714 } 5715 #endif 5716 /* D triangle */ 5717 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5718 orntNew[0] = 0; 5719 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5720 orntNew[1] = 0; 5721 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5722 orntNew[2] = 0; 5723 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5724 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5725 #if 1 5726 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 5727 for (p = 0; p < 3; ++p) { 5728 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5729 } 5730 #endif 5731 } 5732 /* Split faces have 2 vertices and the same cells as the parent */ 5733 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 5734 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5735 for (f = fStart; f < fEnd; ++f) { 5736 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5737 5738 for (r = 0; r < 2; ++r) { 5739 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5740 const PetscInt *cone, *support; 5741 PetscInt coneNew[2], coneSize, c, supportSize, s; 5742 5743 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5744 coneNew[0] = vStartNew + (cone[0] - vStart); 5745 coneNew[1] = vStartNew + (cone[1] - vStart); 5746 coneNew[(r+1)%2] = newv; 5747 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5748 #if 1 5749 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5750 for (p = 0; p < 2; ++p) { 5751 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5752 } 5753 #endif 5754 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5755 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5756 for (s = 0; s < supportSize; ++s) { 5757 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5758 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5759 for (c = 0; c < coneSize; ++c) { 5760 if (cone[c] == f) break; 5761 } 5762 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5763 } 5764 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5765 #if 1 5766 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5767 for (p = 0; p < supportSize; ++p) { 5768 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 5769 } 5770 #endif 5771 } 5772 } 5773 /* Interior faces have 2 vertices and 2 cells */ 5774 for (c = cStart; c < cEnd; ++c) { 5775 const PetscInt *cone; 5776 5777 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5778 for (r = 0; r < 3; ++r) { 5779 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5780 PetscInt coneNew[2]; 5781 PetscInt supportNew[2]; 5782 5783 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5784 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5785 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5786 #if 1 5787 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5788 for (p = 0; p < 2; ++p) { 5789 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5790 } 5791 #endif 5792 supportNew[0] = (c - cStart)*4 + (r+1)%3; 5793 supportNew[1] = (c - cStart)*4 + 3; 5794 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5795 #if 1 5796 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5797 for (p = 0; p < 2; ++p) { 5798 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 5799 } 5800 #endif 5801 } 5802 } 5803 /* Old vertices have identical supports */ 5804 for (v = vStart; v < vEnd; ++v) { 5805 const PetscInt newp = vStartNew + (v - vStart); 5806 const PetscInt *support, *cone; 5807 PetscInt size, s; 5808 5809 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5810 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5811 for (s = 0; s < size; ++s) { 5812 PetscInt r = 0; 5813 5814 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5815 if (cone[1] == v) r = 1; 5816 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5817 } 5818 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5819 #if 1 5820 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5821 for (p = 0; p < size; ++p) { 5822 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5823 } 5824 #endif 5825 } 5826 /* Face vertices have 2 + cells*2 supports */ 5827 for (f = fStart; f < fEnd; ++f) { 5828 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5829 const PetscInt *cone, *support; 5830 PetscInt size, s; 5831 5832 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5833 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5834 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5835 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5836 for (s = 0; s < size; ++s) { 5837 PetscInt r = 0; 5838 5839 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5840 if (cone[1] == f) r = 1; 5841 else if (cone[2] == f) r = 2; 5842 supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5843 supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5844 } 5845 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5846 #if 1 5847 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5848 for (p = 0; p < 2+size*2; ++p) { 5849 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5850 } 5851 #endif 5852 } 5853 ierr = PetscFree(supportRef);CHKERRQ(ierr); 5854 break; 5855 case 2: 5856 /* Hex 2D */ 5857 /* 5858 3---------2---------2 5859 | | | 5860 | D 2 C | 5861 | | | 5862 3----3----0----1----1 5863 | | | 5864 | A 0 B | 5865 | | | 5866 0---------0---------1 5867 */ 5868 /* All cells have 4 faces */ 5869 for (c = cStart; c < cEnd; ++c) { 5870 const PetscInt newp = (c - cStart)*4; 5871 const PetscInt *cone, *ornt; 5872 PetscInt coneNew[4], orntNew[4]; 5873 5874 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5875 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5876 /* A quad */ 5877 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5878 orntNew[0] = ornt[0]; 5879 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5880 orntNew[1] = 0; 5881 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5882 orntNew[2] = -2; 5883 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5884 orntNew[3] = ornt[3]; 5885 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5886 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5887 #if 1 5888 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 5889 for (p = 0; p < 4; ++p) { 5890 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5891 } 5892 #endif 5893 /* B quad */ 5894 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5895 orntNew[0] = ornt[0]; 5896 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5897 orntNew[1] = ornt[1]; 5898 coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5899 orntNew[2] = 0; 5900 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5901 orntNew[3] = -2; 5902 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5903 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5904 #if 1 5905 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 5906 for (p = 0; p < 4; ++p) { 5907 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5908 } 5909 #endif 5910 /* C quad */ 5911 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5912 orntNew[0] = -2; 5913 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5914 orntNew[1] = ornt[1]; 5915 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5916 orntNew[2] = ornt[2]; 5917 coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5918 orntNew[3] = 0; 5919 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5920 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5921 #if 1 5922 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 5923 for (p = 0; p < 4; ++p) { 5924 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5925 } 5926 #endif 5927 /* D quad */ 5928 coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5929 orntNew[0] = 0; 5930 coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5931 orntNew[1] = -2; 5932 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5933 orntNew[2] = ornt[2]; 5934 coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 5935 orntNew[3] = ornt[3]; 5936 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5937 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5938 #if 1 5939 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 5940 for (p = 0; p < 4; ++p) { 5941 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5942 } 5943 #endif 5944 } 5945 /* Split faces have 2 vertices and the same cells as the parent */ 5946 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 5947 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5948 for (f = fStart; f < fEnd; ++f) { 5949 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5950 5951 for (r = 0; r < 2; ++r) { 5952 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5953 const PetscInt *cone, *support; 5954 PetscInt coneNew[2], coneSize, c, supportSize, s; 5955 5956 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5957 coneNew[0] = vStartNew + (cone[0] - vStart); 5958 coneNew[1] = vStartNew + (cone[1] - vStart); 5959 coneNew[(r+1)%2] = newv; 5960 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5961 #if 1 5962 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5963 for (p = 0; p < 2; ++p) { 5964 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5965 } 5966 #endif 5967 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5968 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5969 for (s = 0; s < supportSize; ++s) { 5970 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5971 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5972 for (c = 0; c < coneSize; ++c) { 5973 if (cone[c] == f) break; 5974 } 5975 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 5976 } 5977 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5978 #if 1 5979 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5980 for (p = 0; p < supportSize; ++p) { 5981 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 5982 } 5983 #endif 5984 } 5985 } 5986 /* Interior faces have 2 vertices and 2 cells */ 5987 for (c = cStart; c < cEnd; ++c) { 5988 const PetscInt *cone; 5989 PetscInt coneNew[2], supportNew[2]; 5990 5991 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5992 for (r = 0; r < 4; ++r) { 5993 const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5994 5995 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5996 coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5997 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5998 #if 1 5999 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6000 for (p = 0; p < 2; ++p) { 6001 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6002 } 6003 #endif 6004 supportNew[0] = (c - cStart)*4 + r; 6005 supportNew[1] = (c - cStart)*4 + (r+1)%4; 6006 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6007 #if 1 6008 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6009 for (p = 0; p < 2; ++p) { 6010 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6011 } 6012 #endif 6013 } 6014 } 6015 /* Old vertices have identical supports */ 6016 for (v = vStart; v < vEnd; ++v) { 6017 const PetscInt newp = vStartNew + (v - vStart); 6018 const PetscInt *support, *cone; 6019 PetscInt size, s; 6020 6021 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6022 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6023 for (s = 0; s < size; ++s) { 6024 PetscInt r = 0; 6025 6026 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6027 if (cone[1] == v) r = 1; 6028 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6029 } 6030 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6031 #if 1 6032 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6033 for (p = 0; p < size; ++p) { 6034 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6035 } 6036 #endif 6037 } 6038 /* Face vertices have 2 + cells supports */ 6039 for (f = fStart; f < fEnd; ++f) { 6040 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6041 const PetscInt *cone, *support; 6042 PetscInt size, s; 6043 6044 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6045 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6046 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6047 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6048 for (s = 0; s < size; ++s) { 6049 PetscInt r = 0; 6050 6051 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6052 if (cone[1] == f) r = 1; 6053 else if (cone[2] == f) r = 2; 6054 else if (cone[3] == f) r = 3; 6055 supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 6056 } 6057 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6058 #if 1 6059 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6060 for (p = 0; p < 2+size; ++p) { 6061 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6062 } 6063 #endif 6064 } 6065 /* Cell vertices have 4 supports */ 6066 for (c = cStart; c < cEnd; ++c) { 6067 const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6068 PetscInt supportNew[4]; 6069 6070 for (r = 0; r < 4; ++r) { 6071 supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 6072 } 6073 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6074 } 6075 break; 6076 case 3: 6077 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6078 cMax = PetscMin(cEnd, cMax); 6079 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6080 fMax = PetscMin(fEnd, fMax); 6081 /* Interior cells have 3 faces */ 6082 for (c = cStart; c < cMax; ++c) { 6083 const PetscInt newp = cStartNew + (c - cStart)*4; 6084 const PetscInt *cone, *ornt; 6085 PetscInt coneNew[3], orntNew[3]; 6086 6087 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6088 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6089 /* A triangle */ 6090 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6091 orntNew[0] = ornt[0]; 6092 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6093 orntNew[1] = -2; 6094 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 6095 orntNew[2] = ornt[2]; 6096 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6097 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6098 #if 1 6099 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6100 for (p = 0; p < 3; ++p) { 6101 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6102 } 6103 #endif 6104 /* B triangle */ 6105 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6106 orntNew[0] = ornt[0]; 6107 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6108 orntNew[1] = ornt[1]; 6109 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6110 orntNew[2] = -2; 6111 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6112 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6113 #if 1 6114 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6115 for (p = 0; p < 3; ++p) { 6116 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6117 } 6118 #endif 6119 /* C triangle */ 6120 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6121 orntNew[0] = -2; 6122 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6123 orntNew[1] = ornt[1]; 6124 coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 6125 orntNew[2] = ornt[2]; 6126 ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 6127 ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 6128 #if 1 6129 if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 6130 for (p = 0; p < 3; ++p) { 6131 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6132 } 6133 #endif 6134 /* D triangle */ 6135 coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0; 6136 orntNew[0] = 0; 6137 coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1; 6138 orntNew[1] = 0; 6139 coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2; 6140 orntNew[2] = 0; 6141 ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 6142 ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 6143 #if 1 6144 if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 6145 for (p = 0; p < 3; ++p) { 6146 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6147 } 6148 #endif 6149 } 6150 /* 6151 2----3----3 6152 | | 6153 | B | 6154 | | 6155 0----4--- 1 6156 | | 6157 | A | 6158 | | 6159 0----2----1 6160 */ 6161 /* Hybrid cells have 4 faces */ 6162 for (c = cMax; c < cEnd; ++c) { 6163 const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2; 6164 const PetscInt *cone, *ornt; 6165 PetscInt coneNew[4], orntNew[4]; 6166 6167 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6168 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 6169 /* A quad */ 6170 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 6171 orntNew[0] = ornt[0]; 6172 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 6173 orntNew[1] = ornt[1]; 6174 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax); 6175 orntNew[2] = 0; 6176 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6177 orntNew[3] = 0; 6178 ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 6179 ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 6180 #if 1 6181 if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 6182 for (p = 0; p < 4; ++p) { 6183 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6184 } 6185 #endif 6186 /* B quad */ 6187 coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 6188 orntNew[0] = ornt[0]; 6189 coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 6190 orntNew[1] = ornt[1]; 6191 coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6192 orntNew[2] = 0; 6193 coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax); 6194 orntNew[3] = 0; 6195 ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 6196 ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 6197 #if 1 6198 if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 6199 for (p = 0; p < 4; ++p) { 6200 if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 6201 } 6202 #endif 6203 } 6204 /* Interior split faces have 2 vertices and the same cells as the parent */ 6205 ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr); 6206 ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 6207 for (f = fStart; f < fMax; ++f) { 6208 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6209 6210 for (r = 0; r < 2; ++r) { 6211 const PetscInt newp = fStartNew + (f - fStart)*2 + r; 6212 const PetscInt *cone, *support; 6213 PetscInt coneNew[2], coneSize, c, supportSize, s; 6214 6215 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6216 coneNew[0] = vStartNew + (cone[0] - vStart); 6217 coneNew[1] = vStartNew + (cone[1] - vStart); 6218 coneNew[(r+1)%2] = newv; 6219 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6220 #if 1 6221 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6222 for (p = 0; p < 2; ++p) { 6223 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6224 } 6225 #endif 6226 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 6227 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6228 for (s = 0; s < supportSize; ++s) { 6229 if (support[s] >= cMax) { 6230 supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6231 } else { 6232 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 6233 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6234 for (c = 0; c < coneSize; ++c) { 6235 if (cone[c] == f) break; 6236 } 6237 supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 6238 } 6239 } 6240 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6241 #if 1 6242 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6243 for (p = 0; p < supportSize; ++p) { 6244 if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 6245 } 6246 #endif 6247 } 6248 } 6249 /* Interior cell faces have 2 vertices and 2 cells */ 6250 for (c = cStart; c < cMax; ++c) { 6251 const PetscInt *cone; 6252 6253 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6254 for (r = 0; r < 3; ++r) { 6255 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r; 6256 PetscInt coneNew[2]; 6257 PetscInt supportNew[2]; 6258 6259 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 6260 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 6261 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6262 #if 1 6263 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6264 for (p = 0; p < 2; ++p) { 6265 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6266 } 6267 #endif 6268 supportNew[0] = (c - cStart)*4 + (r+1)%3; 6269 supportNew[1] = (c - cStart)*4 + 3; 6270 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6271 #if 1 6272 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6273 for (p = 0; p < 2; ++p) { 6274 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6275 } 6276 #endif 6277 } 6278 } 6279 /* Interior hybrid faces have 2 vertices and the same cells */ 6280 for (f = fMax; f < fEnd; ++f) { 6281 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax); 6282 const PetscInt *cone; 6283 const PetscInt *support; 6284 PetscInt coneNew[2]; 6285 PetscInt supportNew[2]; 6286 PetscInt size, s, r; 6287 6288 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6289 coneNew[0] = vStartNew + (cone[0] - vStart); 6290 coneNew[1] = vStartNew + (cone[1] - vStart); 6291 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6292 #if 1 6293 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6294 for (p = 0; p < 2; ++p) { 6295 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6296 } 6297 #endif 6298 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6299 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6300 for (s = 0; s < size; ++s) { 6301 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6302 for (r = 0; r < 2; ++r) { 6303 if (cone[r+2] == f) break; 6304 } 6305 supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r; 6306 } 6307 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6308 #if 1 6309 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6310 for (p = 0; p < size; ++p) { 6311 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6312 } 6313 #endif 6314 } 6315 /* Cell hybrid faces have 2 vertices and 2 cells */ 6316 for (c = cMax; c < cEnd; ++c) { 6317 const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax); 6318 const PetscInt *cone; 6319 PetscInt coneNew[2]; 6320 PetscInt supportNew[2]; 6321 6322 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 6323 coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart); 6324 coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart); 6325 ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 6326 #if 1 6327 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6328 for (p = 0; p < 2; ++p) { 6329 if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 6330 } 6331 #endif 6332 supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0; 6333 supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1; 6334 ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 6335 #if 1 6336 if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 6337 for (p = 0; p < 2; ++p) { 6338 if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 6339 } 6340 #endif 6341 } 6342 /* Old vertices have identical supports */ 6343 for (v = vStart; v < vEnd; ++v) { 6344 const PetscInt newp = vStartNew + (v - vStart); 6345 const PetscInt *support, *cone; 6346 PetscInt size, s; 6347 6348 ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 6349 ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 6350 for (s = 0; s < size; ++s) { 6351 if (support[s] >= fMax) { 6352 supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax); 6353 } else { 6354 PetscInt r = 0; 6355 6356 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6357 if (cone[1] == v) r = 1; 6358 supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 6359 } 6360 } 6361 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6362 #if 1 6363 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6364 for (p = 0; p < size; ++p) { 6365 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6366 } 6367 #endif 6368 } 6369 /* Face vertices have 2 + (2 interior, 1 hybrid) supports */ 6370 for (f = fStart; f < fMax; ++f) { 6371 const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 6372 const PetscInt *cone, *support; 6373 PetscInt size, newSize = 2, s; 6374 6375 ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 6376 ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 6377 supportRef[0] = fStartNew + (f - fStart)*2 + 0; 6378 supportRef[1] = fStartNew + (f - fStart)*2 + 1; 6379 for (s = 0; s < size; ++s) { 6380 PetscInt r = 0; 6381 6382 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 6383 if (support[s] >= cMax) { 6384 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax); 6385 6386 newSize += 1; 6387 } else { 6388 if (cone[1] == f) r = 1; 6389 else if (cone[2] == f) r = 2; 6390 supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 6391 supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r; 6392 6393 newSize += 2; 6394 } 6395 } 6396 ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 6397 #if 1 6398 if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 6399 for (p = 0; p < newSize; ++p) { 6400 if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 6401 } 6402 #endif 6403 } 6404 ierr = PetscFree(supportRef);CHKERRQ(ierr); 6405 break; 6406 default: 6407 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6408 } 6409 PetscFunctionReturn(0); 6410 } 6411 6412 #undef __FUNCT__ 6413 #define __FUNCT__ "CellRefinerSetCoordinates" 6414 PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6415 { 6416 PetscSection coordSection, coordSectionNew; 6417 Vec coordinates, coordinatesNew; 6418 PetscScalar *coords, *coordsNew; 6419 PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f; 6420 PetscErrorCode ierr; 6421 6422 PetscFunctionBegin; 6423 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6424 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6425 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6426 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6427 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6428 ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr); 6429 ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr); 6430 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6431 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr); 6432 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 6433 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 6434 ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 6435 if (fMax < 0) fMax = fEnd; 6436 switch (refiner) { 6437 case 1: 6438 case 2: 6439 case 3: 6440 /* Simplicial and Hex 2D */ 6441 /* All vertices have the dim coordinates */ 6442 for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 6443 ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 6444 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 6445 } 6446 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 6447 ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 6448 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6449 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 6450 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr); 6451 ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 6452 ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 6453 ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 6454 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 6455 ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6456 /* Old vertices have the same coordinates */ 6457 for (v = vStart; v < vEnd; ++v) { 6458 const PetscInt newv = vStartNew + (v - vStart); 6459 PetscInt off, offnew, d; 6460 6461 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6462 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6463 for (d = 0; d < dim; ++d) { 6464 coordsNew[offnew+d] = coords[off+d]; 6465 } 6466 } 6467 /* Face vertices have the average of endpoint coordinates */ 6468 for (f = fStart; f < fMax; ++f) { 6469 const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 6470 const PetscInt *cone; 6471 PetscInt coneSize, offA, offB, offnew, d; 6472 6473 ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 6474 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 6475 ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 6476 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6477 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6478 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6479 for (d = 0; d < dim; ++d) { 6480 coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 6481 } 6482 } 6483 /* Just Hex 2D */ 6484 if (refiner == 2) { 6485 /* Cell vertices have the average of corner coordinates */ 6486 for (c = cStart; c < cEnd; ++c) { 6487 const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 6488 PetscInt *cone = NULL; 6489 PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 6490 6491 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6492 for (p = 0; p < closureSize*2; p += 2) { 6493 const PetscInt point = cone[p]; 6494 if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point; 6495 } 6496 if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 6497 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 6498 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 6499 ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 6500 ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 6501 ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 6502 for (d = 0; d < dim; ++d) { 6503 coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 6504 } 6505 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 6506 } 6507 } 6508 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 6509 ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 6510 ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 6511 ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 6512 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 6513 break; 6514 default: 6515 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6516 } 6517 PetscFunctionReturn(0); 6518 } 6519 6520 #undef __FUNCT__ 6521 #define __FUNCT__ "DMPlexCreateProcessSF" 6522 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 6523 { 6524 PetscInt numRoots, numLeaves, l; 6525 const PetscInt *localPoints; 6526 const PetscSFNode *remotePoints; 6527 PetscInt *localPointsNew; 6528 PetscSFNode *remotePointsNew; 6529 PetscInt *ranks, *ranksNew; 6530 PetscErrorCode ierr; 6531 6532 PetscFunctionBegin; 6533 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6534 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 6535 for (l = 0; l < numLeaves; ++l) { 6536 ranks[l] = remotePoints[l].rank; 6537 } 6538 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6539 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6540 ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6541 ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6542 for (l = 0; l < numLeaves; ++l) { 6543 ranksNew[l] = ranks[l]; 6544 localPointsNew[l] = l; 6545 remotePointsNew[l].index = 0; 6546 remotePointsNew[l].rank = ranksNew[l]; 6547 } 6548 ierr = PetscFree(ranks);CHKERRQ(ierr); 6549 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6550 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 6551 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6552 ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6553 PetscFunctionReturn(0); 6554 } 6555 6556 #undef __FUNCT__ 6557 #define __FUNCT__ "CellRefinerCreateSF" 6558 PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6559 { 6560 PetscSF sf, sfNew, sfProcess; 6561 IS processRanks; 6562 MPI_Datatype depthType; 6563 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6564 const PetscInt *localPoints, *neighbors; 6565 const PetscSFNode *remotePoints; 6566 PetscInt *localPointsNew; 6567 PetscSFNode *remotePointsNew; 6568 PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6569 PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n; 6570 PetscErrorCode ierr; 6571 6572 PetscFunctionBegin; 6573 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6574 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6575 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6576 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6577 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6578 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6579 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6580 ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6581 switch (refiner) { 6582 case 3: 6583 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6584 cMax = PetscMin(cEnd, cMax); 6585 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6586 fMax = PetscMin(fEnd, fMax); 6587 } 6588 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6589 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6590 /* Caculate size of new SF */ 6591 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6592 if (numRoots < 0) PetscFunctionReturn(0); 6593 for (l = 0; l < numLeaves; ++l) { 6594 const PetscInt p = localPoints[l]; 6595 6596 switch (refiner) { 6597 case 1: 6598 /* Simplicial 2D */ 6599 if ((p >= vStart) && (p < vEnd)) { 6600 /* Old vertices stay the same */ 6601 ++numLeavesNew; 6602 } else if ((p >= fStart) && (p < fEnd)) { 6603 /* Old faces add new faces and vertex */ 6604 numLeavesNew += 1 + 2; 6605 } else if ((p >= cStart) && (p < cEnd)) { 6606 /* Old cells add new cells and interior faces */ 6607 numLeavesNew += 4 + 3; 6608 } 6609 break; 6610 case 2: 6611 /* Hex 2D */ 6612 if ((p >= vStart) && (p < vEnd)) { 6613 /* Old vertices stay the same */ 6614 ++numLeavesNew; 6615 } else if ((p >= fStart) && (p < fEnd)) { 6616 /* Old faces add new faces and vertex */ 6617 numLeavesNew += 1 + 2; 6618 } else if ((p >= cStart) && (p < cEnd)) { 6619 /* Old cells add new cells and interior faces */ 6620 numLeavesNew += 4 + 4; 6621 } 6622 break; 6623 default: 6624 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6625 } 6626 } 6627 /* Communicate depthSizes for each remote rank */ 6628 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6629 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6630 ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6631 ierr = PetscMalloc7(depth+1,PetscInt,&depthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthMaxOld,numNeighbors,PetscInt,&rvStart,numNeighbors,PetscInt,&reStart,numNeighbors,PetscInt,&rfStart,numNeighbors,PetscInt,&rcStart);CHKERRQ(ierr); 6632 ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6633 ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6634 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6635 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6636 for (n = 0; n < numNeighbors; ++n) { 6637 ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6638 } 6639 depthSizeOld[depth] = cMax; 6640 depthSizeOld[0] = vMax; 6641 depthSizeOld[depth-1] = fMax; 6642 depthSizeOld[1] = eMax; 6643 6644 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6645 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr); 6646 6647 depthSizeOld[depth] = cEnd - cStart; 6648 depthSizeOld[0] = vEnd - vStart; 6649 depthSizeOld[depth-1] = fEnd - fStart; 6650 depthSizeOld[1] = eEnd - eStart; 6651 6652 ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6653 ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6654 for (n = 0; n < numNeighbors; ++n) { 6655 ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6656 } 6657 ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6658 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6659 /* Calculate new point SF */ 6660 ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6661 ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6662 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6663 for (l = 0, m = 0; l < numLeaves; ++l) { 6664 PetscInt p = localPoints[l]; 6665 PetscInt rp = remotePoints[l].index, n; 6666 PetscMPIInt rrank = remotePoints[l].rank; 6667 6668 ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6669 if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6670 switch (refiner) { 6671 case 1: 6672 /* Simplicial 2D */ 6673 if ((p >= vStart) && (p < vEnd)) { 6674 /* Old vertices stay the same */ 6675 localPointsNew[m] = vStartNew + (p - vStart); 6676 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6677 remotePointsNew[m].rank = rrank; 6678 ++m; 6679 } else if ((p >= fStart) && (p < fEnd)) { 6680 /* Old faces add new faces and vertex */ 6681 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6682 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6683 remotePointsNew[m].rank = rrank; 6684 ++m; 6685 for (r = 0; r < 2; ++r, ++m) { 6686 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6687 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6688 remotePointsNew[m].rank = rrank; 6689 } 6690 } else if ((p >= cStart) && (p < cEnd)) { 6691 /* Old cells add new cells and interior faces */ 6692 for (r = 0; r < 4; ++r, ++m) { 6693 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6694 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6695 remotePointsNew[m].rank = rrank; 6696 } 6697 for (r = 0; r < 3; ++r, ++m) { 6698 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6699 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6700 remotePointsNew[m].rank = rrank; 6701 } 6702 } 6703 break; 6704 case 2: 6705 /* Hex 2D */ 6706 if ((p >= vStart) && (p < vEnd)) { 6707 /* Old vertices stay the same */ 6708 localPointsNew[m] = vStartNew + (p - vStart); 6709 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6710 remotePointsNew[m].rank = rrank; 6711 ++m; 6712 } else if ((p >= fStart) && (p < fEnd)) { 6713 /* Old faces add new faces and vertex */ 6714 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6715 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6716 remotePointsNew[m].rank = rrank; 6717 ++m; 6718 for (r = 0; r < 2; ++r, ++m) { 6719 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6720 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6721 remotePointsNew[m].rank = rrank; 6722 } 6723 } else if ((p >= cStart) && (p < cEnd)) { 6724 /* Old cells add new cells and interior faces */ 6725 for (r = 0; r < 4; ++r, ++m) { 6726 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6727 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6728 remotePointsNew[m].rank = rrank; 6729 } 6730 for (r = 0; r < 4; ++r, ++m) { 6731 localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6732 remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6733 remotePointsNew[m].rank = rrank; 6734 } 6735 } 6736 break; 6737 case 3: 6738 /* Hybrid simplicial 2D */ 6739 if ((p >= vStart) && (p < vEnd)) { 6740 /* Old vertices stay the same */ 6741 localPointsNew[m] = vStartNew + (p - vStart); 6742 remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6743 remotePointsNew[m].rank = rrank; 6744 ++m; 6745 } else if ((p >= fStart) && (p < fMax)) { 6746 /* Old interior faces add new faces and vertex */ 6747 localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6748 remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6749 remotePointsNew[m].rank = rrank; 6750 ++m; 6751 for (r = 0; r < 2; ++r, ++m) { 6752 localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6753 remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6754 remotePointsNew[m].rank = rrank; 6755 } 6756 } else if ((p >= fMax) && (p < fEnd)) { 6757 /* Old hybrid faces stay the same */ 6758 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax); 6759 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]); 6760 remotePointsNew[m].rank = rrank; 6761 ++m; 6762 } else if ((p >= cStart) && (p < cMax)) { 6763 /* Old interior cells add new cells and interior faces */ 6764 for (r = 0; r < 4; ++r, ++m) { 6765 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6766 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6767 remotePointsNew[m].rank = rrank; 6768 } 6769 for (r = 0; r < 3; ++r, ++m) { 6770 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r; 6771 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r; 6772 remotePointsNew[m].rank = rrank; 6773 } 6774 } else if ((p >= cStart) && (p < cMax)) { 6775 /* Old hybrid cells add new cells and hybrid face */ 6776 for (r = 0; r < 2; ++r, ++m) { 6777 localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6778 remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6779 remotePointsNew[m].rank = rrank; 6780 } 6781 localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6782 remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth]); 6783 remotePointsNew[m].rank = rrank; 6784 ++m; 6785 } 6786 break; 6787 default: 6788 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6789 } 6790 } 6791 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6792 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6793 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6794 ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6795 ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6796 PetscFunctionReturn(0); 6797 } 6798 6799 #undef __FUNCT__ 6800 #define __FUNCT__ "CellRefinerCreateLabels" 6801 PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6802 { 6803 PetscInt numLabels, l; 6804 PetscInt newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r; 6805 PetscErrorCode ierr; 6806 6807 PetscFunctionBegin; 6808 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6809 ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6810 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6811 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6812 6813 cStartNew = 0; 6814 vStartNew = depthSize[2]; 6815 fStartNew = depthSize[2] + depthSize[0]; 6816 6817 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6818 ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr); 6819 switch (refiner) { 6820 case 3: 6821 if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh"); 6822 cMax = PetscMin(cEnd, cMax); 6823 if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh"); 6824 fMax = PetscMin(fEnd, fMax); 6825 } 6826 for (l = 0; l < numLabels; ++l) { 6827 DMLabel label, labelNew; 6828 const char *lname; 6829 PetscBool isDepth; 6830 IS valueIS; 6831 const PetscInt *values; 6832 PetscInt numValues, val; 6833 6834 ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6835 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6836 if (isDepth) continue; 6837 ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6838 ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6839 ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6840 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6841 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6842 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6843 for (val = 0; val < numValues; ++val) { 6844 IS pointIS; 6845 const PetscInt *points; 6846 PetscInt numPoints, n; 6847 6848 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6849 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6850 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6851 for (n = 0; n < numPoints; ++n) { 6852 const PetscInt p = points[n]; 6853 switch (refiner) { 6854 case 1: 6855 /* Simplicial 2D */ 6856 if ((p >= vStart) && (p < vEnd)) { 6857 /* Old vertices stay the same */ 6858 newp = vStartNew + (p - vStart); 6859 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6860 } else if ((p >= fStart) && (p < fEnd)) { 6861 /* Old faces add new faces and vertex */ 6862 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6863 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6864 for (r = 0; r < 2; ++r) { 6865 newp = fStartNew + (p - fStart)*2 + r; 6866 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6867 } 6868 } else if ((p >= cStart) && (p < cEnd)) { 6869 /* Old cells add new cells and interior faces */ 6870 for (r = 0; r < 4; ++r) { 6871 newp = cStartNew + (p - cStart)*4 + r; 6872 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6873 } 6874 for (r = 0; r < 3; ++r) { 6875 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6876 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6877 } 6878 } 6879 break; 6880 case 2: 6881 /* Hex 2D */ 6882 if ((p >= vStart) && (p < vEnd)) { 6883 /* Old vertices stay the same */ 6884 newp = vStartNew + (p - vStart); 6885 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6886 } else if ((p >= fStart) && (p < fEnd)) { 6887 /* Old faces add new faces and vertex */ 6888 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6889 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6890 for (r = 0; r < 2; ++r) { 6891 newp = fStartNew + (p - fStart)*2 + r; 6892 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6893 } 6894 } else if ((p >= cStart) && (p < cEnd)) { 6895 /* Old cells add new cells and interior faces and vertex */ 6896 for (r = 0; r < 4; ++r) { 6897 newp = cStartNew + (p - cStart)*4 + r; 6898 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6899 } 6900 for (r = 0; r < 4; ++r) { 6901 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6902 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6903 } 6904 newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 6905 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6906 } 6907 break; 6908 case 3: 6909 /* Hybrid simplicial 2D */ 6910 if ((p >= vStart) && (p < vEnd)) { 6911 /* Old vertices stay the same */ 6912 newp = vStartNew + (p - vStart); 6913 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6914 } else if ((p >= fStart) && (p < fMax)) { 6915 /* Old interior faces add new faces and vertex */ 6916 newp = vStartNew + (vEnd - vStart) + (p - fStart); 6917 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6918 for (r = 0; r < 2; ++r) { 6919 newp = fStartNew + (p - fStart)*2 + r; 6920 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6921 } 6922 } else if ((p >= fMax) && (p < fEnd)) { 6923 /* Old hybrid faces stay the same */ 6924 newp = fStartNew + (fMax - fStart)*2 + (p - fMax); 6925 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6926 } else if ((p >= cStart) && (p < cMax)) { 6927 /* Old interior cells add new cells and interior faces */ 6928 for (r = 0; r < 4; ++r) { 6929 newp = cStartNew + (p - cStart)*4 + r; 6930 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6931 } 6932 for (r = 0; r < 3; ++r) { 6933 newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6934 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6935 } 6936 } else if ((p >= cMax) && (p < cEnd)) { 6937 /* Old hybrid cells add new cells and hybrid face */ 6938 for (r = 0; r < 2; ++r) { 6939 newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r; 6940 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6941 } 6942 newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax); 6943 ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6944 } 6945 break; 6946 default: 6947 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6948 } 6949 } 6950 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 6951 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 6952 } 6953 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 6954 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 6955 if (0) { 6956 ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 6957 ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6958 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6959 } 6960 } 6961 PetscFunctionReturn(0); 6962 } 6963 6964 #undef __FUNCT__ 6965 #define __FUNCT__ "DMPlexRefine_Uniform" 6966 /* This will only work for interpolated meshes */ 6967 PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 6968 { 6969 DM rdm; 6970 PetscInt *depthSize; 6971 PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 6972 PetscErrorCode ierr; 6973 6974 PetscFunctionBegin; 6975 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 6976 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 6977 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6978 ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 6979 /* Calculate number of new points of each depth */ 6980 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6981 ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 6982 ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 6983 ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 6984 /* Step 1: Set chart */ 6985 for (d = 0; d <= depth; ++d) pEnd += depthSize[d]; 6986 ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 6987 /* Step 2: Set cone/support sizes */ 6988 ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6989 /* Step 3: Setup refined DM */ 6990 ierr = DMSetUp(rdm);CHKERRQ(ierr); 6991 /* Step 4: Set cones and supports */ 6992 ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6993 /* Step 5: Stratify */ 6994 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 6995 /* Step 6: Set coordinates for vertices */ 6996 ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6997 /* Step 7: Create pointSF */ 6998 ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6999 /* Step 8: Create labels */ 7000 ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 7001 ierr = PetscFree(depthSize);CHKERRQ(ierr); 7002 7003 *dmRefined = rdm; 7004 PetscFunctionReturn(0); 7005 } 7006 7007 #undef __FUNCT__ 7008 #define __FUNCT__ "DMPlexSetRefinementUniform" 7009 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 7010 { 7011 DM_Plex *mesh = (DM_Plex*) dm->data; 7012 7013 PetscFunctionBegin; 7014 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7015 mesh->refinementUniform = refinementUniform; 7016 PetscFunctionReturn(0); 7017 } 7018 7019 #undef __FUNCT__ 7020 #define __FUNCT__ "DMPlexGetRefinementUniform" 7021 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 7022 { 7023 DM_Plex *mesh = (DM_Plex*) dm->data; 7024 7025 PetscFunctionBegin; 7026 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7027 PetscValidPointer(refinementUniform, 2); 7028 *refinementUniform = mesh->refinementUniform; 7029 PetscFunctionReturn(0); 7030 } 7031 7032 #undef __FUNCT__ 7033 #define __FUNCT__ "DMPlexSetRefinementLimit" 7034 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 7035 { 7036 DM_Plex *mesh = (DM_Plex*) dm->data; 7037 7038 PetscFunctionBegin; 7039 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7040 mesh->refinementLimit = refinementLimit; 7041 PetscFunctionReturn(0); 7042 } 7043 7044 #undef __FUNCT__ 7045 #define __FUNCT__ "DMPlexGetRefinementLimit" 7046 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 7047 { 7048 DM_Plex *mesh = (DM_Plex*) dm->data; 7049 7050 PetscFunctionBegin; 7051 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7052 PetscValidPointer(refinementLimit, 2); 7053 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 7054 *refinementLimit = mesh->refinementLimit; 7055 PetscFunctionReturn(0); 7056 } 7057 7058 #undef __FUNCT__ 7059 #define __FUNCT__ "DMPlexGetCellRefiner_Private" 7060 PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 7061 { 7062 PetscInt dim, cStart, coneSize, cMax; 7063 PetscErrorCode ierr; 7064 7065 PetscFunctionBegin; 7066 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7067 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 7068 ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 7069 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7070 switch (dim) { 7071 case 2: 7072 switch (coneSize) { 7073 case 3: 7074 if (cMax >= 0) *cellRefiner = 3; /* Hybrid */ 7075 else *cellRefiner = 1; /* Triangular */ 7076 break; 7077 case 4: 7078 if (cMax >= 0) *cellRefiner = 4; /* Hybrid */ 7079 else *cellRefiner = 2; /* Quadrilateral */ 7080 break; 7081 default: 7082 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 7083 } 7084 break; 7085 default: 7086 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 7087 } 7088 PetscFunctionReturn(0); 7089 } 7090 7091 #undef __FUNCT__ 7092 #define __FUNCT__ "DMRefine_Plex" 7093 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 7094 { 7095 PetscReal refinementLimit; 7096 PetscInt dim, cStart, cEnd; 7097 char genname[1024], *name = NULL; 7098 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 7099 PetscErrorCode ierr; 7100 7101 PetscFunctionBegin; 7102 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 7103 if (isUniform) { 7104 CellRefiner cellRefiner; 7105 7106 ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 7107 ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 7108 PetscFunctionReturn(0); 7109 } 7110 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 7111 if (refinementLimit == 0.0) PetscFunctionReturn(0); 7112 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7113 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7114 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 7115 if (flg) name = genname; 7116 if (name) { 7117 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 7118 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 7119 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 7120 } 7121 switch (dim) { 7122 case 2: 7123 if (!name || isTriangle) { 7124 #if defined(PETSC_HAVE_TRIANGLE) 7125 double *maxVolumes; 7126 PetscInt c; 7127 7128 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7129 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7130 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7131 #else 7132 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 7133 #endif 7134 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 7135 break; 7136 case 3: 7137 if (!name || isCTetgen) { 7138 #if defined(PETSC_HAVE_CTETGEN) 7139 PetscReal *maxVolumes; 7140 PetscInt c; 7141 7142 ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 7143 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7144 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7145 #else 7146 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 7147 #endif 7148 } else if (isTetgen) { 7149 #if defined(PETSC_HAVE_TETGEN) 7150 double *maxVolumes; 7151 PetscInt c; 7152 7153 ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 7154 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 7155 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 7156 #else 7157 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 7158 #endif 7159 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 7160 break; 7161 default: 7162 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 7163 } 7164 PetscFunctionReturn(0); 7165 } 7166 7167 #undef __FUNCT__ 7168 #define __FUNCT__ "DMPlexGetDepth" 7169 /*@ 7170 DMPlexGetDepth - get the number of strata 7171 7172 Not Collective 7173 7174 Input Parameters: 7175 . dm - The DMPlex object 7176 7177 Output Parameters: 7178 . depth - number of strata 7179 7180 Level: developer 7181 7182 Notes: 7183 DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 7184 7185 .keywords: mesh, points 7186 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 7187 @*/ 7188 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 7189 { 7190 PetscInt d; 7191 PetscErrorCode ierr; 7192 7193 PetscFunctionBegin; 7194 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7195 PetscValidPointer(depth, 2); 7196 ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 7197 *depth = d-1; 7198 PetscFunctionReturn(0); 7199 } 7200 7201 #undef __FUNCT__ 7202 #define __FUNCT__ "DMPlexGetDepthStratum" 7203 /*@ 7204 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 7205 7206 Not Collective 7207 7208 Input Parameters: 7209 + dm - The DMPlex object 7210 - stratumValue - The requested depth 7211 7212 Output Parameters: 7213 + start - The first point at this depth 7214 - end - One beyond the last point at this depth 7215 7216 Level: developer 7217 7218 .keywords: mesh, points 7219 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 7220 @*/ 7221 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7222 { 7223 DM_Plex *mesh = (DM_Plex*) dm->data; 7224 DMLabel next = mesh->labels; 7225 PetscBool flg = PETSC_FALSE; 7226 PetscInt depth; 7227 PetscErrorCode ierr; 7228 7229 PetscFunctionBegin; 7230 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7231 if (stratumValue < 0) { 7232 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7233 PetscFunctionReturn(0); 7234 } else { 7235 PetscInt pStart, pEnd; 7236 7237 if (start) *start = 0; 7238 if (end) *end = 0; 7239 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7240 if (pStart == pEnd) PetscFunctionReturn(0); 7241 } 7242 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7243 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7244 /* We should have a generic GetLabel() and a Label class */ 7245 while (next) { 7246 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7247 if (flg) break; 7248 next = next->next; 7249 } 7250 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7251 depth = stratumValue; 7252 if ((depth < 0) || (depth >= next->numStrata)) { 7253 if (start) *start = 0; 7254 if (end) *end = 0; 7255 } else { 7256 if (start) *start = next->points[next->stratumOffsets[depth]]; 7257 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7258 } 7259 PetscFunctionReturn(0); 7260 } 7261 7262 #undef __FUNCT__ 7263 #define __FUNCT__ "DMPlexGetHeightStratum" 7264 /*@ 7265 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 7266 7267 Not Collective 7268 7269 Input Parameters: 7270 + dm - The DMPlex object 7271 - stratumValue - The requested height 7272 7273 Output Parameters: 7274 + start - The first point at this height 7275 - end - One beyond the last point at this height 7276 7277 Level: developer 7278 7279 .keywords: mesh, points 7280 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 7281 @*/ 7282 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 7283 { 7284 DM_Plex *mesh = (DM_Plex*) dm->data; 7285 DMLabel next = mesh->labels; 7286 PetscBool flg = PETSC_FALSE; 7287 PetscInt depth; 7288 PetscErrorCode ierr; 7289 7290 PetscFunctionBegin; 7291 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7292 if (stratumValue < 0) { 7293 ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 7294 } else { 7295 PetscInt pStart, pEnd; 7296 7297 if (start) *start = 0; 7298 if (end) *end = 0; 7299 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7300 if (pStart == pEnd) PetscFunctionReturn(0); 7301 } 7302 ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 7303 if (!flg) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 7304 /* We should have a generic GetLabel() and a Label class */ 7305 while (next) { 7306 ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 7307 if (flg) break; 7308 next = next->next; 7309 } 7310 /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 7311 depth = next->stratumValues[next->numStrata-1] - stratumValue; 7312 if ((depth < 0) || (depth >= next->numStrata)) { 7313 if (start) *start = 0; 7314 if (end) *end = 0; 7315 } else { 7316 if (start) *start = next->points[next->stratumOffsets[depth]]; 7317 if (end) *end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1; 7318 } 7319 PetscFunctionReturn(0); 7320 } 7321 7322 #undef __FUNCT__ 7323 #define __FUNCT__ "DMPlexCreateSectionInitial" 7324 /* Set the number of dof on each point and separate by fields */ 7325 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 7326 { 7327 PetscInt *numDofTot; 7328 PetscInt pStart = 0, pEnd = 0; 7329 PetscInt p, d, f; 7330 PetscErrorCode ierr; 7331 7332 PetscFunctionBegin; 7333 ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 7334 for (d = 0; d <= dim; ++d) { 7335 numDofTot[d] = 0; 7336 for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d]; 7337 } 7338 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 7339 if (numFields > 0) { 7340 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 7341 if (numComp) { 7342 for (f = 0; f < numFields; ++f) { 7343 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 7344 } 7345 } 7346 } 7347 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7348 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 7349 for (d = 0; d <= dim; ++d) { 7350 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 7351 for (p = pStart; p < pEnd; ++p) { 7352 for (f = 0; f < numFields; ++f) { 7353 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 7354 } 7355 ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 7356 } 7357 } 7358 ierr = PetscFree(numDofTot);CHKERRQ(ierr); 7359 PetscFunctionReturn(0); 7360 } 7361 7362 #undef __FUNCT__ 7363 #define __FUNCT__ "DMPlexCreateSectionBCDof" 7364 /* Set the number of dof on each point and separate by fields 7365 If constDof is PETSC_DETERMINE, constrain every dof on the point 7366 */ 7367 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) 7368 { 7369 PetscInt numFields; 7370 PetscInt bc; 7371 PetscErrorCode ierr; 7372 7373 PetscFunctionBegin; 7374 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7375 for (bc = 0; bc < numBC; ++bc) { 7376 PetscInt field = 0; 7377 const PetscInt *idx; 7378 PetscInt n, i; 7379 7380 if (numFields) field = bcField[bc]; 7381 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 7382 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7383 for (i = 0; i < n; ++i) { 7384 const PetscInt p = idx[i]; 7385 PetscInt numConst = constDof; 7386 7387 /* Constrain every dof on the point */ 7388 if (numConst < 0) { 7389 if (numFields) { 7390 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 7391 } else { 7392 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 7393 } 7394 } 7395 if (numFields) { 7396 ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 7397 } 7398 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 7399 } 7400 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 7401 } 7402 PetscFunctionReturn(0); 7403 } 7404 7405 #undef __FUNCT__ 7406 #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 7407 /* Set the constrained indices on each point and separate by fields */ 7408 PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) 7409 { 7410 PetscInt *maxConstraints; 7411 PetscInt numFields, f, pStart = 0, pEnd = 0, p; 7412 PetscErrorCode ierr; 7413 7414 PetscFunctionBegin; 7415 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7416 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7417 ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 7418 for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0; 7419 for (p = pStart; p < pEnd; ++p) { 7420 PetscInt cdof; 7421 7422 if (numFields) { 7423 for (f = 0; f < numFields; ++f) { 7424 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 7425 maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 7426 } 7427 } else { 7428 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7429 maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 7430 } 7431 } 7432 for (f = 0; f < numFields; ++f) { 7433 maxConstraints[numFields] += maxConstraints[f]; 7434 } 7435 if (maxConstraints[numFields]) { 7436 PetscInt *indices; 7437 7438 ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7439 for (p = pStart; p < pEnd; ++p) { 7440 PetscInt cdof, d; 7441 7442 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7443 if (cdof) { 7444 if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7445 if (numFields) { 7446 PetscInt numConst = 0, foff = 0; 7447 7448 for (f = 0; f < numFields; ++f) { 7449 PetscInt cfdof, fdof; 7450 7451 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7452 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7453 /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7454 for (d = 0; d < cfdof; ++d) indices[numConst+d] = d; 7455 ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7456 for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff; 7457 numConst += cfdof; 7458 foff += fdof; 7459 } 7460 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7461 } else { 7462 for (d = 0; d < cdof; ++d) indices[d] = d; 7463 } 7464 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7465 } 7466 } 7467 ierr = PetscFree(indices);CHKERRQ(ierr); 7468 } 7469 ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7470 PetscFunctionReturn(0); 7471 } 7472 7473 #undef __FUNCT__ 7474 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7475 /* Set the constrained field indices on each point */ 7476 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) 7477 { 7478 const PetscInt *points, *indices; 7479 PetscInt numFields, maxDof, numPoints, p, numConstraints; 7480 PetscErrorCode ierr; 7481 7482 PetscFunctionBegin; 7483 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7484 if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7485 7486 ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7487 ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7488 if (!constraintIndices) { 7489 PetscInt *idx, i; 7490 7491 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7492 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7493 for (i = 0; i < maxDof; ++i) idx[i] = i; 7494 for (p = 0; p < numPoints; ++p) { 7495 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7496 } 7497 ierr = PetscFree(idx);CHKERRQ(ierr); 7498 } else { 7499 ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7500 ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7501 for (p = 0; p < numPoints; ++p) { 7502 PetscInt fcdof; 7503 7504 ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7505 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); 7506 ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7507 } 7508 ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7509 } 7510 ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7511 PetscFunctionReturn(0); 7512 } 7513 7514 #undef __FUNCT__ 7515 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7516 /* Set the constrained indices on each point and separate by fields */ 7517 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 7518 { 7519 PetscInt *indices; 7520 PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7521 PetscErrorCode ierr; 7522 7523 PetscFunctionBegin; 7524 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7525 ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7526 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7527 if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7528 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7529 for (p = pStart; p < pEnd; ++p) { 7530 PetscInt cdof, d; 7531 7532 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7533 if (cdof) { 7534 PetscInt numConst = 0, foff = 0; 7535 7536 for (f = 0; f < numFields; ++f) { 7537 const PetscInt *fcind; 7538 PetscInt fdof, fcdof; 7539 7540 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7541 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7542 if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7543 /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7544 for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff; 7545 foff += fdof; 7546 numConst += fcdof; 7547 } 7548 if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7549 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7550 } 7551 } 7552 ierr = PetscFree(indices);CHKERRQ(ierr); 7553 PetscFunctionReturn(0); 7554 } 7555 7556 #undef __FUNCT__ 7557 #define __FUNCT__ "DMPlexCreateSection" 7558 /*@C 7559 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7560 7561 Not Collective 7562 7563 Input Parameters: 7564 + dm - The DMPlex object 7565 . dim - The spatial dimension of the problem 7566 . numFields - The number of fields in the problem 7567 . numComp - An array of size numFields that holds the number of components for each field 7568 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7569 . numBC - The number of boundary conditions 7570 . bcField - An array of size numBC giving the field number for each boundry condition 7571 - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7572 7573 Output Parameter: 7574 . section - The PetscSection object 7575 7576 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 7577 nubmer of dof for field 0 on each edge. 7578 7579 Level: developer 7580 7581 .keywords: mesh, elements 7582 .seealso: DMPlexCreate(), PetscSectionCreate() 7583 @*/ 7584 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) 7585 { 7586 PetscErrorCode ierr; 7587 7588 PetscFunctionBegin; 7589 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7590 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7591 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7592 if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7593 { 7594 PetscBool view = PETSC_FALSE; 7595 7596 ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7597 if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7598 } 7599 PetscFunctionReturn(0); 7600 } 7601 7602 #undef __FUNCT__ 7603 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7604 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 7605 { 7606 PetscSection section; 7607 PetscErrorCode ierr; 7608 7609 PetscFunctionBegin; 7610 ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7611 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 7612 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7613 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 7614 PetscFunctionReturn(0); 7615 } 7616 7617 #undef __FUNCT__ 7618 #define __FUNCT__ "DMPlexGetCoordinateSection" 7619 /*@ 7620 DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7621 7622 Not Collective 7623 7624 Input Parameter: 7625 . dm - The DMPlex object 7626 7627 Output Parameter: 7628 . section - The PetscSection object 7629 7630 Level: intermediate 7631 7632 .keywords: mesh, coordinates 7633 .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7634 @*/ 7635 PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) 7636 { 7637 DM cdm; 7638 PetscErrorCode ierr; 7639 7640 PetscFunctionBegin; 7641 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7642 PetscValidPointer(section, 2); 7643 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7644 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7645 PetscFunctionReturn(0); 7646 } 7647 7648 #undef __FUNCT__ 7649 #define __FUNCT__ "DMPlexSetCoordinateSection" 7650 /*@ 7651 DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7652 7653 Not Collective 7654 7655 Input Parameters: 7656 + dm - The DMPlex object 7657 - section - The PetscSection object 7658 7659 Level: intermediate 7660 7661 .keywords: mesh, coordinates 7662 .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7663 @*/ 7664 PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) 7665 { 7666 DM cdm; 7667 PetscErrorCode ierr; 7668 7669 PetscFunctionBegin; 7670 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7671 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 7672 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7673 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7674 PetscFunctionReturn(0); 7675 } 7676 7677 #undef __FUNCT__ 7678 #define __FUNCT__ "DMPlexGetConeSection" 7679 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 7680 { 7681 DM_Plex *mesh = (DM_Plex*) dm->data; 7682 7683 PetscFunctionBegin; 7684 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7685 if (section) *section = mesh->coneSection; 7686 PetscFunctionReturn(0); 7687 } 7688 7689 #undef __FUNCT__ 7690 #define __FUNCT__ "DMPlexGetCones" 7691 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 7692 { 7693 DM_Plex *mesh = (DM_Plex*) dm->data; 7694 7695 PetscFunctionBegin; 7696 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7697 if (cones) *cones = mesh->cones; 7698 PetscFunctionReturn(0); 7699 } 7700 7701 #undef __FUNCT__ 7702 #define __FUNCT__ "DMPlexGetConeOrientations" 7703 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 7704 { 7705 DM_Plex *mesh = (DM_Plex*) dm->data; 7706 7707 PetscFunctionBegin; 7708 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7709 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7710 PetscFunctionReturn(0); 7711 } 7712 7713 #undef __FUNCT__ 7714 #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7715 PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7716 { 7717 const PetscInt embedDim = 2; 7718 PetscReal x = PetscRealPart(point[0]); 7719 PetscReal y = PetscRealPart(point[1]); 7720 PetscReal v0[2], J[4], invJ[4], detJ; 7721 PetscReal xi, eta; 7722 PetscErrorCode ierr; 7723 7724 PetscFunctionBegin; 7725 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7726 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 7727 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 7728 7729 if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 7730 else *cell = -1; 7731 PetscFunctionReturn(0); 7732 } 7733 7734 #undef __FUNCT__ 7735 #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7736 PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7737 { 7738 PetscSection coordSection; 7739 Vec coordsLocal; 7740 const PetscScalar *coords; 7741 const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7742 PetscReal x = PetscRealPart(point[0]); 7743 PetscReal y = PetscRealPart(point[1]); 7744 PetscInt crossings = 0, f; 7745 PetscErrorCode ierr; 7746 7747 PetscFunctionBegin; 7748 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7749 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7750 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7751 for (f = 0; f < 4; ++f) { 7752 PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 7753 PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 7754 PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 7755 PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 7756 PetscReal slope = (y_j - y_i) / (x_j - x_i); 7757 PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 7758 PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 7759 PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7760 if ((cond1 || cond2) && above) ++crossings; 7761 } 7762 if (crossings % 2) *cell = c; 7763 else *cell = -1; 7764 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7765 PetscFunctionReturn(0); 7766 } 7767 7768 #undef __FUNCT__ 7769 #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7770 PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7771 { 7772 const PetscInt embedDim = 3; 7773 PetscReal v0[3], J[9], invJ[9], detJ; 7774 PetscReal x = PetscRealPart(point[0]); 7775 PetscReal y = PetscRealPart(point[1]); 7776 PetscReal z = PetscRealPart(point[2]); 7777 PetscReal xi, eta, zeta; 7778 PetscErrorCode ierr; 7779 7780 PetscFunctionBegin; 7781 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7782 xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 7783 eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 7784 zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 7785 7786 if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 7787 else *cell = -1; 7788 PetscFunctionReturn(0); 7789 } 7790 7791 #undef __FUNCT__ 7792 #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7793 PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7794 { 7795 PetscSection coordSection; 7796 Vec coordsLocal; 7797 const PetscScalar *coords; 7798 const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7799 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7800 PetscBool found = PETSC_TRUE; 7801 PetscInt f; 7802 PetscErrorCode ierr; 7803 7804 PetscFunctionBegin; 7805 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7806 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7807 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7808 for (f = 0; f < 6; ++f) { 7809 /* Check the point is under plane */ 7810 /* Get face normal */ 7811 PetscReal v_i[3]; 7812 PetscReal v_j[3]; 7813 PetscReal normal[3]; 7814 PetscReal pp[3]; 7815 PetscReal dot; 7816 7817 v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 7818 v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 7819 v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 7820 v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 7821 v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 7822 v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 7823 normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 7824 normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 7825 normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 7826 pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 7827 pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 7828 pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 7829 dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7830 7831 /* Check that projected point is in face (2D location problem) */ 7832 if (dot < 0.0) { 7833 found = PETSC_FALSE; 7834 break; 7835 } 7836 } 7837 if (found) *cell = c; 7838 else *cell = -1; 7839 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 7840 PetscFunctionReturn(0); 7841 } 7842 7843 #undef __FUNCT__ 7844 #define __FUNCT__ "DMLocatePoints_Plex" 7845 /* 7846 Need to implement using the guess 7847 */ 7848 PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7849 { 7850 PetscInt cell = -1 /*, guess = -1*/; 7851 PetscInt bs, numPoints, p; 7852 PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7853 PetscInt *cells; 7854 PetscScalar *a; 7855 PetscErrorCode ierr; 7856 7857 PetscFunctionBegin; 7858 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7859 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7860 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 7861 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 7862 ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7863 ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7864 ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7865 if (bs != dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Block size for point vector %d must be the mesh coordinate dimension %d", bs, dim); 7866 numPoints /= bs; 7867 ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7868 for (p = 0; p < numPoints; ++p) { 7869 const PetscScalar *point = &a[p*bs]; 7870 7871 switch (dim) { 7872 case 2: 7873 for (c = cStart; c < cEnd; ++c) { 7874 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7875 switch (coneSize) { 7876 case 3: 7877 ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7878 break; 7879 case 4: 7880 ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 7881 break; 7882 default: 7883 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7884 } 7885 if (cell >= 0) break; 7886 } 7887 break; 7888 case 3: 7889 for (c = cStart; c < cEnd; ++c) { 7890 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7891 switch (coneSize) { 7892 case 4: 7893 ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 7894 break; 7895 case 8: 7896 ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 7897 break; 7898 default: 7899 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7900 } 7901 if (cell >= 0) break; 7902 } 7903 break; 7904 default: 7905 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 7906 } 7907 cells[p] = cell; 7908 } 7909 ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 7910 ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 7911 PetscFunctionReturn(0); 7912 } 7913 7914 /******************************** FEM Support **********************************/ 7915 7916 #undef __FUNCT__ 7917 #define __FUNCT__ "DMPlexVecGetClosure" 7918 /*@C 7919 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 7920 7921 Not collective 7922 7923 Input Parameters: 7924 + dm - The DM 7925 . section - The section describing the layout in v, or NULL to use the default section 7926 . v - The local vector 7927 - point - The sieve point in the DM 7928 7929 Output Parameters: 7930 + csize - The number of values in the closure, or NULL 7931 - values - The array of values, which is a borrowed array and should not be freed 7932 7933 Level: intermediate 7934 7935 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7936 @*/ 7937 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 7938 { 7939 PetscScalar *array, *vArray; 7940 PetscInt *points = NULL; 7941 PetscInt offsets[32]; 7942 PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 7943 PetscErrorCode ierr; 7944 7945 PetscFunctionBegin; 7946 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7947 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7948 if (!section) { 7949 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7950 } 7951 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7952 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7953 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7954 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7955 /* Compress out points not in the section */ 7956 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7957 for (p = 0, q = 0; p < numPoints*2; p += 2) { 7958 if ((points[p] >= pStart) && (points[p] < pEnd)) { 7959 points[q*2] = points[p]; 7960 points[q*2+1] = points[p+1]; 7961 ++q; 7962 } 7963 } 7964 numPoints = q; 7965 for (p = 0, size = 0; p < numPoints*2; p += 2) { 7966 PetscInt dof, fdof; 7967 7968 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7969 for (f = 0; f < numFields; ++f) { 7970 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7971 offsets[f+1] += fdof; 7972 } 7973 size += dof; 7974 } 7975 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 7976 if (numFields && offsets[numFields] != size) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 7977 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 7978 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 7979 for (p = 0; p < numPoints*2; p += 2) { 7980 PetscInt o = points[p+1]; 7981 PetscInt dof, off, d; 7982 PetscScalar *varr; 7983 7984 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7985 ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 7986 varr = &vArray[off]; 7987 if (numFields) { 7988 PetscInt fdof, foff, fcomp, f, c; 7989 7990 for (f = 0, foff = 0; f < numFields; ++f) { 7991 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7992 if (o >= 0) { 7993 for (d = 0; d < fdof; ++d, ++offsets[f]) { 7994 array[offsets[f]] = varr[foff+d]; 7995 } 7996 } else { 7997 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7998 for (d = fdof/fcomp-1; d >= 0; --d) { 7999 for (c = 0; c < fcomp; ++c, ++offsets[f]) { 8000 array[offsets[f]] = varr[foff+d*fcomp+c]; 8001 } 8002 } 8003 } 8004 foff += fdof; 8005 } 8006 } else { 8007 if (o >= 0) { 8008 for (d = 0; d < dof; ++d, ++offsets[0]) { 8009 array[offsets[0]] = varr[d]; 8010 } 8011 } else { 8012 for (d = dof-1; d >= 0; --d, ++offsets[0]) { 8013 array[offsets[0]] = varr[d]; 8014 } 8015 } 8016 } 8017 } 8018 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8019 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 8020 if (csize) *csize = size; 8021 *values = array; 8022 PetscFunctionReturn(0); 8023 } 8024 8025 #undef __FUNCT__ 8026 #define __FUNCT__ "DMPlexVecRestoreClosure" 8027 /*@C 8028 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 8029 8030 Not collective 8031 8032 Input Parameters: 8033 + dm - The DM 8034 . section - The section describing the layout in v, or NULL to use the default section 8035 . v - The local vector 8036 . point - The sieve point in the DM 8037 . csize - The number of values in the closure, or NULL 8038 - values - The array of values, which is a borrowed array and should not be freed 8039 8040 Level: intermediate 8041 8042 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 8043 @*/ 8044 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) 8045 { 8046 PetscInt size = 0; 8047 PetscErrorCode ierr; 8048 8049 PetscFunctionBegin; 8050 /* Should work without recalculating size */ 8051 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 8052 PetscFunctionReturn(0); 8053 } 8054 8055 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 8056 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 8057 8058 #undef __FUNCT__ 8059 #define __FUNCT__ "updatePoint_private" 8060 PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8061 { 8062 PetscInt cdof; /* The number of constraints on this point */ 8063 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8064 PetscScalar *a; 8065 PetscInt off, cind = 0, k; 8066 PetscErrorCode ierr; 8067 8068 PetscFunctionBegin; 8069 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8070 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8071 a = &array[off]; 8072 if (!cdof || setBC) { 8073 if (orientation >= 0) { 8074 for (k = 0; k < dof; ++k) { 8075 fuse(&a[k], values[k]); 8076 } 8077 } else { 8078 for (k = 0; k < dof; ++k) { 8079 fuse(&a[k], values[dof-k-1]); 8080 } 8081 } 8082 } else { 8083 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8084 if (orientation >= 0) { 8085 for (k = 0; k < dof; ++k) { 8086 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8087 fuse(&a[k], values[k]); 8088 } 8089 } else { 8090 for (k = 0; k < dof; ++k) { 8091 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 8092 fuse(&a[k], values[dof-k-1]); 8093 } 8094 } 8095 } 8096 PetscFunctionReturn(0); 8097 } 8098 8099 #undef __FUNCT__ 8100 #define __FUNCT__ "updatePointFields_private" 8101 PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 8102 { 8103 PetscScalar *a; 8104 PetscInt numFields, off, foff, f; 8105 PetscErrorCode ierr; 8106 8107 PetscFunctionBegin; 8108 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8109 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 8110 a = &array[off]; 8111 for (f = 0, foff = 0; f < numFields; ++f) { 8112 PetscInt fdof, fcomp, fcdof; 8113 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8114 PetscInt cind = 0, k, c; 8115 8116 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8117 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8118 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 8119 if (!fcdof || setBC) { 8120 if (orientation >= 0) { 8121 for (k = 0; k < fdof; ++k) { 8122 fuse(&a[foff+k], values[foffs[f]+k]); 8123 } 8124 } else { 8125 for (k = fdof/fcomp-1; k >= 0; --k) { 8126 for (c = 0; c < fcomp; ++c) { 8127 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8128 } 8129 } 8130 } 8131 } else { 8132 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8133 if (orientation >= 0) { 8134 for (k = 0; k < fdof; ++k) { 8135 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 8136 fuse(&a[foff+k], values[foffs[f]+k]); 8137 } 8138 } else { 8139 for (k = fdof/fcomp-1; k >= 0; --k) { 8140 for (c = 0; c < fcomp; ++c) { 8141 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 8142 fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 8143 } 8144 } 8145 } 8146 } 8147 foff += fdof; 8148 foffs[f] += fdof; 8149 } 8150 PetscFunctionReturn(0); 8151 } 8152 8153 #undef __FUNCT__ 8154 #define __FUNCT__ "DMPlexVecSetClosure" 8155 /*@C 8156 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 8157 8158 Not collective 8159 8160 Input Parameters: 8161 + dm - The DM 8162 . section - The section describing the layout in v, or NULL to use the default sectionw 8163 . v - The local vector 8164 . point - The sieve point in the DM 8165 . values - The array of values, which is a borrowed array and should not be freed 8166 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 8167 8168 Level: intermediate 8169 8170 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 8171 @*/ 8172 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 8173 { 8174 PetscScalar *array; 8175 PetscInt *points = NULL; 8176 PetscInt offsets[32]; 8177 PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 8178 PetscErrorCode ierr; 8179 8180 PetscFunctionBegin; 8181 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8182 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 8183 if (!section) { 8184 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8185 } 8186 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8187 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8188 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8189 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8190 /* Compress out points not in the section */ 8191 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8192 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8193 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8194 points[q*2] = points[p]; 8195 points[q*2+1] = points[p+1]; 8196 ++q; 8197 } 8198 } 8199 numPoints = q; 8200 for (p = 0; p < numPoints*2; p += 2) { 8201 PetscInt fdof; 8202 8203 for (f = 0; f < numFields; ++f) { 8204 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8205 offsets[f+1] += fdof; 8206 } 8207 } 8208 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8209 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 8210 if (numFields) { 8211 switch (mode) { 8212 case INSERT_VALUES: 8213 for (p = 0; p < numPoints*2; p += 2) { 8214 PetscInt o = points[p+1]; 8215 updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 8216 } break; 8217 case INSERT_ALL_VALUES: 8218 for (p = 0; p < numPoints*2; p += 2) { 8219 PetscInt o = points[p+1]; 8220 updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 8221 } break; 8222 case ADD_VALUES: 8223 for (p = 0; p < numPoints*2; p += 2) { 8224 PetscInt o = points[p+1]; 8225 updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 8226 } break; 8227 case ADD_ALL_VALUES: 8228 for (p = 0; p < numPoints*2; p += 2) { 8229 PetscInt o = points[p+1]; 8230 updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 8231 } break; 8232 default: 8233 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8234 } 8235 } else { 8236 switch (mode) { 8237 case INSERT_VALUES: 8238 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8239 PetscInt o = points[p+1]; 8240 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8241 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 8242 } break; 8243 case INSERT_ALL_VALUES: 8244 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8245 PetscInt o = points[p+1]; 8246 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8247 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 8248 } break; 8249 case ADD_VALUES: 8250 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8251 PetscInt o = points[p+1]; 8252 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8253 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 8254 } break; 8255 case ADD_ALL_VALUES: 8256 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8257 PetscInt o = points[p+1]; 8258 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8259 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 8260 } break; 8261 default: 8262 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 8263 } 8264 } 8265 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8266 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 8267 PetscFunctionReturn(0); 8268 } 8269 8270 #undef __FUNCT__ 8271 #define __FUNCT__ "DMPlexPrintMatSetValues" 8272 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 8273 { 8274 PetscMPIInt rank; 8275 PetscInt i, j; 8276 PetscErrorCode ierr; 8277 8278 PetscFunctionBegin; 8279 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 8280 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 8281 for (i = 0; i < numIndices; i++) { 8282 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 8283 } 8284 for (i = 0; i < numIndices; i++) { 8285 ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr); 8286 for (j = 0; j < numIndices; j++) { 8287 #if defined(PETSC_USE_COMPLEX) 8288 ierr = PetscViewerASCIIPrintf(viewer, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 8289 #else 8290 ierr = PetscViewerASCIIPrintf(viewer, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 8291 #endif 8292 } 8293 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 8294 } 8295 PetscFunctionReturn(0); 8296 } 8297 8298 #undef __FUNCT__ 8299 #define __FUNCT__ "indicesPoint_private" 8300 /* . off - The global offset of this point */ 8301 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8302 { 8303 PetscInt dof; /* The number of unknowns on this point */ 8304 PetscInt cdof; /* The number of constraints on this point */ 8305 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 8306 PetscInt cind = 0, k; 8307 PetscErrorCode ierr; 8308 8309 PetscFunctionBegin; 8310 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 8311 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 8312 if (!cdof || setBC) { 8313 if (orientation >= 0) { 8314 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 8315 } else { 8316 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 8317 } 8318 } else { 8319 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 8320 if (orientation >= 0) { 8321 for (k = 0; k < dof; ++k) { 8322 if ((cind < cdof) && (k == cdofs[cind])) { 8323 /* Insert check for returning constrained indices */ 8324 indices[*loff+k] = -(off+k+1); 8325 ++cind; 8326 } else { 8327 indices[*loff+k] = off+k-cind; 8328 } 8329 } 8330 } else { 8331 for (k = 0; k < dof; ++k) { 8332 if ((cind < cdof) && (k == cdofs[cind])) { 8333 /* Insert check for returning constrained indices */ 8334 indices[*loff+dof-k-1] = -(off+k+1); 8335 ++cind; 8336 } else { 8337 indices[*loff+dof-k-1] = off+k-cind; 8338 } 8339 } 8340 } 8341 } 8342 *loff += dof; 8343 PetscFunctionReturn(0); 8344 } 8345 8346 #undef __FUNCT__ 8347 #define __FUNCT__ "indicesPointFields_private" 8348 /* . off - The global offset of this point */ 8349 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 8350 { 8351 PetscInt numFields, foff, f; 8352 PetscErrorCode ierr; 8353 8354 PetscFunctionBegin; 8355 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8356 for (f = 0, foff = 0; f < numFields; ++f) { 8357 PetscInt fdof, fcomp, cfdof; 8358 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 8359 PetscInt cind = 0, k, c; 8360 8361 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 8362 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 8363 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 8364 if (!cfdof || setBC) { 8365 if (orientation >= 0) { 8366 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 8367 } else { 8368 for (k = fdof/fcomp-1; k >= 0; --k) { 8369 for (c = 0; c < fcomp; ++c) { 8370 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 8371 } 8372 } 8373 } 8374 } else { 8375 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 8376 if (orientation >= 0) { 8377 for (k = 0; k < fdof; ++k) { 8378 if ((cind < cfdof) && (k == fcdofs[cind])) { 8379 indices[foffs[f]+k] = -(off+foff+k+1); 8380 ++cind; 8381 } else { 8382 indices[foffs[f]+k] = off+foff+k-cind; 8383 } 8384 } 8385 } else { 8386 for (k = fdof/fcomp-1; k >= 0; --k) { 8387 for (c = 0; c < fcomp; ++c) { 8388 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 8389 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 8390 ++cind; 8391 } else { 8392 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 8393 } 8394 } 8395 } 8396 } 8397 } 8398 foff += fdof - cfdof; 8399 foffs[f] += fdof; 8400 } 8401 PetscFunctionReturn(0); 8402 } 8403 8404 #undef __FUNCT__ 8405 #define __FUNCT__ "DMPlexMatSetClosure" 8406 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 8407 { 8408 DM_Plex *mesh = (DM_Plex*) dm->data; 8409 PetscInt *points = NULL; 8410 PetscInt *indices; 8411 PetscInt offsets[32]; 8412 PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 8413 PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 8414 PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 8415 PetscErrorCode ierr; 8416 8417 PetscFunctionBegin; 8418 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8419 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 8420 if (useDefault) { 8421 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 8422 } 8423 if (useGlobalDefault) { 8424 if (useDefault) { 8425 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 8426 } else { 8427 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8428 } 8429 } 8430 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 8431 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 8432 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 8433 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8434 /* Compress out points not in the section */ 8435 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 8436 for (p = 0, q = 0; p < numPoints*2; p += 2) { 8437 if ((points[p] >= pStart) && (points[p] < pEnd)) { 8438 points[q*2] = points[p]; 8439 points[q*2+1] = points[p+1]; 8440 ++q; 8441 } 8442 } 8443 numPoints = q; 8444 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 8445 PetscInt fdof; 8446 8447 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 8448 for (f = 0; f < numFields; ++f) { 8449 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 8450 offsets[f+1] += fdof; 8451 } 8452 numIndices += dof; 8453 } 8454 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 8455 8456 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8457 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8458 if (numFields) { 8459 for (p = 0; p < numPoints*2; p += 2) { 8460 PetscInt o = points[p+1]; 8461 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8462 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8463 } 8464 } else { 8465 for (p = 0, off = 0; p < numPoints*2; p += 2) { 8466 PetscInt o = points[p+1]; 8467 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8468 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 8469 } 8470 } 8471 if (useGlobalDefault && !useDefault) { 8472 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8473 } 8474 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);} 8475 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8476 if (ierr) { 8477 PetscMPIInt rank; 8478 PetscErrorCode ierr2; 8479 8480 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 8481 ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8482 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2); 8483 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 8484 CHKERRQ(ierr); 8485 } 8486 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8487 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8488 PetscFunctionReturn(0); 8489 } 8490 8491 #undef __FUNCT__ 8492 #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8493 PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8494 { 8495 PetscSection coordSection; 8496 Vec coordinates; 8497 const PetscScalar *coords; 8498 const PetscInt dim = 2; 8499 PetscInt d, f; 8500 PetscErrorCode ierr; 8501 8502 PetscFunctionBegin; 8503 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8504 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8505 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8506 if (v0) { 8507 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8508 } 8509 if (J) { 8510 for (d = 0; d < dim; d++) { 8511 for (f = 0; f < dim; f++) { 8512 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8513 } 8514 } 8515 *detJ = J[0]*J[3] - J[1]*J[2]; 8516 #if 0 8517 if (detJ < 0.0) { 8518 const PetscReal xLength = mesh->periodicity[0]; 8519 8520 if (xLength != 0.0) { 8521 PetscReal v0x = coords[0*dim+0]; 8522 8523 if (v0x == 0.0) v0x = v0[0] = xLength; 8524 for (f = 0; f < dim; f++) { 8525 const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8526 8527 J[0*dim+f] = 0.5*(px - v0x); 8528 } 8529 } 8530 detJ = J[0]*J[3] - J[1]*J[2]; 8531 } 8532 #endif 8533 PetscLogFlops(8.0 + 3.0); 8534 } 8535 if (invJ) { 8536 const PetscReal invDet = 1.0/(*detJ); 8537 8538 invJ[0] = invDet*J[3]; 8539 invJ[1] = -invDet*J[1]; 8540 invJ[2] = -invDet*J[2]; 8541 invJ[3] = invDet*J[0]; 8542 PetscLogFlops(5.0); 8543 } 8544 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8545 PetscFunctionReturn(0); 8546 } 8547 8548 #undef __FUNCT__ 8549 #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8550 PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8551 { 8552 PetscSection coordSection; 8553 Vec coordinates; 8554 const PetscScalar *coords; 8555 const PetscInt dim = 2; 8556 PetscInt d, f; 8557 PetscErrorCode ierr; 8558 8559 PetscFunctionBegin; 8560 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8561 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8562 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8563 if (v0) { 8564 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8565 } 8566 if (J) { 8567 for (d = 0; d < dim; d++) { 8568 for (f = 0; f < dim; f++) { 8569 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8570 } 8571 } 8572 *detJ = J[0]*J[3] - J[1]*J[2]; 8573 PetscLogFlops(8.0 + 3.0); 8574 } 8575 if (invJ) { 8576 const PetscReal invDet = 1.0/(*detJ); 8577 8578 invJ[0] = invDet*J[3]; 8579 invJ[1] = -invDet*J[1]; 8580 invJ[2] = -invDet*J[2]; 8581 invJ[3] = invDet*J[0]; 8582 PetscLogFlops(5.0); 8583 } 8584 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8585 PetscFunctionReturn(0); 8586 } 8587 8588 #undef __FUNCT__ 8589 #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8590 PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8591 { 8592 PetscSection coordSection; 8593 Vec coordinates; 8594 const PetscScalar *coords; 8595 const PetscInt dim = 3; 8596 PetscInt d, f; 8597 PetscErrorCode ierr; 8598 8599 PetscFunctionBegin; 8600 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8601 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8602 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8603 if (v0) { 8604 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8605 } 8606 if (J) { 8607 for (d = 0; d < dim; d++) { 8608 for (f = 0; f < dim; f++) { 8609 J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8610 } 8611 } 8612 /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8613 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8614 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8615 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8616 PetscLogFlops(18.0 + 12.0); 8617 } 8618 if (invJ) { 8619 const PetscReal invDet = 1.0/(*detJ); 8620 8621 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8622 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8623 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8624 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8625 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8626 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8627 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8628 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8629 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8630 PetscLogFlops(37.0); 8631 } 8632 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8633 PetscFunctionReturn(0); 8634 } 8635 8636 #undef __FUNCT__ 8637 #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8638 PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8639 { 8640 PetscSection coordSection; 8641 Vec coordinates; 8642 const PetscScalar *coords; 8643 const PetscInt dim = 3; 8644 PetscInt d; 8645 PetscErrorCode ierr; 8646 8647 PetscFunctionBegin; 8648 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8649 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8650 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8651 if (v0) { 8652 for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]); 8653 } 8654 if (J) { 8655 for (d = 0; d < dim; d++) { 8656 J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8657 J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8658 J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8659 } 8660 *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8661 J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8662 J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8663 PetscLogFlops(18.0 + 12.0); 8664 } 8665 if (invJ) { 8666 const PetscReal invDet = -1.0/(*detJ); 8667 8668 invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8669 invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8670 invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8671 invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8672 invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8673 invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8674 invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8675 invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8676 invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8677 PetscLogFlops(37.0); 8678 } 8679 *detJ *= 8.0; 8680 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 8681 PetscFunctionReturn(0); 8682 } 8683 8684 #undef __FUNCT__ 8685 #define __FUNCT__ "DMPlexComputeCellGeometry" 8686 /*@C 8687 DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8688 8689 Collective on DM 8690 8691 Input Arguments: 8692 + dm - the DM 8693 - cell - the cell 8694 8695 Output Arguments: 8696 + v0 - the translation part of this affine transform 8697 . J - the Jacobian of the transform to the reference element 8698 . invJ - the inverse of the Jacobian 8699 - detJ - the Jacobian determinant 8700 8701 Level: advanced 8702 8703 .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8704 @*/ 8705 PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 8706 { 8707 PetscInt dim, coneSize; 8708 PetscErrorCode ierr; 8709 8710 PetscFunctionBegin; 8711 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8712 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8713 switch (dim) { 8714 case 2: 8715 switch (coneSize) { 8716 case 3: 8717 ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8718 break; 8719 case 4: 8720 ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8721 break; 8722 default: 8723 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8724 } 8725 break; 8726 case 3: 8727 switch (coneSize) { 8728 case 4: 8729 ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8730 break; 8731 case 8: 8732 ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8733 break; 8734 default: 8735 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 8736 } 8737 break; 8738 default: 8739 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8740 } 8741 PetscFunctionReturn(0); 8742 } 8743 8744 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 8745 { 8746 switch (i) { 8747 case 0: 8748 switch (j) { 8749 case 0: return 0; 8750 case 1: 8751 switch (k) { 8752 case 0: return 0; 8753 case 1: return 0; 8754 case 2: return 1; 8755 } 8756 case 2: 8757 switch (k) { 8758 case 0: return 0; 8759 case 1: return -1; 8760 case 2: return 0; 8761 } 8762 } 8763 case 1: 8764 switch (j) { 8765 case 0: 8766 switch (k) { 8767 case 0: return 0; 8768 case 1: return 0; 8769 case 2: return -1; 8770 } 8771 case 1: return 0; 8772 case 2: 8773 switch (k) { 8774 case 0: return 1; 8775 case 1: return 0; 8776 case 2: return 0; 8777 } 8778 } 8779 case 2: 8780 switch (j) { 8781 case 0: 8782 switch (k) { 8783 case 0: return 0; 8784 case 1: return 1; 8785 case 2: return 0; 8786 } 8787 case 1: 8788 switch (k) { 8789 case 0: return -1; 8790 case 1: return 0; 8791 case 2: return 0; 8792 } 8793 case 2: return 0; 8794 } 8795 } 8796 return 0; 8797 } 8798 8799 #undef __FUNCT__ 8800 #define __FUNCT__ "DMPlexCreateRigidBody" 8801 /*@C 8802 DMPlexCreateRigidBody - create rigid body modes from coordinates 8803 8804 Collective on DM 8805 8806 Input Arguments: 8807 + dm - the DM 8808 . section - the local section associated with the rigid field, or NULL for the default section 8809 - globalSection - the global section associated with the rigid field, or NULL for the default section 8810 8811 Output Argument: 8812 . sp - the null space 8813 8814 Note: This is necessary to take account of Dirichlet conditions on the displacements 8815 8816 Level: advanced 8817 8818 .seealso: MatNullSpaceCreate() 8819 @*/ 8820 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 8821 { 8822 MPI_Comm comm; 8823 Vec coordinates, localMode, mode[6]; 8824 PetscSection coordSection; 8825 PetscScalar *coords; 8826 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 8827 PetscErrorCode ierr; 8828 8829 PetscFunctionBegin; 8830 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 8831 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8832 if (dim == 1) { 8833 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 8834 PetscFunctionReturn(0); 8835 } 8836 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 8837 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 8838 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 8839 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8840 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8841 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8842 m = (dim*(dim+1))/2; 8843 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 8844 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 8845 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 8846 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 8847 /* Assume P1 */ 8848 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 8849 for (d = 0; d < dim; ++d) { 8850 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8851 8852 values[d] = 1.0; 8853 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8854 for (v = vStart; v < vEnd; ++v) { 8855 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8856 } 8857 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8858 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8859 } 8860 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 8861 for (d = dim; d < dim*(dim+1)/2; ++d) { 8862 PetscInt i, j, k = dim > 2 ? d - dim : d; 8863 8864 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8865 for (v = vStart; v < vEnd; ++v) { 8866 PetscScalar values[3] = {0.0, 0.0, 0.0}; 8867 PetscInt off; 8868 8869 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 8870 for (i = 0; i < dim; ++i) { 8871 for (j = 0; j < dim; ++j) { 8872 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 8873 } 8874 } 8875 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8876 } 8877 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8878 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8879 } 8880 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 8881 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 8882 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 8883 /* Orthonormalize system */ 8884 for (i = dim; i < m; ++i) { 8885 PetscScalar dots[6]; 8886 8887 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 8888 for (j = 0; j < i; ++j) dots[j] *= -1.0; 8889 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 8890 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 8891 } 8892 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 8893 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 8894 PetscFunctionReturn(0); 8895 } 8896 8897 #undef __FUNCT__ 8898 #define __FUNCT__ "DMPlexGetHybridBounds" 8899 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 8900 { 8901 DM_Plex *mesh = (DM_Plex*) dm->data; 8902 PetscInt dim; 8903 PetscErrorCode ierr; 8904 8905 PetscFunctionBegin; 8906 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8907 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8908 if (cMax) *cMax = mesh->hybridPointMax[dim]; 8909 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 8910 if (eMax) *eMax = mesh->hybridPointMax[1]; 8911 if (vMax) *vMax = mesh->hybridPointMax[0]; 8912 PetscFunctionReturn(0); 8913 } 8914 8915 #undef __FUNCT__ 8916 #define __FUNCT__ "DMPlexSetHybridBounds" 8917 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 8918 { 8919 DM_Plex *mesh = (DM_Plex*) dm->data; 8920 PetscInt dim; 8921 PetscErrorCode ierr; 8922 8923 PetscFunctionBegin; 8924 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8925 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8926 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 8927 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 8928 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 8929 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 8930 PetscFunctionReturn(0); 8931 } 8932 8933 #undef __FUNCT__ 8934 #define __FUNCT__ "DMPlexGetVTKCellHeight" 8935 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8936 { 8937 DM_Plex *mesh = (DM_Plex*) dm->data; 8938 8939 PetscFunctionBegin; 8940 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8941 PetscValidPointer(cellHeight, 2); 8942 *cellHeight = mesh->vtkCellHeight; 8943 PetscFunctionReturn(0); 8944 } 8945 8946 #undef __FUNCT__ 8947 #define __FUNCT__ "DMPlexSetVTKCellHeight" 8948 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8949 { 8950 DM_Plex *mesh = (DM_Plex*) dm->data; 8951 8952 PetscFunctionBegin; 8953 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8954 mesh->vtkCellHeight = cellHeight; 8955 PetscFunctionReturn(0); 8956 } 8957 8958 #undef __FUNCT__ 8959 #define __FUNCT__ "DMPlexCreateNumbering_Private" 8960 /* We can easily have a form that takes an IS instead */ 8961 PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 8962 { 8963 PetscSection section, globalSection; 8964 PetscInt *numbers, p; 8965 PetscErrorCode ierr; 8966 8967 PetscFunctionBegin; 8968 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 8969 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 8970 for (p = pStart; p < pEnd; ++p) { 8971 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 8972 } 8973 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 8974 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 8975 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 8976 for (p = pStart; p < pEnd; ++p) { 8977 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 8978 } 8979 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 8980 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 8981 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8982 PetscFunctionReturn(0); 8983 } 8984 8985 #undef __FUNCT__ 8986 #define __FUNCT__ "DMPlexGetCellNumbering" 8987 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8988 { 8989 DM_Plex *mesh = (DM_Plex*) dm->data; 8990 PetscInt cellHeight, cStart, cEnd, cMax; 8991 PetscErrorCode ierr; 8992 8993 PetscFunctionBegin; 8994 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8995 if (!mesh->globalCellNumbers) { 8996 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 8997 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 8998 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 8999 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 9000 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9001 } 9002 *globalCellNumbers = mesh->globalCellNumbers; 9003 PetscFunctionReturn(0); 9004 } 9005 9006 #undef __FUNCT__ 9007 #define __FUNCT__ "DMPlexGetVertexNumbering" 9008 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9009 { 9010 DM_Plex *mesh = (DM_Plex*) dm->data; 9011 PetscInt vStart, vEnd, vMax; 9012 PetscErrorCode ierr; 9013 9014 PetscFunctionBegin; 9015 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9016 if (!mesh->globalVertexNumbers) { 9017 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9018 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 9019 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 9020 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9021 } 9022 *globalVertexNumbers = mesh->globalVertexNumbers; 9023 PetscFunctionReturn(0); 9024 } 9025 9026 #undef __FUNCT__ 9027 #define __FUNCT__ "DMPlexGetScale" 9028 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9029 { 9030 DM_Plex *mesh = (DM_Plex*) dm->data; 9031 9032 PetscFunctionBegin; 9033 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9034 PetscValidPointer(scale, 3); 9035 *scale = mesh->scale[unit]; 9036 PetscFunctionReturn(0); 9037 } 9038 9039 #undef __FUNCT__ 9040 #define __FUNCT__ "DMPlexSetScale" 9041 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9042 { 9043 DM_Plex *mesh = (DM_Plex*) dm->data; 9044 9045 PetscFunctionBegin; 9046 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9047 mesh->scale[unit] = scale; 9048 PetscFunctionReturn(0); 9049 } 9050 9051 9052 /******************************************************************************* 9053 This should be in a separate Discretization object, but I am not sure how to lay 9054 it out yet, so I am stuffing things here while I experiment. 9055 *******************************************************************************/ 9056 #undef __FUNCT__ 9057 #define __FUNCT__ "DMPlexSetFEMIntegration" 9058 PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9059 PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9060 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9061 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9062 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9063 PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9064 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9065 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9066 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9067 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9068 void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9069 PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9070 const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9071 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9072 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9073 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9074 void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9075 { 9076 DM_Plex *mesh = (DM_Plex*) dm->data; 9077 9078 PetscFunctionBegin; 9079 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9080 mesh->integrateResidualFEM = integrateResidualFEM; 9081 mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9082 mesh->integrateJacobianFEM = integrateJacobianFEM; 9083 PetscFunctionReturn(0); 9084 } 9085 9086 #undef __FUNCT__ 9087 #define __FUNCT__ "DMPlexProjectFunctionLocal" 9088 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9089 { 9090 Vec coordinates; 9091 PetscSection section, cSection; 9092 PetscInt dim, vStart, vEnd, v, c, d; 9093 PetscScalar *values, *cArray; 9094 PetscReal *coords; 9095 PetscErrorCode ierr; 9096 9097 PetscFunctionBegin; 9098 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9099 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9100 ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9101 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9102 ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9103 ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9104 ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9105 ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9106 for (v = vStart; v < vEnd; ++v) { 9107 PetscInt dof, off; 9108 9109 ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9110 ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9111 if (dof > dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9112 for (d = 0; d < dof; ++d) coords[d] = PetscRealPart(cArray[off+d]); 9113 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9114 ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9115 } 9116 ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9117 /* Temporary, must be replaced by a projection on the finite element basis */ 9118 { 9119 PetscInt eStart = 0, eEnd = 0, e, depth; 9120 9121 ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9122 --depth; 9123 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9124 for (e = eStart; e < eEnd; ++e) { 9125 const PetscInt *cone = NULL; 9126 PetscInt coneSize, d; 9127 PetscScalar *coordsA, *coordsB; 9128 9129 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9130 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9131 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9132 ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9133 ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9134 for (d = 0; d < dim; ++d) { 9135 coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9136 } 9137 for (c = 0; c < numComp; ++c) values[c] = (*funcs[c])(coords); 9138 ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9139 } 9140 } 9141 9142 ierr = PetscFree(coords);CHKERRQ(ierr); 9143 ierr = PetscFree(values);CHKERRQ(ierr); 9144 #if 0 9145 const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9146 PetscReal detJ; 9147 9148 ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9149 ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9150 ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV(PetscPowInt(this->_mesh->getSieve()->getMaxConeSize(),dim+1), true); 9151 9152 for (PetscInt c = cStart; c < cEnd; ++c) { 9153 ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9154 const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9155 const int oSize = pV.getSize(); 9156 int v = 0; 9157 9158 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, NULL, &detJ);CHKERRQ(ierr); 9159 for (PetscInt cl = 0; cl < oSize; ++cl) { 9160 const PetscInt fDim; 9161 9162 ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9163 if (pointDim) { 9164 for (PetscInt d = 0; d < fDim; ++d, ++v) { 9165 values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9166 } 9167 } 9168 } 9169 ierr = DMPlexVecSetClosure(dm, NULL, localX, c, values);CHKERRQ(ierr); 9170 pV.clear(); 9171 } 9172 ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9173 ierr = PetscFree(values);CHKERRQ(ierr); 9174 #endif 9175 PetscFunctionReturn(0); 9176 } 9177 9178 #undef __FUNCT__ 9179 #define __FUNCT__ "DMPlexProjectFunction" 9180 /*@C 9181 DMPlexProjectFunction - This projects the given function into the function space provided. 9182 9183 Input Parameters: 9184 + dm - The DM 9185 . numComp - The number of components (functions) 9186 . funcs - The coordinate functions to evaluate 9187 - mode - The insertion mode for values 9188 9189 Output Parameter: 9190 . X - vector 9191 9192 Level: developer 9193 9194 Note: 9195 This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9196 We will eventually fix it. 9197 9198 ,seealso: DMPlexComputeL2Diff() 9199 */ 9200 PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9201 { 9202 Vec localX; 9203 PetscErrorCode ierr; 9204 9205 PetscFunctionBegin; 9206 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9207 ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9208 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9209 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9210 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9211 PetscFunctionReturn(0); 9212 } 9213 9214 #undef __FUNCT__ 9215 #define __FUNCT__ "DMPlexComputeL2Diff" 9216 /*@C 9217 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9218 9219 Input Parameters: 9220 + dm - The DM 9221 . quad - The PetscQuadrature object for each field 9222 . funcs - The functions to evaluate for each field component 9223 - X - The coefficient vector u_h 9224 9225 Output Parameter: 9226 . diff - The diff ||u - u_h||_2 9227 9228 Level: developer 9229 9230 .seealso: DMPlexProjectFunction() 9231 */ 9232 PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) 9233 { 9234 const PetscInt debug = 0; 9235 PetscSection section; 9236 Vec localX; 9237 PetscReal *coords, *v0, *J, *invJ, detJ; 9238 PetscReal localDiff = 0.0; 9239 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9240 PetscErrorCode ierr; 9241 9242 PetscFunctionBegin; 9243 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9244 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9245 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9246 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9247 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9248 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9249 for (field = 0; field < numFields; ++field) { 9250 numComponents += quad[field].numComponents; 9251 } 9252 ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9253 ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9254 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9255 for (c = cStart; c < cEnd; ++c) { 9256 const PetscScalar *x; 9257 PetscReal elemDiff = 0.0; 9258 9259 ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9260 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9261 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9262 9263 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9264 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9265 const PetscReal *quadPoints = quad[field].quadPoints; 9266 const PetscReal *quadWeights = quad[field].quadWeights; 9267 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9268 const PetscInt numBasisComps = quad[field].numComponents; 9269 const PetscReal *basis = quad[field].basis; 9270 PetscInt q, d, e, fc, f; 9271 9272 if (debug) { 9273 char title[1024]; 9274 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9275 ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9276 } 9277 for (q = 0; q < numQuadPoints; ++q) { 9278 for (d = 0; d < dim; d++) { 9279 coords[d] = v0[d]; 9280 for (e = 0; e < dim; e++) { 9281 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9282 } 9283 } 9284 for (fc = 0; fc < numBasisComps; ++fc) { 9285 const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9286 PetscReal interpolant = 0.0; 9287 for (f = 0; f < numBasisFuncs; ++f) { 9288 const PetscInt fidx = f*numBasisComps+fc; 9289 interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9290 } 9291 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9292 elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9293 } 9294 } 9295 comp += numBasisComps; 9296 fieldOffset += numBasisFuncs*numBasisComps; 9297 } 9298 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 9299 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9300 localDiff += elemDiff; 9301 } 9302 ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9303 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9304 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9305 *diff = PetscSqrtReal(*diff); 9306 PetscFunctionReturn(0); 9307 } 9308 9309 #undef __FUNCT__ 9310 #define __FUNCT__ "DMPlexComputeResidualFEM" 9311 /*@ 9312 DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9313 9314 Input Parameters: 9315 + dm - The mesh 9316 . X - Local input vector 9317 - user - The user context 9318 9319 Output Parameter: 9320 . F - Local output vector 9321 9322 Note: 9323 The second member of the user context must be an FEMContext. 9324 9325 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9326 like a GPU, or vectorize on a multicore machine. 9327 9328 .seealso: DMPlexComputeJacobianActionFEM() 9329 */ 9330 PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9331 { 9332 DM_Plex *mesh = (DM_Plex*) dm->data; 9333 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9334 PetscQuadrature *quad = fem->quad; 9335 PetscSection section; 9336 PetscReal *v0, *J, *invJ, *detJ; 9337 PetscScalar *elemVec, *u; 9338 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9339 PetscInt cellDof = 0, numComponents = 0; 9340 PetscErrorCode ierr; 9341 9342 PetscFunctionBegin; 9343 /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9344 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9345 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9346 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9347 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9348 numCells = cEnd - cStart; 9349 for (field = 0; field < numFields; ++field) { 9350 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9351 numComponents += quad[field].numComponents; 9352 } 9353 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9354 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9355 ierr = PetscMalloc6(numCells*cellDof,PetscScalar,&u,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof,PetscScalar,&elemVec);CHKERRQ(ierr); 9356 for (c = cStart; c < cEnd; ++c) { 9357 const PetscScalar *x; 9358 PetscInt i; 9359 9360 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9361 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9362 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9363 9364 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9365 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9366 } 9367 for (field = 0; field < numFields; ++field) { 9368 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9369 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9370 void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9371 void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9372 /* Conforming batches */ 9373 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9374 PetscInt numBlocks = 1; 9375 PetscInt batchSize = numBlocks * blockSize; 9376 PetscInt numBatches = numBatchesTmp; 9377 PetscInt numChunks = numCells / (numBatches*batchSize); 9378 /* Remainder */ 9379 PetscInt numRemainder = numCells % (numBatches * batchSize); 9380 PetscInt offset = numCells - numRemainder; 9381 9382 ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9383 ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9384 f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9385 } 9386 for (c = cStart; c < cEnd; ++c) { 9387 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9388 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9389 } 9390 ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9391 if (mesh->printFEM) { 9392 PetscMPIInt rank, numProcs; 9393 PetscInt p; 9394 9395 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9396 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9397 ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9398 for (p = 0; p < numProcs; ++p) { 9399 if (p == rank) { 9400 Vec f; 9401 9402 ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9403 ierr = VecCopy(F, f);CHKERRQ(ierr); 9404 ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9405 ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9406 ierr = VecDestroy(&f);CHKERRQ(ierr); 9407 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9408 } 9409 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9410 } 9411 } 9412 /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9413 PetscFunctionReturn(0); 9414 } 9415 9416 #undef __FUNCT__ 9417 #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9418 /*@C 9419 DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9420 9421 Input Parameters: 9422 + dm - The mesh 9423 . J - The Jacobian shell matrix 9424 . X - Local input vector 9425 - user - The user context 9426 9427 Output Parameter: 9428 . F - Local output vector 9429 9430 Note: 9431 The second member of the user context must be an FEMContext. 9432 9433 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9434 like a GPU, or vectorize on a multicore machine. 9435 9436 .seealso: DMPlexComputeResidualFEM() 9437 */ 9438 PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9439 { 9440 DM_Plex *mesh = (DM_Plex*) dm->data; 9441 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9442 PetscQuadrature *quad = fem->quad; 9443 PetscSection section; 9444 JacActionCtx *jctx; 9445 PetscReal *v0, *J, *invJ, *detJ; 9446 PetscScalar *elemVec, *u, *a; 9447 PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9448 PetscInt cellDof = 0; 9449 PetscErrorCode ierr; 9450 9451 PetscFunctionBegin; 9452 /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9453 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9454 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9455 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9456 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9457 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9458 numCells = cEnd - cStart; 9459 for (field = 0; field < numFields; ++field) { 9460 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9461 } 9462 ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9463 ierr = PetscMalloc7(numCells*cellDof,PetscScalar,&u,numCells*cellDof,PetscScalar,&a,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof,PetscScalar,&elemVec);CHKERRQ(ierr); 9464 for (c = cStart; c < cEnd; ++c) { 9465 const PetscScalar *x; 9466 PetscInt i; 9467 9468 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9469 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9470 ierr = DMPlexVecGetClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9471 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9472 ierr = DMPlexVecRestoreClosure(dm, NULL, jctx->u, c, NULL, &x);CHKERRQ(ierr); 9473 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9474 for (i = 0; i < cellDof; ++i) a[c*cellDof+i] = x[i]; 9475 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9476 } 9477 for (field = 0; field < numFields; ++field) { 9478 const PetscInt numQuadPoints = quad[field].numQuadPoints; 9479 const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9480 /* Conforming batches */ 9481 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9482 PetscInt numBlocks = 1; 9483 PetscInt batchSize = numBlocks * blockSize; 9484 PetscInt numBatches = numBatchesTmp; 9485 PetscInt numChunks = numCells / (numBatches*batchSize); 9486 /* Remainder */ 9487 PetscInt numRemainder = numCells % (numBatches * batchSize); 9488 PetscInt offset = numCells - numRemainder; 9489 9490 ierr = (*mesh->integrateJacobianActionFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, a, v0, J, invJ, detJ, fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, elemVec);CHKERRQ(ierr); 9491 ierr = (*mesh->integrateJacobianActionFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &a[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9492 fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9493 } 9494 for (c = cStart; c < cEnd; ++c) { 9495 if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9496 ierr = DMPlexVecSetClosure(dm, NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9497 } 9498 ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9499 if (mesh->printFEM) { 9500 PetscMPIInt rank, numProcs; 9501 PetscInt p; 9502 9503 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 9504 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &numProcs);CHKERRQ(ierr); 9505 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9506 for (p = 0; p < numProcs; ++p) { 9507 if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9508 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9509 } 9510 } 9511 /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9512 PetscFunctionReturn(0); 9513 } 9514 9515 #undef __FUNCT__ 9516 #define __FUNCT__ "DMPlexComputeJacobianFEM" 9517 /*@ 9518 DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9519 9520 Input Parameters: 9521 + dm - The mesh 9522 . X - Local input vector 9523 - user - The user context 9524 9525 Output Parameter: 9526 . Jac - Jacobian matrix 9527 9528 Note: 9529 The second member of the user context must be an FEMContext. 9530 9531 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9532 like a GPU, or vectorize on a multicore machine. 9533 9534 .seealso: FormFunctionLocal() 9535 */ 9536 PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9537 { 9538 DM_Plex *mesh = (DM_Plex*) dm->data; 9539 PetscFEM *fem = (PetscFEM*) &((DM*) user)[1]; 9540 PetscQuadrature *quad = fem->quad; 9541 PetscSection section; 9542 PetscReal *v0, *J, *invJ, *detJ; 9543 PetscScalar *elemMat, *u; 9544 PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9545 PetscInt cellDof = 0, numComponents = 0; 9546 PetscBool isShell; 9547 PetscErrorCode ierr; 9548 9549 PetscFunctionBegin; 9550 /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9551 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9552 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9553 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9554 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9555 numCells = cEnd - cStart; 9556 for (field = 0; field < numFields; ++field) { 9557 cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9558 numComponents += quad[field].numComponents; 9559 } 9560 ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9561 ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 9562 ierr = PetscMalloc6(numCells*cellDof,PetscScalar,&u,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof*cellDof,PetscScalar,&elemMat);CHKERRQ(ierr); 9563 for (c = cStart; c < cEnd; ++c) { 9564 const PetscScalar *x; 9565 PetscInt i; 9566 9567 ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9568 if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9569 ierr = DMPlexVecGetClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9570 9571 for (i = 0; i < cellDof; ++i) u[c*cellDof+i] = x[i]; 9572 ierr = DMPlexVecRestoreClosure(dm, NULL, X, c, NULL, &x);CHKERRQ(ierr); 9573 } 9574 ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 9575 for (fieldI = 0; fieldI < numFields; ++fieldI) { 9576 const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 9577 const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 9578 PetscInt fieldJ; 9579 9580 for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 9581 void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 9582 void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 9583 void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 9584 void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 9585 /* Conforming batches */ 9586 PetscInt blockSize = numBasisFuncs*numQuadPoints; 9587 PetscInt numBlocks = 1; 9588 PetscInt batchSize = numBlocks * blockSize; 9589 PetscInt numBatches = numBatchesTmp; 9590 PetscInt numChunks = numCells / (numBatches*batchSize); 9591 /* Remainder */ 9592 PetscInt numRemainder = numCells % (numBatches * batchSize); 9593 PetscInt offset = numCells - numRemainder; 9594 9595 ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 9596 ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9597 g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 9598 } 9599 } 9600 for (c = cStart; c < cEnd; ++c) { 9601 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 9602 ierr = DMPlexMatSetClosure(dm, NULL, NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 9603 } 9604 ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 9605 9606 /* Assemble matrix, using the 2-step process: 9607 MatAssemblyBegin(), MatAssemblyEnd(). */ 9608 ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9609 ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9610 9611 if (mesh->printFEM) { 9612 ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 9613 ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 9614 ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 9615 } 9616 /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9617 ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 9618 if (isShell) { 9619 JacActionCtx *jctx; 9620 9621 ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9622 ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 9623 } 9624 *str = SAME_NONZERO_PATTERN; 9625 PetscFunctionReturn(0); 9626 } 9627 9628 9629 #undef __FUNCT__ 9630 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 9631 /*@C 9632 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 9633 the local section and an SF describing the section point overlap. 9634 9635 Input Parameters: 9636 + s - The PetscSection for the local field layout 9637 . sf - The SF describing parallel layout of the section points 9638 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 9639 . label - The label specifying the points 9640 - labelValue - The label stratum specifying the points 9641 9642 Output Parameter: 9643 . gsection - The PetscSection for the global field layout 9644 9645 Note: This gives negative sizes and offsets to points not owned by this process 9646 9647 Level: developer 9648 9649 .seealso: PetscSectionCreate() 9650 @*/ 9651 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 9652 { 9653 PetscInt *neg; 9654 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 9655 PetscErrorCode ierr; 9656 9657 PetscFunctionBegin; 9658 ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 9659 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 9660 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 9661 ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 9662 /* Mark ghost points with negative dof */ 9663 for (p = pStart; p < pEnd; ++p) { 9664 PetscInt value; 9665 9666 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 9667 if (value != labelValue) continue; 9668 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 9669 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 9670 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 9671 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 9672 neg[p-pStart] = -(dof+1); 9673 } 9674 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 9675 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 9676 if (nroots >= 0) { 9677 if (nroots > pEnd - pStart) { 9678 PetscInt *tmpDof; 9679 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9680 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 9681 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9682 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9683 for (p = pStart; p < pEnd; ++p) { 9684 if (tmpDof[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpDof[p]; 9685 } 9686 ierr = PetscFree(tmpDof);CHKERRQ(ierr); 9687 } else { 9688 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9689 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9690 } 9691 } 9692 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 9693 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9694 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 9695 9696 (*gsection)->atlasOff[p] = off; 9697 9698 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 9699 } 9700 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 9701 globalOff -= off; 9702 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9703 (*gsection)->atlasOff[p] += globalOff; 9704 9705 neg[p] = -((*gsection)->atlasOff[p]+1); 9706 } 9707 /* Put in negative offsets for ghost points */ 9708 if (nroots >= 0) { 9709 if (nroots > pEnd - pStart) { 9710 PetscInt *tmpOff; 9711 /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9712 ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 9713 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9714 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9715 for (p = pStart; p < pEnd; ++p) { 9716 if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p]; 9717 } 9718 ierr = PetscFree(tmpOff);CHKERRQ(ierr); 9719 } else { 9720 ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9721 ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9722 } 9723 } 9724 ierr = PetscFree(neg);CHKERRQ(ierr); 9725 PetscFunctionReturn(0); 9726 } 9727