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