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