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