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