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