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