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