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