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