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