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