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 Not collective 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 ierr = DMLabelGetState(label, &mesh->depthState);CHKERRQ(ierr); 1944 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 1945 PetscFunctionReturn(0); 1946 } 1947 1948 #undef __FUNCT__ 1949 #define __FUNCT__ "DMPlexGetJoin" 1950 /*@C 1951 DMPlexGetJoin - Get an array for the join of the set of points 1952 1953 Not Collective 1954 1955 Input Parameters: 1956 + dm - The DMPlex object 1957 . numPoints - The number of input points for the join 1958 - points - The input points 1959 1960 Output Parameters: 1961 + numCoveredPoints - The number of points in the join 1962 - coveredPoints - The points in the join 1963 1964 Level: intermediate 1965 1966 Note: Currently, this is restricted to a single level join 1967 1968 Fortran Notes: 1969 Since it returns an array, this routine is only available in Fortran 90, and you must 1970 include petsc.h90 in your code. 1971 1972 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1973 1974 .keywords: mesh 1975 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 1976 @*/ 1977 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 1978 { 1979 DM_Plex *mesh = (DM_Plex*) dm->data; 1980 PetscInt *join[2]; 1981 PetscInt joinSize, i = 0; 1982 PetscInt dof, off, p, c, m; 1983 PetscErrorCode ierr; 1984 1985 PetscFunctionBegin; 1986 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1987 PetscValidPointer(points, 2); 1988 PetscValidPointer(numCoveredPoints, 3); 1989 PetscValidPointer(coveredPoints, 4); 1990 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 1991 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 1992 /* Copy in support of first point */ 1993 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 1994 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 1995 for (joinSize = 0; joinSize < dof; ++joinSize) { 1996 join[i][joinSize] = mesh->supports[off+joinSize]; 1997 } 1998 /* Check each successive support */ 1999 for (p = 1; p < numPoints; ++p) { 2000 PetscInt newJoinSize = 0; 2001 2002 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2003 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2004 for (c = 0; c < dof; ++c) { 2005 const PetscInt point = mesh->supports[off+c]; 2006 2007 for (m = 0; m < joinSize; ++m) { 2008 if (point == join[i][m]) { 2009 join[1-i][newJoinSize++] = point; 2010 break; 2011 } 2012 } 2013 } 2014 joinSize = newJoinSize; 2015 i = 1-i; 2016 } 2017 *numCoveredPoints = joinSize; 2018 *coveredPoints = join[i]; 2019 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2020 PetscFunctionReturn(0); 2021 } 2022 2023 #undef __FUNCT__ 2024 #define __FUNCT__ "DMPlexRestoreJoin" 2025 /*@C 2026 DMPlexRestoreJoin - Restore an array for the join of the set of points 2027 2028 Not Collective 2029 2030 Input Parameters: 2031 + dm - The DMPlex object 2032 . numPoints - The number of input points for the join 2033 - points - The input points 2034 2035 Output Parameters: 2036 + numCoveredPoints - The number of points in the join 2037 - coveredPoints - The points in the join 2038 2039 Fortran Notes: 2040 Since it returns an array, this routine is only available in Fortran 90, and you must 2041 include petsc.h90 in your code. 2042 2043 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2044 2045 Level: intermediate 2046 2047 .keywords: mesh 2048 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2049 @*/ 2050 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2051 { 2052 PetscErrorCode ierr; 2053 2054 PetscFunctionBegin; 2055 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2056 if (points) PetscValidIntPointer(points,3); 2057 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2058 PetscValidPointer(coveredPoints, 5); 2059 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2060 if (numCoveredPoints) *numCoveredPoints = 0; 2061 PetscFunctionReturn(0); 2062 } 2063 2064 #undef __FUNCT__ 2065 #define __FUNCT__ "DMPlexGetFullJoin" 2066 /*@C 2067 DMPlexGetFullJoin - Get an array for the join of the set of points 2068 2069 Not Collective 2070 2071 Input Parameters: 2072 + dm - The DMPlex object 2073 . numPoints - The number of input points for the join 2074 - points - The input points 2075 2076 Output Parameters: 2077 + numCoveredPoints - The number of points in the join 2078 - coveredPoints - The points in the join 2079 2080 Fortran Notes: 2081 Since it returns an array, this routine is only available in Fortran 90, and you must 2082 include petsc.h90 in your code. 2083 2084 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2085 2086 Level: intermediate 2087 2088 .keywords: mesh 2089 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2090 @*/ 2091 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2092 { 2093 DM_Plex *mesh = (DM_Plex*) dm->data; 2094 PetscInt *offsets, **closures; 2095 PetscInt *join[2]; 2096 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2097 PetscInt p, d, c, m, ms; 2098 PetscErrorCode ierr; 2099 2100 PetscFunctionBegin; 2101 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2102 PetscValidPointer(points, 2); 2103 PetscValidPointer(numCoveredPoints, 3); 2104 PetscValidPointer(coveredPoints, 4); 2105 2106 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2107 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 2108 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2109 ms = mesh->maxSupportSize; 2110 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 2111 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2112 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2113 2114 for (p = 0; p < numPoints; ++p) { 2115 PetscInt closureSize; 2116 2117 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2118 2119 offsets[p*(depth+2)+0] = 0; 2120 for (d = 0; d < depth+1; ++d) { 2121 PetscInt pStart, pEnd, i; 2122 2123 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2124 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2125 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2126 offsets[p*(depth+2)+d+1] = i; 2127 break; 2128 } 2129 } 2130 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2131 } 2132 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); 2133 } 2134 for (d = 0; d < depth+1; ++d) { 2135 PetscInt dof; 2136 2137 /* Copy in support of first point */ 2138 dof = offsets[d+1] - offsets[d]; 2139 for (joinSize = 0; joinSize < dof; ++joinSize) { 2140 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2141 } 2142 /* Check each successive cone */ 2143 for (p = 1; p < numPoints && joinSize; ++p) { 2144 PetscInt newJoinSize = 0; 2145 2146 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2147 for (c = 0; c < dof; ++c) { 2148 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2149 2150 for (m = 0; m < joinSize; ++m) { 2151 if (point == join[i][m]) { 2152 join[1-i][newJoinSize++] = point; 2153 break; 2154 } 2155 } 2156 } 2157 joinSize = newJoinSize; 2158 i = 1-i; 2159 } 2160 if (joinSize) break; 2161 } 2162 *numCoveredPoints = joinSize; 2163 *coveredPoints = join[i]; 2164 for (p = 0; p < numPoints; ++p) { 2165 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2166 } 2167 ierr = PetscFree(closures);CHKERRQ(ierr); 2168 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2169 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2170 PetscFunctionReturn(0); 2171 } 2172 2173 #undef __FUNCT__ 2174 #define __FUNCT__ "DMPlexGetMeet" 2175 /*@C 2176 DMPlexGetMeet - Get an array for the meet of the set of points 2177 2178 Not Collective 2179 2180 Input Parameters: 2181 + dm - The DMPlex object 2182 . numPoints - The number of input points for the meet 2183 - points - The input points 2184 2185 Output Parameters: 2186 + numCoveredPoints - The number of points in the meet 2187 - coveredPoints - The points in the meet 2188 2189 Level: intermediate 2190 2191 Note: Currently, this is restricted to a single level meet 2192 2193 Fortran Notes: 2194 Since it returns an array, this routine is only available in Fortran 90, and you must 2195 include petsc.h90 in your code. 2196 2197 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2198 2199 .keywords: mesh 2200 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2201 @*/ 2202 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2203 { 2204 DM_Plex *mesh = (DM_Plex*) dm->data; 2205 PetscInt *meet[2]; 2206 PetscInt meetSize, i = 0; 2207 PetscInt dof, off, p, c, m; 2208 PetscErrorCode ierr; 2209 2210 PetscFunctionBegin; 2211 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2212 PetscValidPointer(points, 2); 2213 PetscValidPointer(numCoveringPoints, 3); 2214 PetscValidPointer(coveringPoints, 4); 2215 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2216 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2217 /* Copy in cone of first point */ 2218 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2219 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2220 for (meetSize = 0; meetSize < dof; ++meetSize) { 2221 meet[i][meetSize] = mesh->cones[off+meetSize]; 2222 } 2223 /* Check each successive cone */ 2224 for (p = 1; p < numPoints; ++p) { 2225 PetscInt newMeetSize = 0; 2226 2227 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2228 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2229 for (c = 0; c < dof; ++c) { 2230 const PetscInt point = mesh->cones[off+c]; 2231 2232 for (m = 0; m < meetSize; ++m) { 2233 if (point == meet[i][m]) { 2234 meet[1-i][newMeetSize++] = point; 2235 break; 2236 } 2237 } 2238 } 2239 meetSize = newMeetSize; 2240 i = 1-i; 2241 } 2242 *numCoveringPoints = meetSize; 2243 *coveringPoints = meet[i]; 2244 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2245 PetscFunctionReturn(0); 2246 } 2247 2248 #undef __FUNCT__ 2249 #define __FUNCT__ "DMPlexRestoreMeet" 2250 /*@C 2251 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2252 2253 Not Collective 2254 2255 Input Parameters: 2256 + dm - The DMPlex object 2257 . numPoints - The number of input points for the meet 2258 - points - The input points 2259 2260 Output Parameters: 2261 + numCoveredPoints - The number of points in the meet 2262 - coveredPoints - The points in the meet 2263 2264 Level: intermediate 2265 2266 Fortran Notes: 2267 Since it returns an array, this routine is only available in Fortran 90, and you must 2268 include petsc.h90 in your code. 2269 2270 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2271 2272 .keywords: mesh 2273 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2274 @*/ 2275 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2276 { 2277 PetscErrorCode ierr; 2278 2279 PetscFunctionBegin; 2280 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2281 if (points) PetscValidIntPointer(points,3); 2282 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2283 PetscValidPointer(coveredPoints,5); 2284 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2285 if (numCoveredPoints) *numCoveredPoints = 0; 2286 PetscFunctionReturn(0); 2287 } 2288 2289 #undef __FUNCT__ 2290 #define __FUNCT__ "DMPlexGetFullMeet" 2291 /*@C 2292 DMPlexGetFullMeet - Get an array for the meet of the set of points 2293 2294 Not Collective 2295 2296 Input Parameters: 2297 + dm - The DMPlex object 2298 . numPoints - The number of input points for the meet 2299 - points - The input points 2300 2301 Output Parameters: 2302 + numCoveredPoints - The number of points in the meet 2303 - coveredPoints - The points in the meet 2304 2305 Level: intermediate 2306 2307 Fortran Notes: 2308 Since it returns an array, this routine is only available in Fortran 90, and you must 2309 include petsc.h90 in your code. 2310 2311 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2312 2313 .keywords: mesh 2314 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2315 @*/ 2316 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2317 { 2318 DM_Plex *mesh = (DM_Plex*) dm->data; 2319 PetscInt *offsets, **closures; 2320 PetscInt *meet[2]; 2321 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2322 PetscInt p, h, c, m, mc; 2323 PetscErrorCode ierr; 2324 2325 PetscFunctionBegin; 2326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2327 PetscValidPointer(points, 2); 2328 PetscValidPointer(numCoveredPoints, 3); 2329 PetscValidPointer(coveredPoints, 4); 2330 2331 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2332 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 2333 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2334 mc = mesh->maxConeSize; 2335 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 2336 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2337 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2338 2339 for (p = 0; p < numPoints; ++p) { 2340 PetscInt closureSize; 2341 2342 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2343 2344 offsets[p*(height+2)+0] = 0; 2345 for (h = 0; h < height+1; ++h) { 2346 PetscInt pStart, pEnd, i; 2347 2348 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2349 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2350 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2351 offsets[p*(height+2)+h+1] = i; 2352 break; 2353 } 2354 } 2355 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2356 } 2357 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); 2358 } 2359 for (h = 0; h < height+1; ++h) { 2360 PetscInt dof; 2361 2362 /* Copy in cone of first point */ 2363 dof = offsets[h+1] - offsets[h]; 2364 for (meetSize = 0; meetSize < dof; ++meetSize) { 2365 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2366 } 2367 /* Check each successive cone */ 2368 for (p = 1; p < numPoints && meetSize; ++p) { 2369 PetscInt newMeetSize = 0; 2370 2371 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2372 for (c = 0; c < dof; ++c) { 2373 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2374 2375 for (m = 0; m < meetSize; ++m) { 2376 if (point == meet[i][m]) { 2377 meet[1-i][newMeetSize++] = point; 2378 break; 2379 } 2380 } 2381 } 2382 meetSize = newMeetSize; 2383 i = 1-i; 2384 } 2385 if (meetSize) break; 2386 } 2387 *numCoveredPoints = meetSize; 2388 *coveredPoints = meet[i]; 2389 for (p = 0; p < numPoints; ++p) { 2390 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2391 } 2392 ierr = PetscFree(closures);CHKERRQ(ierr); 2393 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2394 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2395 PetscFunctionReturn(0); 2396 } 2397 2398 #undef __FUNCT__ 2399 #define __FUNCT__ "DMPlexEqual" 2400 /*@C 2401 DMPlexEqual - Determine if two DMs have the same topology 2402 2403 Not Collective 2404 2405 Input Parameters: 2406 + dmA - A DMPlex object 2407 - dmB - A DMPlex object 2408 2409 Output Parameters: 2410 . equal - PETSC_TRUE if the topologies are identical 2411 2412 Level: intermediate 2413 2414 Notes: 2415 We are not solving graph isomorphism, so we do not permutation. 2416 2417 .keywords: mesh 2418 .seealso: DMPlexGetCone() 2419 @*/ 2420 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 2421 { 2422 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 2423 PetscErrorCode ierr; 2424 2425 PetscFunctionBegin; 2426 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 2427 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 2428 PetscValidPointer(equal, 3); 2429 2430 *equal = PETSC_FALSE; 2431 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 2432 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 2433 if (depth != depthB) PetscFunctionReturn(0); 2434 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 2435 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 2436 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 2437 for (p = pStart; p < pEnd; ++p) { 2438 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 2439 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 2440 2441 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 2442 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 2443 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 2444 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 2445 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 2446 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 2447 if (coneSize != coneSizeB) PetscFunctionReturn(0); 2448 for (c = 0; c < coneSize; ++c) { 2449 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 2450 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 2451 } 2452 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 2453 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 2454 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 2455 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 2456 if (supportSize != supportSizeB) PetscFunctionReturn(0); 2457 for (s = 0; s < supportSize; ++s) { 2458 if (support[s] != supportB[s]) PetscFunctionReturn(0); 2459 } 2460 } 2461 *equal = PETSC_TRUE; 2462 PetscFunctionReturn(0); 2463 } 2464 2465 #undef __FUNCT__ 2466 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2467 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 2468 { 2469 MPI_Comm comm; 2470 PetscErrorCode ierr; 2471 2472 PetscFunctionBegin; 2473 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2474 PetscValidPointer(numFaceVertices,3); 2475 switch (cellDim) { 2476 case 0: 2477 *numFaceVertices = 0; 2478 break; 2479 case 1: 2480 *numFaceVertices = 1; 2481 break; 2482 case 2: 2483 switch (numCorners) { 2484 case 3: /* triangle */ 2485 *numFaceVertices = 2; /* Edge has 2 vertices */ 2486 break; 2487 case 4: /* quadrilateral */ 2488 *numFaceVertices = 2; /* Edge has 2 vertices */ 2489 break; 2490 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2491 *numFaceVertices = 3; /* Edge has 3 vertices */ 2492 break; 2493 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2494 *numFaceVertices = 3; /* Edge has 3 vertices */ 2495 break; 2496 default: 2497 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 2498 } 2499 break; 2500 case 3: 2501 switch (numCorners) { 2502 case 4: /* tetradehdron */ 2503 *numFaceVertices = 3; /* Face has 3 vertices */ 2504 break; 2505 case 6: /* tet cohesive cells */ 2506 *numFaceVertices = 4; /* Face has 4 vertices */ 2507 break; 2508 case 8: /* hexahedron */ 2509 *numFaceVertices = 4; /* Face has 4 vertices */ 2510 break; 2511 case 9: /* tet cohesive Lagrange cells */ 2512 *numFaceVertices = 6; /* Face has 6 vertices */ 2513 break; 2514 case 10: /* quadratic tetrahedron */ 2515 *numFaceVertices = 6; /* Face has 6 vertices */ 2516 break; 2517 case 12: /* hex cohesive Lagrange cells */ 2518 *numFaceVertices = 6; /* Face has 6 vertices */ 2519 break; 2520 case 18: /* quadratic tet cohesive Lagrange cells */ 2521 *numFaceVertices = 6; /* Face has 6 vertices */ 2522 break; 2523 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2524 *numFaceVertices = 9; /* Face has 9 vertices */ 2525 break; 2526 default: 2527 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 2528 } 2529 break; 2530 default: 2531 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 2532 } 2533 PetscFunctionReturn(0); 2534 } 2535 2536 #undef __FUNCT__ 2537 #define __FUNCT__ "DMPlexGetDepthLabel" 2538 /*@ 2539 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 2540 2541 Not Collective 2542 2543 Input Parameter: 2544 . dm - The DMPlex object 2545 2546 Output Parameter: 2547 . depthLabel - The DMLabel recording point depth 2548 2549 Level: developer 2550 2551 .keywords: mesh, points 2552 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2553 @*/ 2554 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 2555 { 2556 PetscErrorCode ierr; 2557 2558 PetscFunctionBegin; 2559 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2560 PetscValidPointer(depthLabel, 2); 2561 if (!dm->depthLabel) {ierr = DMGetLabel(dm, "depth", &dm->depthLabel);CHKERRQ(ierr);} 2562 *depthLabel = dm->depthLabel; 2563 PetscFunctionReturn(0); 2564 } 2565 2566 #undef __FUNCT__ 2567 #define __FUNCT__ "DMPlexGetDepth" 2568 /*@ 2569 DMPlexGetDepth - Get the depth of the DAG representing this mesh 2570 2571 Not Collective 2572 2573 Input Parameter: 2574 . dm - The DMPlex object 2575 2576 Output Parameter: 2577 . depth - The number of strata (breadth first levels) in the DAG 2578 2579 Level: developer 2580 2581 .keywords: mesh, points 2582 .seealso: DMPlexGetDepthLabel(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2583 @*/ 2584 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 2585 { 2586 DMLabel label; 2587 PetscInt d = 0; 2588 PetscErrorCode ierr; 2589 2590 PetscFunctionBegin; 2591 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2592 PetscValidPointer(depth, 2); 2593 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2594 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 2595 *depth = d-1; 2596 PetscFunctionReturn(0); 2597 } 2598 2599 #undef __FUNCT__ 2600 #define __FUNCT__ "DMPlexGetDepthStratum" 2601 /*@ 2602 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 2603 2604 Not Collective 2605 2606 Input Parameters: 2607 + dm - The DMPlex object 2608 - stratumValue - The requested depth 2609 2610 Output Parameters: 2611 + start - The first point at this depth 2612 - end - One beyond the last point at this depth 2613 2614 Level: developer 2615 2616 .keywords: mesh, points 2617 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 2618 @*/ 2619 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2620 { 2621 DMLabel label; 2622 PetscInt pStart, pEnd; 2623 PetscErrorCode ierr; 2624 2625 PetscFunctionBegin; 2626 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2627 if (start) {PetscValidPointer(start, 3); *start = 0;} 2628 if (end) {PetscValidPointer(end, 4); *end = 0;} 2629 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2630 if (pStart == pEnd) PetscFunctionReturn(0); 2631 if (stratumValue < 0) { 2632 if (start) *start = pStart; 2633 if (end) *end = pEnd; 2634 PetscFunctionReturn(0); 2635 } 2636 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2637 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 2638 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 2639 PetscFunctionReturn(0); 2640 } 2641 2642 #undef __FUNCT__ 2643 #define __FUNCT__ "DMPlexGetHeightStratum" 2644 /*@ 2645 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 2646 2647 Not Collective 2648 2649 Input Parameters: 2650 + dm - The DMPlex object 2651 - stratumValue - The requested height 2652 2653 Output Parameters: 2654 + start - The first point at this height 2655 - end - One beyond the last point at this height 2656 2657 Level: developer 2658 2659 .keywords: mesh, points 2660 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 2661 @*/ 2662 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2663 { 2664 DMLabel label; 2665 PetscInt depth, pStart, pEnd; 2666 PetscErrorCode ierr; 2667 2668 PetscFunctionBegin; 2669 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2670 if (start) {PetscValidPointer(start, 3); *start = 0;} 2671 if (end) {PetscValidPointer(end, 4); *end = 0;} 2672 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2673 if (pStart == pEnd) PetscFunctionReturn(0); 2674 if (stratumValue < 0) { 2675 if (start) *start = pStart; 2676 if (end) *end = pEnd; 2677 PetscFunctionReturn(0); 2678 } 2679 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2680 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 2681 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 2682 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 2683 PetscFunctionReturn(0); 2684 } 2685 2686 #undef __FUNCT__ 2687 #define __FUNCT__ "DMPlexCreateSectionInitial" 2688 /* Set the number of dof on each point and separate by fields */ 2689 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 2690 { 2691 PetscInt *pMax; 2692 PetscInt depth, pStart = 0, pEnd = 0; 2693 PetscInt Nf, p, d, dep, f; 2694 PetscBool *isFE; 2695 PetscErrorCode ierr; 2696 2697 PetscFunctionBegin; 2698 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 2699 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 2700 for (f = 0; f < numFields; ++f) { 2701 PetscObject obj; 2702 PetscClassId id; 2703 2704 isFE[f] = PETSC_FALSE; 2705 if (f >= Nf) continue; 2706 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 2707 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 2708 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 2709 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 2710 } 2711 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2712 if (numFields > 0) { 2713 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 2714 if (numComp) { 2715 for (f = 0; f < numFields; ++f) { 2716 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 2717 } 2718 } 2719 } 2720 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2721 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 2722 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2723 ierr = PetscMalloc1(depth+1,&pMax);CHKERRQ(ierr); 2724 ierr = DMPlexGetHybridBounds(dm, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 2725 for (dep = 0; dep <= depth; ++dep) { 2726 d = dim == depth ? dep : (!dep ? 0 : dim); 2727 ierr = DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd);CHKERRQ(ierr); 2728 pMax[dep] = pMax[dep] < 0 ? pEnd : pMax[dep]; 2729 for (p = pStart; p < pEnd; ++p) { 2730 PetscInt tot = 0; 2731 2732 for (f = 0; f < numFields; ++f) { 2733 if (isFE[f] && p >= pMax[dep]) continue; 2734 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 2735 tot += numDof[f*(dim+1)+d]; 2736 } 2737 ierr = PetscSectionSetDof(*section, p, tot);CHKERRQ(ierr); 2738 } 2739 } 2740 ierr = PetscFree(pMax);CHKERRQ(ierr); 2741 ierr = PetscFree(isFE);CHKERRQ(ierr); 2742 PetscFunctionReturn(0); 2743 } 2744 2745 #undef __FUNCT__ 2746 #define __FUNCT__ "DMPlexCreateSectionBCDof" 2747 /* Set the number of dof on each point and separate by fields 2748 If bcComps is NULL or the IS is NULL, constrain every dof on the point 2749 */ 2750 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 2751 { 2752 PetscInt numFields; 2753 PetscInt bc; 2754 PetscSection aSec; 2755 PetscErrorCode ierr; 2756 2757 PetscFunctionBegin; 2758 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 2759 for (bc = 0; bc < numBC; ++bc) { 2760 PetscInt field = 0; 2761 const PetscInt *comp; 2762 const PetscInt *idx; 2763 PetscInt Nc = -1, n, i; 2764 2765 if (numFields) field = bcField[bc]; 2766 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 2767 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 2768 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 2769 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 2770 for (i = 0; i < n; ++i) { 2771 const PetscInt p = idx[i]; 2772 PetscInt numConst; 2773 2774 if (numFields) { 2775 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 2776 } else { 2777 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 2778 } 2779 /* If Nc < 0, constrain every dof on the point */ 2780 if (Nc > 0) numConst = PetscMin(numConst, Nc); 2781 if (numFields) {ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr);} 2782 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 2783 } 2784 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 2785 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 2786 } 2787 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 2788 if (aSec) { 2789 PetscInt aStart, aEnd, a; 2790 2791 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 2792 for (a = aStart; a < aEnd; a++) { 2793 PetscInt dof, f; 2794 2795 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 2796 if (dof) { 2797 /* if there are point-to-point constraints, then all dofs are constrained */ 2798 ierr = PetscSectionGetDof(section, a, &dof);CHKERRQ(ierr); 2799 ierr = PetscSectionSetConstraintDof(section, a, dof);CHKERRQ(ierr); 2800 for (f = 0; f < numFields; f++) { 2801 ierr = PetscSectionGetFieldDof(section, a, f, &dof);CHKERRQ(ierr); 2802 ierr = PetscSectionSetFieldConstraintDof(section, a, f, dof);CHKERRQ(ierr); 2803 } 2804 } 2805 } 2806 } 2807 PetscFunctionReturn(0); 2808 } 2809 2810 #undef __FUNCT__ 2811 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 2812 /* Set the constrained field indices on each point 2813 If bcComps is NULL or the IS is NULL, constrain every dof on the point 2814 */ 2815 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt numBC,const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 2816 { 2817 PetscSection aSec; 2818 PetscInt *indices; 2819 PetscInt numFields, maxDof, pStart, pEnd, p, bc, f, d; 2820 PetscErrorCode ierr; 2821 2822 PetscFunctionBegin; 2823 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 2824 if (!numFields) PetscFunctionReturn(0); 2825 /* Initialize all field indices to -1 */ 2826 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 2827 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 2828 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 2829 for (d = 0; d < maxDof; ++d) indices[d] = -1; 2830 for (p = pStart; p < pEnd; ++p) for (f = 0; f < numFields; ++f) {ierr = PetscSectionSetFieldConstraintIndices(section, p, f, indices);CHKERRQ(ierr);} 2831 /* Handle BC constraints */ 2832 for (bc = 0; bc < numBC; ++bc) { 2833 const PetscInt field = bcField[bc]; 2834 const PetscInt *comp, *idx; 2835 PetscInt Nc = -1, n, i; 2836 2837 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 2838 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 2839 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 2840 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 2841 for (i = 0; i < n; ++i) { 2842 const PetscInt p = idx[i]; 2843 const PetscInt *find; 2844 PetscInt fcdof, c; 2845 2846 ierr = PetscSectionGetFieldConstraintDof(section, p, field, &fcdof);CHKERRQ(ierr); 2847 if (Nc < 0) { 2848 for (d = 0; d < fcdof; ++d) indices[d] = d; 2849 } else { 2850 ierr = PetscSectionGetFieldConstraintIndices(section, p, field, &find);CHKERRQ(ierr); 2851 for (d = 0; d < fcdof; ++d) {if (find[d] < 0) break; indices[d] = find[d];} 2852 for (c = 0; c < Nc; ++c) indices[d+c] = comp[c]; 2853 ierr = PetscSortInt(d+Nc, indices);CHKERRQ(ierr); 2854 for (c = d+Nc; c < fcdof; ++c) indices[c] = -1; 2855 } 2856 ierr = PetscSectionSetFieldConstraintIndices(section, p, field, indices);CHKERRQ(ierr); 2857 } 2858 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 2859 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 2860 } 2861 /* Handle anchors */ 2862 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 2863 if (aSec) { 2864 PetscInt aStart, aEnd, a; 2865 2866 for (d = 0; d < maxDof; ++d) indices[d] = d; 2867 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 2868 for (a = aStart; a < aEnd; a++) { 2869 PetscInt dof, fdof, f; 2870 2871 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 2872 if (dof) { 2873 /* if there are point-to-point constraints, then all dofs are constrained */ 2874 for (f = 0; f < numFields; f++) { 2875 ierr = PetscSectionGetFieldDof(section, a, f, &fdof);CHKERRQ(ierr); 2876 ierr = PetscSectionSetFieldConstraintIndices(section, a, f, indices);CHKERRQ(ierr); 2877 } 2878 } 2879 } 2880 } 2881 ierr = PetscFree(indices);CHKERRQ(ierr); 2882 PetscFunctionReturn(0); 2883 } 2884 2885 #undef __FUNCT__ 2886 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 2887 /* Set the constrained indices on each point */ 2888 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 2889 { 2890 PetscInt *indices; 2891 PetscInt numFields, maxDof, pStart, pEnd, p, f, d; 2892 PetscErrorCode ierr; 2893 2894 PetscFunctionBegin; 2895 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 2896 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 2897 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 2898 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 2899 for (d = 0; d < maxDof; ++d) indices[d] = -1; 2900 for (p = pStart; p < pEnd; ++p) { 2901 PetscInt cdof, d; 2902 2903 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 2904 if (cdof) { 2905 if (numFields) { 2906 PetscInt numConst = 0, foff = 0; 2907 2908 for (f = 0; f < numFields; ++f) { 2909 const PetscInt *find; 2910 PetscInt fcdof, fdof; 2911 2912 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 2913 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 2914 /* Change constraint numbering from field component to local dof number */ 2915 ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &find);CHKERRQ(ierr); 2916 for (d = 0; d < fcdof; ++d) indices[numConst+d] = find[d] + foff; 2917 numConst += fcdof; 2918 foff += fdof; 2919 } 2920 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 2921 } else { 2922 for (d = 0; d < cdof; ++d) indices[d] = d; 2923 } 2924 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 2925 } 2926 } 2927 ierr = PetscFree(indices);CHKERRQ(ierr); 2928 PetscFunctionReturn(0); 2929 } 2930 2931 #undef __FUNCT__ 2932 #define __FUNCT__ "DMPlexCreateSection" 2933 /*@C 2934 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 2935 2936 Not Collective 2937 2938 Input Parameters: 2939 + dm - The DMPlex object 2940 . dim - The spatial dimension of the problem 2941 . numFields - The number of fields in the problem 2942 . numComp - An array of size numFields that holds the number of components for each field 2943 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 2944 . numBC - The number of boundary conditions 2945 . bcField - An array of size numBC giving the field number for each boundry condition 2946 . bcComps - [Optional] An array of size numBC giving an IS holding the field components to which each boundary condition applies 2947 . bcPoints - An array of size numBC giving an IS holding the Plex points to which each boundary condition applies 2948 - perm - Optional permutation of the chart, or NULL 2949 2950 Output Parameter: 2951 . section - The PetscSection object 2952 2953 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 2954 number of dof for field 0 on each edge. 2955 2956 The chart permutation is the same one set using PetscSectionSetPermutation() 2957 2958 Level: developer 2959 2960 Fortran Notes: 2961 A Fortran 90 version is available as DMPlexCreateSectionF90() 2962 2963 .keywords: mesh, elements 2964 .seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation() 2965 @*/ 2966 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) 2967 { 2968 PetscSection aSec; 2969 PetscErrorCode ierr; 2970 2971 PetscFunctionBegin; 2972 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 2973 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 2974 if (perm) {ierr = PetscSectionSetPermutation(*section, perm);CHKERRQ(ierr);} 2975 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 2976 ierr = DMPlexGetAnchors(dm,&aSec,NULL);CHKERRQ(ierr); 2977 if (numBC || aSec) { 2978 ierr = DMPlexCreateSectionBCIndicesField(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 2979 ierr = DMPlexCreateSectionBCIndices(dm, *section);CHKERRQ(ierr); 2980 } 2981 ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr); 2982 PetscFunctionReturn(0); 2983 } 2984 2985 #undef __FUNCT__ 2986 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 2987 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 2988 { 2989 PetscSection section, s; 2990 Mat m; 2991 PetscInt dim; 2992 PetscErrorCode ierr; 2993 2994 PetscFunctionBegin; 2995 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 2996 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 2997 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 2998 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 2999 ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 3000 ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 3001 ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 3002 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 3003 ierr = MatDestroy(&m);CHKERRQ(ierr); 3004 PetscFunctionReturn(0); 3005 } 3006 3007 #undef __FUNCT__ 3008 #define __FUNCT__ "DMPlexGetConeSection" 3009 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 3010 { 3011 DM_Plex *mesh = (DM_Plex*) dm->data; 3012 3013 PetscFunctionBegin; 3014 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3015 if (section) *section = mesh->coneSection; 3016 PetscFunctionReturn(0); 3017 } 3018 3019 #undef __FUNCT__ 3020 #define __FUNCT__ "DMPlexGetSupportSection" 3021 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 3022 { 3023 DM_Plex *mesh = (DM_Plex*) dm->data; 3024 3025 PetscFunctionBegin; 3026 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3027 if (section) *section = mesh->supportSection; 3028 PetscFunctionReturn(0); 3029 } 3030 3031 #undef __FUNCT__ 3032 #define __FUNCT__ "DMPlexGetCones" 3033 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 3034 { 3035 DM_Plex *mesh = (DM_Plex*) dm->data; 3036 3037 PetscFunctionBegin; 3038 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3039 if (cones) *cones = mesh->cones; 3040 PetscFunctionReturn(0); 3041 } 3042 3043 #undef __FUNCT__ 3044 #define __FUNCT__ "DMPlexGetConeOrientations" 3045 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 3046 { 3047 DM_Plex *mesh = (DM_Plex*) dm->data; 3048 3049 PetscFunctionBegin; 3050 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3051 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 3052 PetscFunctionReturn(0); 3053 } 3054 3055 /******************************** FEM Support **********************************/ 3056 3057 #undef __FUNCT__ 3058 #define __FUNCT__ "DMPlexVecGetClosure_Depth1_Static" 3059 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3060 { 3061 PetscScalar *array, *vArray; 3062 const PetscInt *cone, *coneO; 3063 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3064 PetscErrorCode ierr; 3065 3066 PetscFunctionBeginHot; 3067 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3068 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3069 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3070 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3071 if (!values || !*values) { 3072 if ((point >= pStart) && (point < pEnd)) { 3073 PetscInt dof; 3074 3075 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3076 size += dof; 3077 } 3078 for (p = 0; p < numPoints; ++p) { 3079 const PetscInt cp = cone[p]; 3080 PetscInt dof; 3081 3082 if ((cp < pStart) || (cp >= pEnd)) continue; 3083 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3084 size += dof; 3085 } 3086 if (!values) { 3087 if (csize) *csize = size; 3088 PetscFunctionReturn(0); 3089 } 3090 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 3091 } else { 3092 array = *values; 3093 } 3094 size = 0; 3095 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3096 if ((point >= pStart) && (point < pEnd)) { 3097 PetscInt dof, off, d; 3098 PetscScalar *varr; 3099 3100 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3101 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3102 varr = &vArray[off]; 3103 for (d = 0; d < dof; ++d, ++offset) { 3104 array[offset] = varr[d]; 3105 } 3106 size += dof; 3107 } 3108 for (p = 0; p < numPoints; ++p) { 3109 const PetscInt cp = cone[p]; 3110 PetscInt o = coneO[p]; 3111 PetscInt dof, off, d; 3112 PetscScalar *varr; 3113 3114 if ((cp < pStart) || (cp >= pEnd)) continue; 3115 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3116 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3117 varr = &vArray[off]; 3118 if (o >= 0) { 3119 for (d = 0; d < dof; ++d, ++offset) { 3120 array[offset] = varr[d]; 3121 } 3122 } else { 3123 for (d = dof-1; d >= 0; --d, ++offset) { 3124 array[offset] = varr[d]; 3125 } 3126 } 3127 size += dof; 3128 } 3129 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3130 if (!*values) { 3131 if (csize) *csize = size; 3132 *values = array; 3133 } else { 3134 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 3135 *csize = size; 3136 } 3137 PetscFunctionReturn(0); 3138 } 3139 3140 #undef __FUNCT__ 3141 #define __FUNCT__ "DMPlexVecGetClosure_Static" 3142 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3143 { 3144 PetscInt offset = 0, p; 3145 PetscErrorCode ierr; 3146 3147 PetscFunctionBeginHot; 3148 *size = 0; 3149 for (p = 0; p < numPoints*2; p += 2) { 3150 const PetscInt point = points[p]; 3151 const PetscInt o = points[p+1]; 3152 PetscInt dof, off, d; 3153 const PetscScalar *varr; 3154 3155 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3156 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3157 varr = &vArray[off]; 3158 if (o >= 0) { 3159 for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 3160 } else { 3161 for (d = dof-1; d >= 0; --d, ++offset) array[offset] = varr[d]; 3162 } 3163 } 3164 *size = offset; 3165 PetscFunctionReturn(0); 3166 } 3167 3168 #undef __FUNCT__ 3169 #define __FUNCT__ "DMPlexVecGetClosure_Fields_Static" 3170 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3171 { 3172 PetscInt offset = 0, f; 3173 PetscErrorCode ierr; 3174 3175 PetscFunctionBeginHot; 3176 *size = 0; 3177 for (f = 0; f < numFields; ++f) { 3178 PetscInt fcomp, p; 3179 3180 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3181 for (p = 0; p < numPoints*2; p += 2) { 3182 const PetscInt point = points[p]; 3183 const PetscInt o = points[p+1]; 3184 PetscInt fdof, foff, d, c; 3185 const PetscScalar *varr; 3186 3187 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3188 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3189 varr = &vArray[foff]; 3190 if (o >= 0) { 3191 for (d = 0; d < fdof; ++d, ++offset) array[offset] = varr[d]; 3192 } else { 3193 for (d = fdof/fcomp-1; d >= 0; --d) { 3194 for (c = 0; c < fcomp; ++c, ++offset) { 3195 array[offset] = varr[d*fcomp+c]; 3196 } 3197 } 3198 } 3199 } 3200 } 3201 *size = offset; 3202 PetscFunctionReturn(0); 3203 } 3204 3205 #undef __FUNCT__ 3206 #define __FUNCT__ "DMPlexVecGetClosure" 3207 /*@C 3208 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 3209 3210 Not collective 3211 3212 Input Parameters: 3213 + dm - The DM 3214 . section - The section describing the layout in v, or NULL to use the default section 3215 . v - The local vector 3216 - point - The sieve point in the DM 3217 3218 Output Parameters: 3219 + csize - The number of values in the closure, or NULL 3220 - values - The array of values, which is a borrowed array and should not be freed 3221 3222 Fortran Notes: 3223 Since it returns an array, this routine is only available in Fortran 90, and you must 3224 include petsc.h90 in your code. 3225 3226 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3227 3228 Level: intermediate 3229 3230 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3231 @*/ 3232 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3233 { 3234 PetscSection clSection; 3235 IS clPoints; 3236 PetscScalar *array, *vArray; 3237 PetscInt *points = NULL; 3238 const PetscInt *clp; 3239 PetscInt depth, numFields, numPoints, size; 3240 PetscErrorCode ierr; 3241 3242 PetscFunctionBeginHot; 3243 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3244 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3245 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3246 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3247 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3248 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3249 if (depth == 1 && numFields < 2) { 3250 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 3251 PetscFunctionReturn(0); 3252 } 3253 /* Get points */ 3254 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3255 if (!clPoints) { 3256 PetscInt pStart, pEnd, p, q; 3257 3258 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3259 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3260 /* Compress out points not in the section */ 3261 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3262 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3263 points[q*2] = points[p]; 3264 points[q*2+1] = points[p+1]; 3265 ++q; 3266 } 3267 } 3268 numPoints = q; 3269 } else { 3270 PetscInt dof, off; 3271 3272 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3273 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3274 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3275 numPoints = dof/2; 3276 points = (PetscInt *) &clp[off]; 3277 } 3278 /* Get array */ 3279 if (!values || !*values) { 3280 PetscInt asize = 0, dof, p; 3281 3282 for (p = 0; p < numPoints*2; p += 2) { 3283 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3284 asize += dof; 3285 } 3286 if (!values) { 3287 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3288 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3289 if (csize) *csize = asize; 3290 PetscFunctionReturn(0); 3291 } 3292 ierr = DMGetWorkArray(dm, asize, PETSC_SCALAR, &array);CHKERRQ(ierr); 3293 } else { 3294 array = *values; 3295 } 3296 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3297 /* Get values */ 3298 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(section, numPoints, points, numFields, vArray, &size, array);CHKERRQ(ierr);} 3299 else {ierr = DMPlexVecGetClosure_Static(section, numPoints, points, vArray, &size, array);CHKERRQ(ierr);} 3300 /* Cleanup points */ 3301 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3302 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3303 /* Cleanup array */ 3304 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3305 if (!*values) { 3306 if (csize) *csize = size; 3307 *values = array; 3308 } else { 3309 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 3310 *csize = size; 3311 } 3312 PetscFunctionReturn(0); 3313 } 3314 3315 #undef __FUNCT__ 3316 #define __FUNCT__ "DMPlexVecRestoreClosure" 3317 /*@C 3318 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 3319 3320 Not collective 3321 3322 Input Parameters: 3323 + dm - The DM 3324 . section - The section describing the layout in v, or NULL to use the default section 3325 . v - The local vector 3326 . point - The sieve point in the DM 3327 . csize - The number of values in the closure, or NULL 3328 - values - The array of values, which is a borrowed array and should not be freed 3329 3330 Fortran Notes: 3331 Since it returns an array, this routine is only available in Fortran 90, and you must 3332 include petsc.h90 in your code. 3333 3334 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3335 3336 Level: intermediate 3337 3338 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3339 @*/ 3340 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3341 { 3342 PetscInt size = 0; 3343 PetscErrorCode ierr; 3344 3345 PetscFunctionBegin; 3346 /* Should work without recalculating size */ 3347 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 3348 PetscFunctionReturn(0); 3349 } 3350 3351 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 3352 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 3353 3354 #undef __FUNCT__ 3355 #define __FUNCT__ "updatePoint_private" 3356 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[]) 3357 { 3358 PetscInt cdof; /* The number of constraints on this point */ 3359 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3360 PetscScalar *a; 3361 PetscInt off, cind = 0, k; 3362 PetscErrorCode ierr; 3363 3364 PetscFunctionBegin; 3365 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3366 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3367 a = &array[off]; 3368 if (!cdof || setBC) { 3369 if (orientation >= 0) { 3370 for (k = 0; k < dof; ++k) { 3371 fuse(&a[k], values[k]); 3372 } 3373 } else { 3374 for (k = 0; k < dof; ++k) { 3375 fuse(&a[k], values[dof-k-1]); 3376 } 3377 } 3378 } else { 3379 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3380 if (orientation >= 0) { 3381 for (k = 0; k < dof; ++k) { 3382 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3383 fuse(&a[k], values[k]); 3384 } 3385 } else { 3386 for (k = 0; k < dof; ++k) { 3387 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3388 fuse(&a[k], values[dof-k-1]); 3389 } 3390 } 3391 } 3392 PetscFunctionReturn(0); 3393 } 3394 3395 #undef __FUNCT__ 3396 #define __FUNCT__ "updatePointBC_private" 3397 PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 3398 { 3399 PetscInt cdof; /* The number of constraints on this point */ 3400 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3401 PetscScalar *a; 3402 PetscInt off, cind = 0, k; 3403 PetscErrorCode ierr; 3404 3405 PetscFunctionBegin; 3406 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3407 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3408 a = &array[off]; 3409 if (cdof) { 3410 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3411 if (orientation >= 0) { 3412 for (k = 0; k < dof; ++k) { 3413 if ((cind < cdof) && (k == cdofs[cind])) { 3414 fuse(&a[k], values[k]); 3415 ++cind; 3416 } 3417 } 3418 } else { 3419 for (k = 0; k < dof; ++k) { 3420 if ((cind < cdof) && (k == cdofs[cind])) { 3421 fuse(&a[k], values[dof-k-1]); 3422 ++cind; 3423 } 3424 } 3425 } 3426 } 3427 PetscFunctionReturn(0); 3428 } 3429 3430 #undef __FUNCT__ 3431 #define __FUNCT__ "updatePointFields_private" 3432 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[]) 3433 { 3434 PetscScalar *a; 3435 PetscInt fdof, foff, fcdof, foffset = *offset; 3436 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3437 PetscInt cind = 0, k, c; 3438 PetscErrorCode ierr; 3439 3440 PetscFunctionBegin; 3441 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3442 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3443 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3444 a = &array[foff]; 3445 if (!fcdof || setBC) { 3446 if (o >= 0) { 3447 for (k = 0; k < fdof; ++k) fuse(&a[k], values[foffset+k]); 3448 } else { 3449 for (k = fdof/fcomp-1; k >= 0; --k) { 3450 for (c = 0; c < fcomp; ++c) { 3451 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3452 } 3453 } 3454 } 3455 } else { 3456 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3457 if (o >= 0) { 3458 for (k = 0; k < fdof; ++k) { 3459 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 3460 fuse(&a[k], values[foffset+k]); 3461 } 3462 } else { 3463 for (k = fdof/fcomp-1; k >= 0; --k) { 3464 for (c = 0; c < fcomp; ++c) { 3465 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 3466 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3467 } 3468 } 3469 } 3470 } 3471 *offset += fdof; 3472 PetscFunctionReturn(0); 3473 } 3474 3475 #undef __FUNCT__ 3476 #define __FUNCT__ "updatePointFieldsBC_private" 3477 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[]) 3478 { 3479 PetscScalar *a; 3480 PetscInt fdof, foff, fcdof, foffset = *offset; 3481 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3482 PetscInt cind = 0, k, c; 3483 PetscErrorCode ierr; 3484 3485 PetscFunctionBegin; 3486 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3487 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3488 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3489 a = &array[foff]; 3490 if (fcdof) { 3491 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3492 if (o >= 0) { 3493 for (k = 0; k < fdof; ++k) { 3494 if ((cind < fcdof) && (k == fcdofs[cind])) { 3495 fuse(&a[k], values[foffset+k]); 3496 ++cind; 3497 } 3498 } 3499 } else { 3500 for (k = fdof/fcomp-1; k >= 0; --k) { 3501 for (c = 0; c < fcomp; ++c) { 3502 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) { 3503 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3504 ++cind; 3505 } 3506 } 3507 } 3508 } 3509 } 3510 *offset += fdof; 3511 PetscFunctionReturn(0); 3512 } 3513 3514 #undef __FUNCT__ 3515 #define __FUNCT__ "DMPlexVecSetClosure_Static" 3516 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3517 { 3518 PetscScalar *array; 3519 const PetscInt *cone, *coneO; 3520 PetscInt pStart, pEnd, p, numPoints, off, dof; 3521 PetscErrorCode ierr; 3522 3523 PetscFunctionBeginHot; 3524 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3525 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3526 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3527 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3528 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3529 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 3530 const PetscInt cp = !p ? point : cone[p-1]; 3531 const PetscInt o = !p ? 0 : coneO[p-1]; 3532 3533 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 3534 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3535 /* ADD_VALUES */ 3536 { 3537 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3538 PetscScalar *a; 3539 PetscInt cdof, coff, cind = 0, k; 3540 3541 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 3542 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 3543 a = &array[coff]; 3544 if (!cdof) { 3545 if (o >= 0) { 3546 for (k = 0; k < dof; ++k) { 3547 a[k] += values[off+k]; 3548 } 3549 } else { 3550 for (k = 0; k < dof; ++k) { 3551 a[k] += values[off+dof-k-1]; 3552 } 3553 } 3554 } else { 3555 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 3556 if (o >= 0) { 3557 for (k = 0; k < dof; ++k) { 3558 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3559 a[k] += values[off+k]; 3560 } 3561 } else { 3562 for (k = 0; k < dof; ++k) { 3563 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3564 a[k] += values[off+dof-k-1]; 3565 } 3566 } 3567 } 3568 } 3569 } 3570 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3571 PetscFunctionReturn(0); 3572 } 3573 3574 #undef __FUNCT__ 3575 #define __FUNCT__ "DMPlexVecSetClosure" 3576 /*@C 3577 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 3578 3579 Not collective 3580 3581 Input Parameters: 3582 + dm - The DM 3583 . section - The section describing the layout in v, or NULL to use the default section 3584 . v - The local vector 3585 . point - The sieve point in the DM 3586 . values - The array of values 3587 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 3588 3589 Fortran Notes: 3590 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3591 3592 Level: intermediate 3593 3594 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 3595 @*/ 3596 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3597 { 3598 PetscSection clSection; 3599 IS clPoints; 3600 PetscScalar *array; 3601 PetscInt *points = NULL; 3602 const PetscInt *clp; 3603 PetscInt depth, numFields, numPoints, p; 3604 PetscErrorCode ierr; 3605 3606 PetscFunctionBeginHot; 3607 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3608 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3609 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3610 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3611 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3612 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3613 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 3614 ierr = DMPlexVecSetClosure_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 3615 PetscFunctionReturn(0); 3616 } 3617 /* Get points */ 3618 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3619 if (!clPoints) { 3620 PetscInt pStart, pEnd, q; 3621 3622 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3623 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3624 /* Compress out points not in the section */ 3625 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3626 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3627 points[q*2] = points[p]; 3628 points[q*2+1] = points[p+1]; 3629 ++q; 3630 } 3631 } 3632 numPoints = q; 3633 } else { 3634 PetscInt dof, off; 3635 3636 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3637 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3638 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3639 numPoints = dof/2; 3640 points = (PetscInt *) &clp[off]; 3641 } 3642 /* Get array */ 3643 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3644 /* Get values */ 3645 if (numFields > 0) { 3646 PetscInt offset = 0, fcomp, f; 3647 for (f = 0; f < numFields; ++f) { 3648 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3649 switch (mode) { 3650 case INSERT_VALUES: 3651 for (p = 0; p < numPoints*2; p += 2) { 3652 const PetscInt point = points[p]; 3653 const PetscInt o = points[p+1]; 3654 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 3655 } break; 3656 case INSERT_ALL_VALUES: 3657 for (p = 0; p < numPoints*2; p += 2) { 3658 const PetscInt point = points[p]; 3659 const PetscInt o = points[p+1]; 3660 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 3661 } break; 3662 case INSERT_BC_VALUES: 3663 for (p = 0; p < numPoints*2; p += 2) { 3664 const PetscInt point = points[p]; 3665 const PetscInt o = points[p+1]; 3666 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 3667 } break; 3668 case ADD_VALUES: 3669 for (p = 0; p < numPoints*2; p += 2) { 3670 const PetscInt point = points[p]; 3671 const PetscInt o = points[p+1]; 3672 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 3673 } break; 3674 case ADD_ALL_VALUES: 3675 for (p = 0; p < numPoints*2; p += 2) { 3676 const PetscInt point = points[p]; 3677 const PetscInt o = points[p+1]; 3678 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 3679 } break; 3680 default: 3681 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3682 } 3683 } 3684 } else { 3685 PetscInt dof, off; 3686 3687 switch (mode) { 3688 case INSERT_VALUES: 3689 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3690 PetscInt o = points[p+1]; 3691 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3692 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 3693 } break; 3694 case INSERT_ALL_VALUES: 3695 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3696 PetscInt o = points[p+1]; 3697 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3698 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 3699 } break; 3700 case INSERT_BC_VALUES: 3701 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3702 PetscInt o = points[p+1]; 3703 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3704 updatePointBC_private(section, points[p], dof, insert, o, &values[off], array); 3705 } break; 3706 case ADD_VALUES: 3707 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3708 PetscInt o = points[p+1]; 3709 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3710 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 3711 } break; 3712 case ADD_ALL_VALUES: 3713 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3714 PetscInt o = points[p+1]; 3715 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3716 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 3717 } break; 3718 default: 3719 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3720 } 3721 } 3722 /* Cleanup points */ 3723 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3724 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3725 /* Cleanup array */ 3726 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3727 PetscFunctionReturn(0); 3728 } 3729 3730 #undef __FUNCT__ 3731 #define __FUNCT__ "DMPlexVecSetFieldClosure_Internal" 3732 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, const PetscScalar values[], InsertMode mode) 3733 { 3734 PetscSection clSection; 3735 IS clPoints; 3736 PetscScalar *array; 3737 PetscInt *points = NULL; 3738 const PetscInt *clp; 3739 PetscInt numFields, numPoints, p; 3740 PetscInt offset = 0, fcomp, f; 3741 PetscErrorCode ierr; 3742 3743 PetscFunctionBeginHot; 3744 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3745 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3746 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3747 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3748 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3749 /* Get points */ 3750 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3751 if (!clPoints) { 3752 PetscInt pStart, pEnd, q; 3753 3754 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3755 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3756 /* Compress out points not in the section */ 3757 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3758 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3759 points[q*2] = points[p]; 3760 points[q*2+1] = points[p+1]; 3761 ++q; 3762 } 3763 } 3764 numPoints = q; 3765 } else { 3766 PetscInt dof, off; 3767 3768 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3769 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3770 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3771 numPoints = dof/2; 3772 points = (PetscInt *) &clp[off]; 3773 } 3774 /* Get array */ 3775 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3776 /* Get values */ 3777 for (f = 0; f < numFields; ++f) { 3778 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3779 if (!fieldActive[f]) { 3780 for (p = 0; p < numPoints*2; p += 2) { 3781 PetscInt fdof; 3782 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 3783 offset += fdof; 3784 } 3785 continue; 3786 } 3787 switch (mode) { 3788 case INSERT_VALUES: 3789 for (p = 0; p < numPoints*2; p += 2) { 3790 const PetscInt point = points[p]; 3791 const PetscInt o = points[p+1]; 3792 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 3793 } break; 3794 case INSERT_ALL_VALUES: 3795 for (p = 0; p < numPoints*2; p += 2) { 3796 const PetscInt point = points[p]; 3797 const PetscInt o = points[p+1]; 3798 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 3799 } break; 3800 case INSERT_BC_VALUES: 3801 for (p = 0; p < numPoints*2; p += 2) { 3802 const PetscInt point = points[p]; 3803 const PetscInt o = points[p+1]; 3804 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 3805 } break; 3806 case ADD_VALUES: 3807 for (p = 0; p < numPoints*2; p += 2) { 3808 const PetscInt point = points[p]; 3809 const PetscInt o = points[p+1]; 3810 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 3811 } break; 3812 case ADD_ALL_VALUES: 3813 for (p = 0; p < numPoints*2; p += 2) { 3814 const PetscInt point = points[p]; 3815 const PetscInt o = points[p+1]; 3816 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 3817 } break; 3818 default: 3819 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3820 } 3821 } 3822 /* Cleanup points */ 3823 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3824 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3825 /* Cleanup array */ 3826 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3827 PetscFunctionReturn(0); 3828 } 3829 3830 #undef __FUNCT__ 3831 #define __FUNCT__ "DMPlexPrintMatSetValues" 3832 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 3833 { 3834 PetscMPIInt rank; 3835 PetscInt i, j; 3836 PetscErrorCode ierr; 3837 3838 PetscFunctionBegin; 3839 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 3840 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 3841 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 3842 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 3843 numCIndices = numCIndices ? numCIndices : numRIndices; 3844 for (i = 0; i < numRIndices; i++) { 3845 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 3846 for (j = 0; j < numCIndices; j++) { 3847 #if defined(PETSC_USE_COMPLEX) 3848 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 3849 #else 3850 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 3851 #endif 3852 } 3853 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 3854 } 3855 PetscFunctionReturn(0); 3856 } 3857 3858 #undef __FUNCT__ 3859 #define __FUNCT__ "indicesPoint_private" 3860 /* . off - The global offset of this point */ 3861 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 3862 { 3863 PetscInt dof; /* The number of unknowns on this point */ 3864 PetscInt cdof; /* The number of constraints on this point */ 3865 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3866 PetscInt cind = 0, k; 3867 PetscErrorCode ierr; 3868 3869 PetscFunctionBegin; 3870 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3871 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3872 if (!cdof || setBC) { 3873 if (orientation >= 0) { 3874 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 3875 } else { 3876 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 3877 } 3878 } else { 3879 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3880 if (orientation >= 0) { 3881 for (k = 0; k < dof; ++k) { 3882 if ((cind < cdof) && (k == cdofs[cind])) { 3883 /* Insert check for returning constrained indices */ 3884 indices[*loff+k] = -(off+k+1); 3885 ++cind; 3886 } else { 3887 indices[*loff+k] = off+k-cind; 3888 } 3889 } 3890 } else { 3891 for (k = 0; k < dof; ++k) { 3892 if ((cind < cdof) && (k == cdofs[cind])) { 3893 /* Insert check for returning constrained indices */ 3894 indices[*loff+dof-k-1] = -(off+k+1); 3895 ++cind; 3896 } else { 3897 indices[*loff+dof-k-1] = off+k-cind; 3898 } 3899 } 3900 } 3901 } 3902 *loff += dof; 3903 PetscFunctionReturn(0); 3904 } 3905 3906 #undef __FUNCT__ 3907 #define __FUNCT__ "indicesPointFields_private" 3908 /* . off - The global offset of this point */ 3909 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 3910 { 3911 PetscInt numFields, foff, f; 3912 PetscErrorCode ierr; 3913 3914 PetscFunctionBegin; 3915 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3916 for (f = 0, foff = 0; f < numFields; ++f) { 3917 PetscInt fdof, fcomp, cfdof; 3918 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3919 PetscInt cind = 0, k, c; 3920 3921 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3922 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3923 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 3924 if (!cfdof || setBC) { 3925 if (orientation >= 0) { 3926 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 3927 } else { 3928 for (k = fdof/fcomp-1; k >= 0; --k) { 3929 for (c = 0; c < fcomp; ++c) { 3930 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 3931 } 3932 } 3933 } 3934 } else { 3935 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3936 if (orientation >= 0) { 3937 for (k = 0; k < fdof; ++k) { 3938 if ((cind < cfdof) && (k == fcdofs[cind])) { 3939 indices[foffs[f]+k] = -(off+foff+k+1); 3940 ++cind; 3941 } else { 3942 indices[foffs[f]+k] = off+foff+k-cind; 3943 } 3944 } 3945 } else { 3946 for (k = fdof/fcomp-1; k >= 0; --k) { 3947 for (c = 0; c < fcomp; ++c) { 3948 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 3949 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 3950 ++cind; 3951 } else { 3952 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 3953 } 3954 } 3955 } 3956 } 3957 } 3958 foff += (setBC ? fdof : (fdof - cfdof)); 3959 foffs[f] += fdof; 3960 } 3961 PetscFunctionReturn(0); 3962 } 3963 3964 #undef __FUNCT__ 3965 #define __FUNCT__ "DMPlexAnchorsModifyMat" 3966 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) 3967 { 3968 Mat cMat; 3969 PetscSection aSec, cSec; 3970 IS aIS; 3971 PetscInt aStart = -1, aEnd = -1; 3972 const PetscInt *anchors; 3973 PetscInt numFields, f, p, q, newP = 0; 3974 PetscInt newNumPoints = 0, newNumIndices = 0; 3975 PetscInt *newPoints, *indices, *newIndices; 3976 PetscInt maxAnchor, maxDof; 3977 PetscInt newOffsets[32]; 3978 PetscInt *pointMatOffsets[32]; 3979 PetscInt *newPointOffsets[32]; 3980 PetscScalar *pointMat[32]; 3981 PetscScalar *newValues=NULL,*tmpValues; 3982 PetscBool anyConstrained = PETSC_FALSE; 3983 PetscErrorCode ierr; 3984 3985 PetscFunctionBegin; 3986 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3987 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3988 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3989 3990 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 3991 /* if there are point-to-point constraints */ 3992 if (aSec) { 3993 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 3994 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 3995 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 3996 /* figure out how many points are going to be in the new element matrix 3997 * (we allow double counting, because it's all just going to be summed 3998 * into the global matrix anyway) */ 3999 for (p = 0; p < 2*numPoints; p+=2) { 4000 PetscInt b = points[p]; 4001 PetscInt bDof = 0, bSecDof; 4002 4003 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4004 if (!bSecDof) { 4005 continue; 4006 } 4007 if (b >= aStart && b < aEnd) { 4008 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 4009 } 4010 if (bDof) { 4011 /* this point is constrained */ 4012 /* it is going to be replaced by its anchors */ 4013 PetscInt bOff, q; 4014 4015 anyConstrained = PETSC_TRUE; 4016 newNumPoints += bDof; 4017 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 4018 for (q = 0; q < bDof; q++) { 4019 PetscInt a = anchors[bOff + q]; 4020 PetscInt aDof; 4021 4022 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 4023 newNumIndices += aDof; 4024 for (f = 0; f < numFields; ++f) { 4025 PetscInt fDof; 4026 4027 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 4028 newOffsets[f+1] += fDof; 4029 } 4030 } 4031 } 4032 else { 4033 /* this point is not constrained */ 4034 newNumPoints++; 4035 newNumIndices += bSecDof; 4036 for (f = 0; f < numFields; ++f) { 4037 PetscInt fDof; 4038 4039 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4040 newOffsets[f+1] += fDof; 4041 } 4042 } 4043 } 4044 } 4045 if (!anyConstrained) { 4046 if (outNumPoints) *outNumPoints = 0; 4047 if (outNumIndices) *outNumIndices = 0; 4048 if (outPoints) *outPoints = NULL; 4049 if (outValues) *outValues = NULL; 4050 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4051 PetscFunctionReturn(0); 4052 } 4053 4054 if (outNumPoints) *outNumPoints = newNumPoints; 4055 if (outNumIndices) *outNumIndices = newNumIndices; 4056 4057 for (f = 1; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 4058 4059 if (!outPoints && !outValues) { 4060 if (offsets) { 4061 for (f = 0; f <= numFields; f++) { 4062 offsets[f] = newOffsets[f]; 4063 } 4064 } 4065 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4066 PetscFunctionReturn(0); 4067 } 4068 4069 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 4070 4071 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 4072 4073 /* workspaces */ 4074 if (numFields) { 4075 for (f = 0; f < numFields; f++) { 4076 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4077 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4078 } 4079 } 4080 else { 4081 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4082 ierr = DMGetWorkArray(dm,numPoints,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4083 } 4084 4085 /* get workspaces for the point-to-point matrices */ 4086 if (numFields) { 4087 PetscInt totalOffset, totalMatOffset; 4088 4089 for (p = 0; p < numPoints; p++) { 4090 PetscInt b = points[2*p]; 4091 PetscInt bDof = 0, bSecDof; 4092 4093 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4094 if (!bSecDof) { 4095 for (f = 0; f < numFields; f++) { 4096 newPointOffsets[f][p + 1] = 0; 4097 pointMatOffsets[f][p + 1] = 0; 4098 } 4099 continue; 4100 } 4101 if (b >= aStart && b < aEnd) { 4102 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4103 } 4104 if (bDof) { 4105 for (f = 0; f < numFields; f++) { 4106 PetscInt fDof, q, bOff, allFDof = 0; 4107 4108 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4109 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4110 for (q = 0; q < bDof; q++) { 4111 PetscInt a = anchors[bOff + q]; 4112 PetscInt aFDof; 4113 4114 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 4115 allFDof += aFDof; 4116 } 4117 newPointOffsets[f][p+1] = allFDof; 4118 pointMatOffsets[f][p+1] = fDof * allFDof; 4119 } 4120 } 4121 else { 4122 for (f = 0; f < numFields; f++) { 4123 PetscInt fDof; 4124 4125 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4126 newPointOffsets[f][p+1] = fDof; 4127 pointMatOffsets[f][p+1] = 0; 4128 } 4129 } 4130 } 4131 for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 4132 newPointOffsets[f][0] = totalOffset; 4133 pointMatOffsets[f][0] = totalMatOffset; 4134 for (p = 0; p < numPoints; p++) { 4135 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 4136 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 4137 } 4138 totalOffset = newPointOffsets[f][numPoints]; 4139 totalMatOffset = pointMatOffsets[f][numPoints]; 4140 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4141 } 4142 } 4143 else { 4144 for (p = 0; p < numPoints; p++) { 4145 PetscInt b = points[2*p]; 4146 PetscInt bDof = 0, bSecDof; 4147 4148 ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 4149 if (!bSecDof) { 4150 newPointOffsets[0][p + 1] = 0; 4151 pointMatOffsets[0][p + 1] = 0; 4152 continue; 4153 } 4154 if (b >= aStart && b < aEnd) { 4155 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4156 } 4157 if (bDof) { 4158 PetscInt bOff, q, allDof = 0; 4159 4160 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4161 for (q = 0; q < bDof; q++) { 4162 PetscInt a = anchors[bOff + q], aDof; 4163 4164 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 4165 allDof += aDof; 4166 } 4167 newPointOffsets[0][p+1] = allDof; 4168 pointMatOffsets[0][p+1] = bSecDof * allDof; 4169 } 4170 else { 4171 newPointOffsets[0][p+1] = bSecDof; 4172 pointMatOffsets[0][p+1] = 0; 4173 } 4174 } 4175 newPointOffsets[0][0] = 0; 4176 pointMatOffsets[0][0] = 0; 4177 for (p = 0; p < numPoints; p++) { 4178 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 4179 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 4180 } 4181 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4182 } 4183 4184 /* output arrays */ 4185 ierr = DMGetWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4186 4187 /* get the point-to-point matrices; construct newPoints */ 4188 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 4189 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 4190 ierr = DMGetWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4191 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4192 if (numFields) { 4193 for (p = 0, newP = 0; p < numPoints; p++) { 4194 PetscInt b = points[2*p]; 4195 PetscInt o = points[2*p+1]; 4196 PetscInt bDof = 0, bSecDof; 4197 4198 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 4199 if (!bSecDof) { 4200 continue; 4201 } 4202 if (b >= aStart && b < aEnd) { 4203 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4204 } 4205 if (bDof) { 4206 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 4207 4208 fStart[0] = 0; 4209 fEnd[0] = 0; 4210 for (f = 0; f < numFields; f++) { 4211 PetscInt fDof; 4212 4213 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 4214 fStart[f+1] = fStart[f] + fDof; 4215 fEnd[f+1] = fStart[f+1]; 4216 } 4217 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4218 ierr = indicesPointFields_private(cSec, b, bOff, fEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4219 4220 fAnchorStart[0] = 0; 4221 fAnchorEnd[0] = 0; 4222 for (f = 0; f < numFields; f++) { 4223 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 4224 4225 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 4226 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 4227 } 4228 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4229 for (q = 0; q < bDof; q++) { 4230 PetscInt a = anchors[bOff + q], aOff; 4231 4232 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4233 newPoints[2*(newP + q)] = a; 4234 newPoints[2*(newP + q) + 1] = 0; 4235 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4236 ierr = indicesPointFields_private(section, a, aOff, fAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4237 } 4238 newP += bDof; 4239 4240 if (outValues) { 4241 /* get the point-to-point submatrix */ 4242 for (f = 0; f < numFields; f++) { 4243 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 4244 } 4245 } 4246 } 4247 else { 4248 newPoints[2 * newP] = b; 4249 newPoints[2 * newP + 1] = o; 4250 newP++; 4251 } 4252 } 4253 } else { 4254 for (p = 0; p < numPoints; p++) { 4255 PetscInt b = points[2*p]; 4256 PetscInt o = points[2*p+1]; 4257 PetscInt bDof = 0, bSecDof; 4258 4259 ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 4260 if (!bSecDof) { 4261 continue; 4262 } 4263 if (b >= aStart && b < aEnd) { 4264 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4265 } 4266 if (bDof) { 4267 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 4268 4269 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4270 ierr = indicesPoint_private(cSec, b, bOff, &bEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4271 4272 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4273 for (q = 0; q < bDof; q++) { 4274 PetscInt a = anchors[bOff + q], aOff; 4275 4276 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4277 4278 newPoints[2*(newP + q)] = a; 4279 newPoints[2*(newP + q) + 1] = 0; 4280 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4281 ierr = indicesPoint_private(section, a, aOff, &bAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4282 } 4283 newP += bDof; 4284 4285 /* get the point-to-point submatrix */ 4286 if (outValues) { 4287 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 4288 } 4289 } 4290 else { 4291 newPoints[2 * newP] = b; 4292 newPoints[2 * newP + 1] = o; 4293 newP++; 4294 } 4295 } 4296 } 4297 4298 if (outValues) { 4299 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4300 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 4301 /* multiply constraints on the right */ 4302 if (numFields) { 4303 for (f = 0; f < numFields; f++) { 4304 PetscInt oldOff = offsets[f]; 4305 4306 for (p = 0; p < numPoints; p++) { 4307 PetscInt cStart = newPointOffsets[f][p]; 4308 PetscInt b = points[2 * p]; 4309 PetscInt c, r, k; 4310 PetscInt dof; 4311 4312 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4313 if (!dof) { 4314 continue; 4315 } 4316 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4317 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 4318 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 4319 4320 for (r = 0; r < numIndices; r++) { 4321 for (c = 0; c < nCols; c++) { 4322 for (k = 0; k < dof; k++) { 4323 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4324 } 4325 } 4326 } 4327 } 4328 else { 4329 /* copy this column as is */ 4330 for (r = 0; r < numIndices; r++) { 4331 for (c = 0; c < dof; c++) { 4332 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4333 } 4334 } 4335 } 4336 oldOff += dof; 4337 } 4338 } 4339 } 4340 else { 4341 PetscInt oldOff = 0; 4342 for (p = 0; p < numPoints; p++) { 4343 PetscInt cStart = newPointOffsets[0][p]; 4344 PetscInt b = points[2 * p]; 4345 PetscInt c, r, k; 4346 PetscInt dof; 4347 4348 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4349 if (!dof) { 4350 continue; 4351 } 4352 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4353 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 4354 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 4355 4356 for (r = 0; r < numIndices; r++) { 4357 for (c = 0; c < nCols; c++) { 4358 for (k = 0; k < dof; k++) { 4359 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4360 } 4361 } 4362 } 4363 } 4364 else { 4365 /* copy this column as is */ 4366 for (r = 0; r < numIndices; r++) { 4367 for (c = 0; c < dof; c++) { 4368 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4369 } 4370 } 4371 } 4372 oldOff += dof; 4373 } 4374 } 4375 4376 if (multiplyLeft) { 4377 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4378 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 4379 /* multiply constraints transpose on the left */ 4380 if (numFields) { 4381 for (f = 0; f < numFields; f++) { 4382 PetscInt oldOff = offsets[f]; 4383 4384 for (p = 0; p < numPoints; p++) { 4385 PetscInt rStart = newPointOffsets[f][p]; 4386 PetscInt b = points[2 * p]; 4387 PetscInt c, r, k; 4388 PetscInt dof; 4389 4390 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4391 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4392 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 4393 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 4394 4395 for (r = 0; r < nRows; r++) { 4396 for (c = 0; c < newNumIndices; c++) { 4397 for (k = 0; k < dof; k++) { 4398 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4399 } 4400 } 4401 } 4402 } 4403 else { 4404 /* copy this row as is */ 4405 for (r = 0; r < dof; r++) { 4406 for (c = 0; c < newNumIndices; c++) { 4407 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4408 } 4409 } 4410 } 4411 oldOff += dof; 4412 } 4413 } 4414 } 4415 else { 4416 PetscInt oldOff = 0; 4417 4418 for (p = 0; p < numPoints; p++) { 4419 PetscInt rStart = newPointOffsets[0][p]; 4420 PetscInt b = points[2 * p]; 4421 PetscInt c, r, k; 4422 PetscInt dof; 4423 4424 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4425 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4426 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 4427 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 4428 4429 for (r = 0; r < nRows; r++) { 4430 for (c = 0; c < newNumIndices; c++) { 4431 for (k = 0; k < dof; k++) { 4432 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4433 } 4434 } 4435 } 4436 } 4437 else { 4438 /* copy this row as is */ 4439 for (r = 0; r < dof; c++) { 4440 for (c = 0; c < newNumIndices; c++) { 4441 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4442 } 4443 } 4444 } 4445 oldOff += dof; 4446 } 4447 } 4448 4449 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4450 } 4451 else { 4452 newValues = tmpValues; 4453 } 4454 } 4455 4456 /* clean up */ 4457 ierr = DMRestoreWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4458 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4459 4460 if (numFields) { 4461 for (f = 0; f < numFields; f++) { 4462 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4463 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4464 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4465 } 4466 } 4467 else { 4468 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4469 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4470 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4471 } 4472 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4473 4474 /* output */ 4475 if (outPoints) { 4476 *outPoints = newPoints; 4477 } 4478 else { 4479 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4480 } 4481 if (*outValues) { 4482 *outValues = newValues; 4483 } 4484 for (f = 0; f <= numFields; f++) { 4485 offsets[f] = newOffsets[f]; 4486 } 4487 PetscFunctionReturn(0); 4488 } 4489 4490 #undef __FUNCT__ 4491 #define __FUNCT__ "DMPlexGetClosureIndices" 4492 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices, PetscInt *outOffsets) 4493 { 4494 PetscSection clSection; 4495 IS clPoints; 4496 const PetscInt *clp; 4497 PetscInt *points = NULL, *pointsNew; 4498 PetscInt numPoints, numPointsNew; 4499 PetscInt offsets[32]; 4500 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 4501 PetscErrorCode ierr; 4502 4503 PetscFunctionBegin; 4504 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4505 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4506 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4507 if (numIndices) PetscValidPointer(numIndices, 4); 4508 PetscValidPointer(indices, 5); 4509 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4510 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 4511 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4512 /* Get points in closure */ 4513 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4514 if (!clPoints) { 4515 PetscInt pStart, pEnd, q; 4516 4517 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4518 /* Compress out points not in the section */ 4519 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4520 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4521 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4522 points[q*2] = points[p]; 4523 points[q*2+1] = points[p+1]; 4524 ++q; 4525 } 4526 } 4527 numPoints = q; 4528 } else { 4529 PetscInt dof, off; 4530 4531 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4532 numPoints = dof/2; 4533 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4534 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4535 points = (PetscInt *) &clp[off]; 4536 } 4537 /* Get number of indices and indices per field */ 4538 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 4539 PetscInt dof, fdof; 4540 4541 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4542 for (f = 0; f < Nf; ++f) { 4543 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4544 offsets[f+1] += fdof; 4545 } 4546 Nind += dof; 4547 } 4548 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 4549 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[Nf], Nind); 4550 /* Correct for hanging node constraints */ 4551 { 4552 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 4553 if (numPointsNew) { 4554 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4555 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4556 numPoints = numPointsNew; 4557 Nind = NindNew; 4558 points = pointsNew; 4559 } 4560 } 4561 /* Calculate indices */ 4562 ierr = DMGetWorkArray(dm, Nind, PETSC_INT, indices);CHKERRQ(ierr); 4563 if (Nf) { 4564 if (outOffsets) { 4565 PetscInt f; 4566 4567 for (f = 0; f < Nf; f++) { 4568 outOffsets[f] = offsets[f]; 4569 } 4570 } 4571 for (p = 0; p < numPoints*2; p += 2) { 4572 PetscInt o = points[p+1]; 4573 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4574 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, *indices); 4575 } 4576 } else { 4577 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4578 PetscInt o = points[p+1]; 4579 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4580 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, *indices); 4581 } 4582 } 4583 /* Cleanup points */ 4584 if (numPointsNew) { 4585 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, PETSC_INT, &pointsNew);CHKERRQ(ierr); 4586 } else { 4587 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4588 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4589 } 4590 if (numIndices) *numIndices = Nind; 4591 PetscFunctionReturn(0); 4592 } 4593 4594 #undef __FUNCT__ 4595 #define __FUNCT__ "DMPlexRestoreClosureIndices" 4596 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices) 4597 { 4598 PetscErrorCode ierr; 4599 4600 PetscFunctionBegin; 4601 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4602 PetscValidPointer(indices, 5); 4603 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, indices);CHKERRQ(ierr); 4604 PetscFunctionReturn(0); 4605 } 4606 4607 #undef __FUNCT__ 4608 #define __FUNCT__ "DMPlexMatSetClosure" 4609 /*@C 4610 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 4611 4612 Not collective 4613 4614 Input Parameters: 4615 + dm - The DM 4616 . section - The section describing the layout in v, or NULL to use the default section 4617 . globalSection - The section describing the layout in v, or NULL to use the default global section 4618 . A - The matrix 4619 . point - The sieve point in the DM 4620 . values - The array of values 4621 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 4622 4623 Fortran Notes: 4624 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4625 4626 Level: intermediate 4627 4628 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 4629 @*/ 4630 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4631 { 4632 DM_Plex *mesh = (DM_Plex*) dm->data; 4633 PetscSection clSection; 4634 IS clPoints; 4635 PetscInt *points = NULL, *newPoints; 4636 const PetscInt *clp; 4637 PetscInt *indices; 4638 PetscInt offsets[32]; 4639 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 4640 PetscScalar *newValues; 4641 PetscErrorCode ierr; 4642 4643 PetscFunctionBegin; 4644 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4645 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4646 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4647 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 4648 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4649 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 4650 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4651 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4652 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4653 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4654 if (!clPoints) { 4655 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4656 /* Compress out points not in the section */ 4657 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4658 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4659 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4660 points[q*2] = points[p]; 4661 points[q*2+1] = points[p+1]; 4662 ++q; 4663 } 4664 } 4665 numPoints = q; 4666 } else { 4667 PetscInt dof, off; 4668 4669 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4670 numPoints = dof/2; 4671 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4672 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4673 points = (PetscInt *) &clp[off]; 4674 } 4675 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 4676 PetscInt fdof; 4677 4678 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4679 for (f = 0; f < numFields; ++f) { 4680 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4681 offsets[f+1] += fdof; 4682 } 4683 numIndices += dof; 4684 } 4685 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 4686 4687 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 4688 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets,PETSC_TRUE);CHKERRQ(ierr); 4689 if (newNumPoints) { 4690 if (!clPoints) { 4691 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4692 } else { 4693 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4694 } 4695 numPoints = newNumPoints; 4696 numIndices = newNumIndices; 4697 points = newPoints; 4698 values = newValues; 4699 } 4700 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4701 if (numFields) { 4702 for (p = 0; p < numPoints*2; p += 2) { 4703 PetscInt o = points[p+1]; 4704 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4705 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 4706 } 4707 } else { 4708 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4709 PetscInt o = points[p+1]; 4710 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4711 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 4712 } 4713 } 4714 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 4715 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 4716 if (mesh->printFEM > 1) { 4717 PetscInt i; 4718 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 4719 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %d", indices[i]);CHKERRQ(ierr);} 4720 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 4721 } 4722 if (ierr) { 4723 PetscMPIInt rank; 4724 PetscErrorCode ierr2; 4725 4726 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 4727 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 4728 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 4729 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 4730 CHKERRQ(ierr); 4731 } 4732 if (newNumPoints) { 4733 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4734 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4735 } 4736 else { 4737 if (!clPoints) { 4738 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4739 } else { 4740 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4741 } 4742 } 4743 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4744 PetscFunctionReturn(0); 4745 } 4746 4747 #undef __FUNCT__ 4748 #define __FUNCT__ "DMPlexMatSetClosureRefined" 4749 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4750 { 4751 DM_Plex *mesh = (DM_Plex*) dmf->data; 4752 PetscInt *fpoints = NULL, *ftotpoints = NULL; 4753 PetscInt *cpoints = NULL; 4754 PetscInt *findices, *cindices; 4755 PetscInt foffsets[32], coffsets[32]; 4756 CellRefiner cellRefiner; 4757 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 4758 PetscErrorCode ierr; 4759 4760 PetscFunctionBegin; 4761 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 4762 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 4763 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 4764 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 4765 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 4766 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 4767 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 4768 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 4769 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 4770 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 4771 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 4772 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 4773 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4774 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4775 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4776 /* Column indices */ 4777 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4778 maxFPoints = numCPoints; 4779 /* Compress out points not in the section */ 4780 /* TODO: Squeeze out points with 0 dof as well */ 4781 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 4782 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 4783 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 4784 cpoints[q*2] = cpoints[p]; 4785 cpoints[q*2+1] = cpoints[p+1]; 4786 ++q; 4787 } 4788 } 4789 numCPoints = q; 4790 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 4791 PetscInt fdof; 4792 4793 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 4794 if (!dof) continue; 4795 for (f = 0; f < numFields; ++f) { 4796 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 4797 coffsets[f+1] += fdof; 4798 } 4799 numCIndices += dof; 4800 } 4801 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 4802 /* Row indices */ 4803 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 4804 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 4805 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4806 for (r = 0, q = 0; r < numSubcells; ++r) { 4807 /* TODO Map from coarse to fine cells */ 4808 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4809 /* Compress out points not in the section */ 4810 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 4811 for (p = 0; p < numFPoints*2; p += 2) { 4812 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 4813 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 4814 if (!dof) continue; 4815 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 4816 if (s < q) continue; 4817 ftotpoints[q*2] = fpoints[p]; 4818 ftotpoints[q*2+1] = fpoints[p+1]; 4819 ++q; 4820 } 4821 } 4822 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4823 } 4824 numFPoints = q; 4825 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 4826 PetscInt fdof; 4827 4828 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 4829 if (!dof) continue; 4830 for (f = 0; f < numFields; ++f) { 4831 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 4832 foffsets[f+1] += fdof; 4833 } 4834 numFIndices += dof; 4835 } 4836 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 4837 4838 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 4839 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 4840 ierr = DMGetWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 4841 ierr = DMGetWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 4842 if (numFields) { 4843 for (p = 0; p < numFPoints*2; p += 2) { 4844 PetscInt o = ftotpoints[p+1]; 4845 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4846 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 4847 } 4848 for (p = 0; p < numCPoints*2; p += 2) { 4849 PetscInt o = cpoints[p+1]; 4850 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4851 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 4852 } 4853 } else { 4854 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 4855 PetscInt o = ftotpoints[p+1]; 4856 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4857 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 4858 } 4859 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 4860 PetscInt o = cpoints[p+1]; 4861 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4862 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 4863 } 4864 } 4865 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 4866 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 4867 if (ierr) { 4868 PetscMPIInt rank; 4869 PetscErrorCode ierr2; 4870 4871 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 4872 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 4873 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 4874 ierr2 = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr2); 4875 ierr2 = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr2); 4876 CHKERRQ(ierr); 4877 } 4878 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4879 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4880 ierr = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 4881 ierr = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 4882 PetscFunctionReturn(0); 4883 } 4884 4885 #undef __FUNCT__ 4886 #define __FUNCT__ "DMPlexMatGetClosureIndicesRefined" 4887 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 4888 { 4889 PetscInt *fpoints = NULL, *ftotpoints = NULL; 4890 PetscInt *cpoints = NULL; 4891 PetscInt foffsets[32], coffsets[32]; 4892 CellRefiner cellRefiner; 4893 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 4894 PetscErrorCode ierr; 4895 4896 PetscFunctionBegin; 4897 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 4898 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 4899 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 4900 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 4901 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 4902 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 4903 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 4904 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 4905 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 4906 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 4907 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 4908 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4909 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4910 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4911 /* Column indices */ 4912 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4913 maxFPoints = numCPoints; 4914 /* Compress out points not in the section */ 4915 /* TODO: Squeeze out points with 0 dof as well */ 4916 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 4917 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 4918 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 4919 cpoints[q*2] = cpoints[p]; 4920 cpoints[q*2+1] = cpoints[p+1]; 4921 ++q; 4922 } 4923 } 4924 numCPoints = q; 4925 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 4926 PetscInt fdof; 4927 4928 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 4929 if (!dof) continue; 4930 for (f = 0; f < numFields; ++f) { 4931 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 4932 coffsets[f+1] += fdof; 4933 } 4934 numCIndices += dof; 4935 } 4936 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 4937 /* Row indices */ 4938 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 4939 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 4940 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4941 for (r = 0, q = 0; r < numSubcells; ++r) { 4942 /* TODO Map from coarse to fine cells */ 4943 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4944 /* Compress out points not in the section */ 4945 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 4946 for (p = 0; p < numFPoints*2; p += 2) { 4947 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 4948 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 4949 if (!dof) continue; 4950 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 4951 if (s < q) continue; 4952 ftotpoints[q*2] = fpoints[p]; 4953 ftotpoints[q*2+1] = fpoints[p+1]; 4954 ++q; 4955 } 4956 } 4957 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4958 } 4959 numFPoints = q; 4960 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 4961 PetscInt fdof; 4962 4963 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 4964 if (!dof) continue; 4965 for (f = 0; f < numFields; ++f) { 4966 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 4967 foffsets[f+1] += fdof; 4968 } 4969 numFIndices += dof; 4970 } 4971 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 4972 4973 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 4974 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 4975 if (numFields) { 4976 for (p = 0; p < numFPoints*2; p += 2) { 4977 PetscInt o = ftotpoints[p+1]; 4978 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4979 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 4980 } 4981 for (p = 0; p < numCPoints*2; p += 2) { 4982 PetscInt o = cpoints[p+1]; 4983 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4984 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 4985 } 4986 } else { 4987 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 4988 PetscInt o = ftotpoints[p+1]; 4989 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4990 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 4991 } 4992 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 4993 PetscInt o = cpoints[p+1]; 4994 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4995 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 4996 } 4997 } 4998 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4999 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5000 PetscFunctionReturn(0); 5001 } 5002 5003 #undef __FUNCT__ 5004 #define __FUNCT__ "DMPlexGetHybridBounds" 5005 /*@ 5006 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 5007 5008 Input Parameter: 5009 . dm - The DMPlex object 5010 5011 Output Parameters: 5012 + cMax - The first hybrid cell 5013 . fMax - The first hybrid face 5014 . eMax - The first hybrid edge 5015 - vMax - The first hybrid vertex 5016 5017 Level: developer 5018 5019 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 5020 @*/ 5021 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 5022 { 5023 DM_Plex *mesh = (DM_Plex*) dm->data; 5024 PetscInt dim; 5025 PetscErrorCode ierr; 5026 5027 PetscFunctionBegin; 5028 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5029 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5030 if (cMax) *cMax = mesh->hybridPointMax[dim]; 5031 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 5032 if (eMax) *eMax = mesh->hybridPointMax[1]; 5033 if (vMax) *vMax = mesh->hybridPointMax[0]; 5034 PetscFunctionReturn(0); 5035 } 5036 5037 #undef __FUNCT__ 5038 #define __FUNCT__ "DMPlexSetHybridBounds" 5039 /*@ 5040 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 5041 5042 Input Parameters: 5043 . dm - The DMPlex object 5044 . cMax - The first hybrid cell 5045 . fMax - The first hybrid face 5046 . eMax - The first hybrid edge 5047 - vMax - The first hybrid vertex 5048 5049 Level: developer 5050 5051 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 5052 @*/ 5053 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 5054 { 5055 DM_Plex *mesh = (DM_Plex*) dm->data; 5056 PetscInt dim; 5057 PetscErrorCode ierr; 5058 5059 PetscFunctionBegin; 5060 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5061 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5062 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 5063 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 5064 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 5065 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 5066 PetscFunctionReturn(0); 5067 } 5068 5069 #undef __FUNCT__ 5070 #define __FUNCT__ "DMPlexGetVTKCellHeight" 5071 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 5072 { 5073 DM_Plex *mesh = (DM_Plex*) dm->data; 5074 5075 PetscFunctionBegin; 5076 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5077 PetscValidPointer(cellHeight, 2); 5078 *cellHeight = mesh->vtkCellHeight; 5079 PetscFunctionReturn(0); 5080 } 5081 5082 #undef __FUNCT__ 5083 #define __FUNCT__ "DMPlexSetVTKCellHeight" 5084 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 5085 { 5086 DM_Plex *mesh = (DM_Plex*) dm->data; 5087 5088 PetscFunctionBegin; 5089 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5090 mesh->vtkCellHeight = cellHeight; 5091 PetscFunctionReturn(0); 5092 } 5093 5094 #undef __FUNCT__ 5095 #define __FUNCT__ "DMPlexCreateNumbering_Private" 5096 /* We can easily have a form that takes an IS instead */ 5097 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 5098 { 5099 PetscSection section, globalSection; 5100 PetscInt *numbers, p; 5101 PetscErrorCode ierr; 5102 5103 PetscFunctionBegin; 5104 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5105 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 5106 for (p = pStart; p < pEnd; ++p) { 5107 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 5108 } 5109 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 5110 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 5111 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 5112 for (p = pStart; p < pEnd; ++p) { 5113 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 5114 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 5115 else numbers[p-pStart] += shift; 5116 } 5117 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 5118 if (globalSize) { 5119 PetscLayout layout; 5120 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 5121 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 5122 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 5123 } 5124 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5125 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 5126 PetscFunctionReturn(0); 5127 } 5128 5129 #undef __FUNCT__ 5130 #define __FUNCT__ "DMPlexGetCellNumbering" 5131 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 5132 { 5133 DM_Plex *mesh = (DM_Plex*) dm->data; 5134 PetscInt cellHeight, cStart, cEnd, cMax; 5135 PetscErrorCode ierr; 5136 5137 PetscFunctionBegin; 5138 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5139 if (!mesh->globalCellNumbers) { 5140 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 5141 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5142 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5143 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 5144 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 5145 } 5146 *globalCellNumbers = mesh->globalCellNumbers; 5147 PetscFunctionReturn(0); 5148 } 5149 5150 #undef __FUNCT__ 5151 #define __FUNCT__ "DMPlexGetVertexNumbering" 5152 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 5153 { 5154 DM_Plex *mesh = (DM_Plex*) dm->data; 5155 PetscInt vStart, vEnd, vMax; 5156 PetscErrorCode ierr; 5157 5158 PetscFunctionBegin; 5159 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5160 if (!mesh->globalVertexNumbers) { 5161 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5162 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 5163 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 5164 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 5165 } 5166 *globalVertexNumbers = mesh->globalVertexNumbers; 5167 PetscFunctionReturn(0); 5168 } 5169 5170 #undef __FUNCT__ 5171 #define __FUNCT__ "DMPlexCreatePointNumbering" 5172 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 5173 { 5174 IS nums[4]; 5175 PetscInt depths[4]; 5176 PetscInt depth, d, shift = 0; 5177 PetscErrorCode ierr; 5178 5179 PetscFunctionBegin; 5180 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5181 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5182 /* For unstratified meshes use dim instead of depth */ 5183 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 5184 depths[0] = depth; depths[1] = 0; 5185 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 5186 for (d = 0; d <= depth; ++d) { 5187 PetscInt pStart, pEnd, gsize; 5188 5189 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 5190 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 5191 shift += gsize; 5192 } 5193 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 5194 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 5195 PetscFunctionReturn(0); 5196 } 5197 5198 #undef __FUNCT__ 5199 #define __FUNCT__ "DMPlexCheckSymmetry" 5200 /*@ 5201 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 5202 5203 Input Parameters: 5204 + dm - The DMPlex object 5205 5206 Note: This is a useful diagnostic when creating meshes programmatically. 5207 5208 Level: developer 5209 5210 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 5211 @*/ 5212 PetscErrorCode DMPlexCheckSymmetry(DM dm) 5213 { 5214 PetscSection coneSection, supportSection; 5215 const PetscInt *cone, *support; 5216 PetscInt coneSize, c, supportSize, s; 5217 PetscInt pStart, pEnd, p, csize, ssize; 5218 PetscErrorCode ierr; 5219 5220 PetscFunctionBegin; 5221 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5222 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 5223 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 5224 /* Check that point p is found in the support of its cone points, and vice versa */ 5225 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5226 for (p = pStart; p < pEnd; ++p) { 5227 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5228 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5229 for (c = 0; c < coneSize; ++c) { 5230 PetscBool dup = PETSC_FALSE; 5231 PetscInt d; 5232 for (d = c-1; d >= 0; --d) { 5233 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 5234 } 5235 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 5236 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 5237 for (s = 0; s < supportSize; ++s) { 5238 if (support[s] == p) break; 5239 } 5240 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 5241 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", p);CHKERRQ(ierr); 5242 for (s = 0; s < coneSize; ++s) { 5243 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[s]);CHKERRQ(ierr); 5244 } 5245 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5246 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", cone[c]);CHKERRQ(ierr); 5247 for (s = 0; s < supportSize; ++s) { 5248 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[s]);CHKERRQ(ierr); 5249 } 5250 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5251 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not repeatedly found in support of repeated cone point %d", p, cone[c]); 5252 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in support of cone point %d", p, cone[c]); 5253 } 5254 } 5255 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 5256 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 5257 for (s = 0; s < supportSize; ++s) { 5258 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5259 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5260 for (c = 0; c < coneSize; ++c) { 5261 if (cone[c] == p) break; 5262 } 5263 if (c >= coneSize) { 5264 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", p);CHKERRQ(ierr); 5265 for (c = 0; c < supportSize; ++c) { 5266 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[c]);CHKERRQ(ierr); 5267 } 5268 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5269 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", support[s]);CHKERRQ(ierr); 5270 for (c = 0; c < coneSize; ++c) { 5271 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[c]);CHKERRQ(ierr); 5272 } 5273 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5274 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in cone of support point %d", p, support[s]); 5275 } 5276 } 5277 } 5278 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 5279 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 5280 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %d != Total support size %d", csize, ssize); 5281 PetscFunctionReturn(0); 5282 } 5283 5284 #undef __FUNCT__ 5285 #define __FUNCT__ "DMPlexCheckSkeleton" 5286 /*@ 5287 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 5288 5289 Input Parameters: 5290 + dm - The DMPlex object 5291 . isSimplex - Are the cells simplices or tensor products 5292 - cellHeight - Normally 0 5293 5294 Note: This is a useful diagnostic when creating meshes programmatically. 5295 5296 Level: developer 5297 5298 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 5299 @*/ 5300 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5301 { 5302 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 5303 PetscErrorCode ierr; 5304 5305 PetscFunctionBegin; 5306 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5307 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5308 switch (dim) { 5309 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 5310 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 5311 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 5312 default: 5313 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %d", dim); 5314 } 5315 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5316 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5317 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5318 cMax = cMax >= 0 ? cMax : cEnd; 5319 for (c = cStart; c < cMax; ++c) { 5320 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5321 5322 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5323 for (cl = 0; cl < closureSize*2; cl += 2) { 5324 const PetscInt p = closure[cl]; 5325 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5326 } 5327 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5328 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d vertices != %d", c, coneSize, numCorners); 5329 } 5330 for (c = cMax; c < cEnd; ++c) { 5331 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5332 5333 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5334 for (cl = 0; cl < closureSize*2; cl += 2) { 5335 const PetscInt p = closure[cl]; 5336 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5337 } 5338 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5339 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %d has %d vertices > %d", c, coneSize, numHybridCorners); 5340 } 5341 PetscFunctionReturn(0); 5342 } 5343 5344 #undef __FUNCT__ 5345 #define __FUNCT__ "DMPlexCheckFaces" 5346 /*@ 5347 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 5348 5349 Input Parameters: 5350 + dm - The DMPlex object 5351 . isSimplex - Are the cells simplices or tensor products 5352 - cellHeight - Normally 0 5353 5354 Note: This is a useful diagnostic when creating meshes programmatically. 5355 5356 Level: developer 5357 5358 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 5359 @*/ 5360 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5361 { 5362 PetscInt pMax[4]; 5363 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 5364 PetscErrorCode ierr; 5365 5366 PetscFunctionBegin; 5367 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5368 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5369 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5370 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 5371 for (h = cellHeight; h < dim; ++h) { 5372 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 5373 for (c = cStart; c < cEnd; ++c) { 5374 const PetscInt *cone, *ornt, *faces; 5375 PetscInt numFaces, faceSize, coneSize,f; 5376 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 5377 5378 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 5379 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 5380 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5381 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5382 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5383 for (cl = 0; cl < closureSize*2; cl += 2) { 5384 const PetscInt p = closure[cl]; 5385 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 5386 } 5387 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5388 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d faces but should have %d", c, coneSize, numFaces); 5389 for (f = 0; f < numFaces; ++f) { 5390 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 5391 5392 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5393 for (cl = 0; cl < fclosureSize*2; cl += 2) { 5394 const PetscInt p = fclosure[cl]; 5395 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 5396 } 5397 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); 5398 for (v = 0; v < fnumCorners; ++v) { 5399 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]); 5400 } 5401 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5402 } 5403 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5404 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5405 } 5406 } 5407 PetscFunctionReturn(0); 5408 } 5409 5410 #undef __FUNCT__ 5411 #define __FUNCT__ "DMCreateInterpolation_Plex" 5412 /* Pointwise interpolation 5413 Just code FEM for now 5414 u^f = I u^c 5415 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 5416 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 5417 I_{ij} = psi^f_i phi^c_j 5418 */ 5419 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 5420 { 5421 PetscSection gsc, gsf; 5422 PetscInt m, n; 5423 void *ctx; 5424 DM cdm; 5425 PetscBool regular; 5426 PetscErrorCode ierr; 5427 5428 PetscFunctionBegin; 5429 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 5430 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 5431 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 5432 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 5433 5434 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 5435 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5436 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 5437 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 5438 5439 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 5440 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 5441 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5442 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5443 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 5444 /* Use naive scaling */ 5445 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 5446 PetscFunctionReturn(0); 5447 } 5448 5449 #undef __FUNCT__ 5450 #define __FUNCT__ "DMCreateInjection_Plex" 5451 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 5452 { 5453 PetscErrorCode ierr; 5454 VecScatter ctx; 5455 5456 PetscFunctionBegin; 5457 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 5458 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 5459 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 5460 PetscFunctionReturn(0); 5461 } 5462 5463 #undef __FUNCT__ 5464 #define __FUNCT__ "DMCreateDefaultSection_Plex" 5465 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 5466 { 5467 PetscSection section; 5468 IS *bcPoints, *bcComps; 5469 PetscBool *isFE; 5470 PetscInt *bcFields, *numComp, *numDof; 5471 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 5472 PetscInt cStart, cEnd, cEndInterior; 5473 PetscErrorCode ierr; 5474 5475 PetscFunctionBegin; 5476 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 5477 if (!numFields) PetscFunctionReturn(0); 5478 /* FE and FV boundary conditions are handled slightly differently */ 5479 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 5480 for (f = 0; f < numFields; ++f) { 5481 PetscObject obj; 5482 PetscClassId id; 5483 5484 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5485 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 5486 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 5487 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 5488 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 5489 } 5490 /* Allocate boundary point storage for FEM boundaries */ 5491 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5492 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5493 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5494 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 5495 ierr = DMGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 5496 for (bd = 0; bd < numBd; ++bd) { 5497 PetscInt field; 5498 PetscBool isEssential; 5499 5500 ierr = DMGetBoundary(dm, bd, &isEssential, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5501 if (isFE[field] && isEssential) ++numBC; 5502 } 5503 /* Add ghost cell boundaries for FVM */ 5504 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 5505 ierr = PetscCalloc3(numBC,&bcFields,numBC,&bcPoints,numBC,&bcComps);CHKERRQ(ierr); 5506 /* Constrain ghost cells for FV */ 5507 for (f = 0; f < numFields; ++f) { 5508 PetscInt *newidx, c; 5509 5510 if (isFE[f] || cEndInterior < 0) continue; 5511 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 5512 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 5513 bcFields[bc] = f; 5514 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5515 } 5516 /* Handle FEM Dirichlet boundaries */ 5517 for (bd = 0; bd < numBd; ++bd) { 5518 const char *bdLabel; 5519 DMLabel label; 5520 const PetscInt *comps; 5521 const PetscInt *values; 5522 PetscInt bd2, field, numComps, numValues; 5523 PetscBool isEssential, duplicate = PETSC_FALSE; 5524 5525 ierr = DMGetBoundary(dm, bd, &isEssential, NULL, &bdLabel, &field, &numComps, &comps, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 5526 if (!isFE[field]) continue; 5527 ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 5528 /* Only want to modify label once */ 5529 for (bd2 = 0; bd2 < bd; ++bd2) { 5530 const char *bdname; 5531 ierr = DMGetBoundary(dm, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5532 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 5533 if (duplicate) break; 5534 } 5535 if (!duplicate && (isFE[field])) { 5536 /* don't complete cells, which are just present to give orientation to the boundary */ 5537 ierr = DMPlexLabelComplete_Internal(dm, label, PETSC_FALSE);CHKERRQ(ierr); 5538 ierr = DMPlexLabelAddCells(dm, label);CHKERRQ(ierr); 5539 } 5540 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 5541 if (isEssential) { 5542 PetscInt *newidx; 5543 PetscInt n, newn = 0, p, v; 5544 5545 bcFields[bc] = field; 5546 if (numComps) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc]);CHKERRQ(ierr);} 5547 for (v = 0; v < numValues; ++v) { 5548 IS tmp; 5549 const PetscInt *idx; 5550 5551 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5552 if (!tmp) continue; 5553 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5554 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5555 if (isFE[field]) { 5556 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 5557 } else { 5558 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 5559 } 5560 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5561 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5562 } 5563 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 5564 newn = 0; 5565 for (v = 0; v < numValues; ++v) { 5566 IS tmp; 5567 const PetscInt *idx; 5568 5569 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5570 if (!tmp) continue; 5571 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5572 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5573 if (isFE[field]) { 5574 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 5575 } else { 5576 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 5577 } 5578 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5579 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5580 } 5581 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5582 } 5583 } 5584 /* Handle discretization */ 5585 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 5586 for (f = 0; f < numFields; ++f) { 5587 PetscObject obj; 5588 5589 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5590 if (isFE[f]) { 5591 PetscFE fe = (PetscFE) obj; 5592 const PetscInt *numFieldDof; 5593 PetscInt d; 5594 5595 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 5596 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 5597 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 5598 } else { 5599 PetscFV fv = (PetscFV) obj; 5600 5601 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 5602 numDof[f*(dim+1)+dim] = numComp[f]; 5603 } 5604 } 5605 for (f = 0; f < numFields; ++f) { 5606 PetscInt d; 5607 for (d = 1; d < dim; ++d) { 5608 if ((numDof[f*(dim+1)+d] > 0) && (depth < dim)) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated when unknowns are specified on edges or faces."); 5609 } 5610 } 5611 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion);CHKERRQ(ierr); 5612 for (f = 0; f < numFields; ++f) { 5613 PetscFE fe; 5614 const char *name; 5615 5616 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 5617 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 5618 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 5619 } 5620 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 5621 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5622 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);ierr = ISDestroy(&bcComps[bc]);CHKERRQ(ierr);} 5623 ierr = PetscFree3(bcFields,bcPoints,bcComps);CHKERRQ(ierr); 5624 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 5625 ierr = PetscFree(isFE);CHKERRQ(ierr); 5626 PetscFunctionReturn(0); 5627 } 5628 5629 #undef __FUNCT__ 5630 #define __FUNCT__ "DMPlexGetRegularRefinement" 5631 /*@ 5632 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 5633 5634 Input Parameter: 5635 . dm - The DMPlex object 5636 5637 Output Parameter: 5638 . regular - The flag 5639 5640 Level: intermediate 5641 5642 .seealso: DMPlexSetRegularRefinement() 5643 @*/ 5644 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 5645 { 5646 PetscFunctionBegin; 5647 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5648 PetscValidPointer(regular, 2); 5649 *regular = ((DM_Plex *) dm->data)->regularRefinement; 5650 PetscFunctionReturn(0); 5651 } 5652 5653 #undef __FUNCT__ 5654 #define __FUNCT__ "DMPlexSetRegularRefinement" 5655 /*@ 5656 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 5657 5658 Input Parameters: 5659 + dm - The DMPlex object 5660 - regular - The flag 5661 5662 Level: intermediate 5663 5664 .seealso: DMPlexGetRegularRefinement() 5665 @*/ 5666 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 5667 { 5668 PetscFunctionBegin; 5669 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5670 ((DM_Plex *) dm->data)->regularRefinement = regular; 5671 PetscFunctionReturn(0); 5672 } 5673 5674 /* anchors */ 5675 #undef __FUNCT__ 5676 #define __FUNCT__ "DMPlexGetAnchors" 5677 /*@ 5678 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 5679 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 5680 5681 not collective 5682 5683 Input Parameters: 5684 . dm - The DMPlex object 5685 5686 Output Parameters: 5687 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 5688 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 5689 5690 5691 Level: intermediate 5692 5693 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 5694 @*/ 5695 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 5696 { 5697 DM_Plex *plex = (DM_Plex *)dm->data; 5698 PetscErrorCode ierr; 5699 5700 PetscFunctionBegin; 5701 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5702 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 5703 if (anchorSection) *anchorSection = plex->anchorSection; 5704 if (anchorIS) *anchorIS = plex->anchorIS; 5705 PetscFunctionReturn(0); 5706 } 5707 5708 #undef __FUNCT__ 5709 #define __FUNCT__ "DMPlexSetAnchors" 5710 /*@ 5711 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 5712 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 5713 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 5714 5715 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 5716 DMGetConstraints() and filling in the entries in the constraint matrix. 5717 5718 collective on dm 5719 5720 Input Parameters: 5721 + dm - The DMPlex object 5722 . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. Must have a local communicator (PETSC_COMM_SELF or derivative). 5723 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 5724 5725 The reference counts of anchorSection and anchorIS are incremented. 5726 5727 Level: intermediate 5728 5729 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 5730 @*/ 5731 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 5732 { 5733 DM_Plex *plex = (DM_Plex *)dm->data; 5734 PetscMPIInt result; 5735 PetscErrorCode ierr; 5736 5737 PetscFunctionBegin; 5738 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5739 if (anchorSection) { 5740 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 5741 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 5742 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 5743 } 5744 if (anchorIS) { 5745 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 5746 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 5747 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 5748 } 5749 5750 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 5751 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 5752 plex->anchorSection = anchorSection; 5753 5754 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 5755 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 5756 plex->anchorIS = anchorIS; 5757 5758 #if defined(PETSC_USE_DEBUG) 5759 if (anchorIS && anchorSection) { 5760 PetscInt size, a, pStart, pEnd; 5761 const PetscInt *anchors; 5762 5763 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 5764 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 5765 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 5766 for (a = 0; a < size; a++) { 5767 PetscInt p; 5768 5769 p = anchors[a]; 5770 if (p >= pStart && p < pEnd) { 5771 PetscInt dof; 5772 5773 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 5774 if (dof) { 5775 PetscErrorCode ierr2; 5776 5777 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 5778 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %d cannot be constrained and an anchor",p); 5779 } 5780 } 5781 } 5782 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 5783 } 5784 #endif 5785 /* reset the generic constraints */ 5786 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 5787 PetscFunctionReturn(0); 5788 } 5789 5790 #undef __FUNCT__ 5791 #define __FUNCT__ "DMPlexCreateConstraintSection_Anchors" 5792 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 5793 { 5794 PetscSection anchorSection; 5795 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 5796 PetscErrorCode ierr; 5797 5798 PetscFunctionBegin; 5799 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5800 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 5801 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 5802 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 5803 if (numFields) { 5804 PetscInt f; 5805 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 5806 5807 for (f = 0; f < numFields; f++) { 5808 PetscInt numComp; 5809 5810 ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 5811 ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 5812 } 5813 } 5814 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 5815 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 5816 pStart = PetscMax(pStart,sStart); 5817 pEnd = PetscMin(pEnd,sEnd); 5818 pEnd = PetscMax(pStart,pEnd); 5819 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 5820 for (p = pStart; p < pEnd; p++) { 5821 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 5822 if (dof) { 5823 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 5824 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 5825 for (f = 0; f < numFields; f++) { 5826 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 5827 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 5828 } 5829 } 5830 } 5831 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 5832 PetscFunctionReturn(0); 5833 } 5834 5835 #undef __FUNCT__ 5836 #define __FUNCT__ "DMPlexCreateConstraintMatrix_Anchors" 5837 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 5838 { 5839 PetscSection aSec; 5840 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 5841 const PetscInt *anchors; 5842 PetscInt numFields, f; 5843 IS aIS; 5844 PetscErrorCode ierr; 5845 5846 PetscFunctionBegin; 5847 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5848 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 5849 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 5850 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 5851 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 5852 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 5853 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 5854 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 5855 /* cSec will be a subset of aSec and section */ 5856 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 5857 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 5858 i[0] = 0; 5859 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 5860 for (p = pStart; p < pEnd; p++) { 5861 PetscInt rDof, rOff, r; 5862 5863 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 5864 if (!rDof) continue; 5865 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 5866 if (numFields) { 5867 for (f = 0; f < numFields; f++) { 5868 annz = 0; 5869 for (r = 0; r < rDof; r++) { 5870 a = anchors[rOff + r]; 5871 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 5872 annz += aDof; 5873 } 5874 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 5875 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 5876 for (q = 0; q < dof; q++) { 5877 i[off + q + 1] = i[off + q] + annz; 5878 } 5879 } 5880 } 5881 else { 5882 annz = 0; 5883 for (q = 0; q < dof; q++) { 5884 a = anchors[off + q]; 5885 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 5886 annz += aDof; 5887 } 5888 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 5889 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 5890 for (q = 0; q < dof; q++) { 5891 i[off + q + 1] = i[off + q] + annz; 5892 } 5893 } 5894 } 5895 nnz = i[m]; 5896 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 5897 offset = 0; 5898 for (p = pStart; p < pEnd; p++) { 5899 if (numFields) { 5900 for (f = 0; f < numFields; f++) { 5901 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 5902 for (q = 0; q < dof; q++) { 5903 PetscInt rDof, rOff, r; 5904 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 5905 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 5906 for (r = 0; r < rDof; r++) { 5907 PetscInt s; 5908 5909 a = anchors[rOff + r]; 5910 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 5911 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 5912 for (s = 0; s < aDof; s++) { 5913 j[offset++] = aOff + s; 5914 } 5915 } 5916 } 5917 } 5918 } 5919 else { 5920 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 5921 for (q = 0; q < dof; q++) { 5922 PetscInt rDof, rOff, r; 5923 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 5924 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 5925 for (r = 0; r < rDof; r++) { 5926 PetscInt s; 5927 5928 a = anchors[rOff + r]; 5929 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 5930 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 5931 for (s = 0; s < aDof; s++) { 5932 j[offset++] = aOff + s; 5933 } 5934 } 5935 } 5936 } 5937 } 5938 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 5939 ierr = PetscFree(i);CHKERRQ(ierr); 5940 ierr = PetscFree(j);CHKERRQ(ierr); 5941 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 5942 PetscFunctionReturn(0); 5943 } 5944 5945 #undef __FUNCT__ 5946 #define __FUNCT__ "DMCreateDefaultConstraints_Plex" 5947 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 5948 { 5949 DM_Plex *plex = (DM_Plex *)dm->data; 5950 PetscSection anchorSection, section, cSec; 5951 Mat cMat; 5952 PetscErrorCode ierr; 5953 5954 PetscFunctionBegin; 5955 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5956 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 5957 if (anchorSection) { 5958 PetscDS ds; 5959 PetscInt nf; 5960 5961 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 5962 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 5963 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 5964 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 5965 ierr = PetscDSGetNumFields(ds,&nf);CHKERRQ(ierr); 5966 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 5967 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 5968 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 5969 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 5970 } 5971 PetscFunctionReturn(0); 5972 } 5973