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