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