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