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