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