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