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