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