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