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