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