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