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