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)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 428 ierr = PetscOptionsGetBool(((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 429 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 430 if (!useLabels) numLabels = 0; 431 ierr = PetscOptionsGetStringArray(((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)->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__ "DMPlexLocalizeCoordinate" 2538 /*@ 2539 DMPlexLocalizeCoordinate - If a mesh is periodic (a torus with lengths L_i, some of which can be infinite), project the coordinate onto [0, L_i) in each dimension. 2540 2541 Input Parameters: 2542 + dm - The DM 2543 - in - The input coordinate point (dim numbers) 2544 2545 Output Parameter: 2546 . out - The localized coordinate point 2547 2548 Level: developer 2549 2550 .seealso: DMPlexLocalizeCoordinates(), DMPlexLocalizeAddCoordinate() 2551 @*/ 2552 PetscErrorCode DMPlexLocalizeCoordinate(DM dm, const PetscScalar in[], PetscScalar out[]) 2553 { 2554 PetscInt dim, d; 2555 PetscErrorCode ierr; 2556 2557 PetscFunctionBegin; 2558 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 2559 if (!dm->maxCell) { 2560 for (d = 0; d < dim; ++d) out[d] = in[d]; 2561 } else { 2562 for (d = 0; d < dim; ++d) { 2563 out[d] = in[d] - dm->L[d]*floor(PetscRealPart(in[d])/dm->L[d]); 2564 } 2565 } 2566 PetscFunctionReturn(0); 2567 } 2568 2569 #undef __FUNCT__ 2570 #define __FUNCT__ "DMPlexLocalizeCoordinate_Internal" 2571 /* 2572 DMPlexLocalizeCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer. 2573 2574 Input Parameters: 2575 + dm - The DM 2576 . dim - The spatial dimension 2577 . anchor - The anchor point, the input point can be no more than maxCell away from it 2578 - in - The input coordinate point (dim numbers) 2579 2580 Output Parameter: 2581 . out - The localized coordinate point 2582 2583 Level: developer 2584 2585 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell 2586 2587 .seealso: DMPlexLocalizeCoordinates(), DMPlexLocalizeAddCoordinate() 2588 */ 2589 PetscErrorCode DMPlexLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 2590 { 2591 PetscInt d; 2592 2593 PetscFunctionBegin; 2594 if (!dm->maxCell) { 2595 for (d = 0; d < dim; ++d) out[d] = in[d]; 2596 } else { 2597 for (d = 0; d < dim; ++d) { 2598 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 2599 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 2600 } else { 2601 out[d] = in[d]; 2602 } 2603 } 2604 } 2605 PetscFunctionReturn(0); 2606 } 2607 #undef __FUNCT__ 2608 #define __FUNCT__ "DMPlexLocalizeCoordinateReal_Internal" 2609 PetscErrorCode DMPlexLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 2610 { 2611 PetscInt d; 2612 2613 PetscFunctionBegin; 2614 if (!dm->maxCell) { 2615 for (d = 0; d < dim; ++d) out[d] = in[d]; 2616 } else { 2617 for (d = 0; d < dim; ++d) { 2618 if (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d]) { 2619 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 2620 } else { 2621 out[d] = in[d]; 2622 } 2623 } 2624 } 2625 PetscFunctionReturn(0); 2626 } 2627 2628 #undef __FUNCT__ 2629 #define __FUNCT__ "DMPlexLocalizeAddCoordinate_Internal" 2630 /* 2631 DMPlexLocalizeAddCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer. 2632 2633 Input Parameters: 2634 + dm - The DM 2635 . dim - The spatial dimension 2636 . anchor - The anchor point, the input point can be no more than maxCell away from it 2637 . in - The input coordinate delta (dim numbers) 2638 - out - The input coordinate point (dim numbers) 2639 2640 Output Parameter: 2641 . out - The localized coordinate in + out 2642 2643 Level: developer 2644 2645 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell 2646 2647 .seealso: DMPlexLocalizeCoordinates(), DMPlexLocalizeCoordinate() 2648 */ 2649 PetscErrorCode DMPlexLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 2650 { 2651 PetscInt d; 2652 2653 PetscFunctionBegin; 2654 if (!dm->maxCell) { 2655 for (d = 0; d < dim; ++d) out[d] += in[d]; 2656 } else { 2657 for (d = 0; d < dim; ++d) { 2658 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 2659 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 2660 } else { 2661 out[d] += in[d]; 2662 } 2663 } 2664 } 2665 PetscFunctionReturn(0); 2666 } 2667 2668 #undef __FUNCT__ 2669 #define __FUNCT__ "DMPlexLocalizeCoordinates" 2670 /*@ 2671 DMPlexLocalizeCoordinates - If a mesh is periodic, create local coordinates for each cell 2672 2673 Input Parameter: 2674 . dm - The DM 2675 2676 Level: developer 2677 2678 .seealso: DMPlexLocalizeCoordinate(), DMPlexLocalizeAddCoordinate() 2679 @*/ 2680 PetscErrorCode DMPlexLocalizeCoordinates(DM dm) 2681 { 2682 PetscSection coordSection, cSection; 2683 Vec coordinates, cVec; 2684 PetscScalar *coords, *coords2, *anchor; 2685 PetscInt Nc, cStart, cEnd, c, vStart, vEnd, v, dof, d, off, off2, bs, coordSize; 2686 PetscErrorCode ierr; 2687 2688 PetscFunctionBegin; 2689 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2690 if (!dm->maxCell) PetscFunctionReturn(0); 2691 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2692 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 2693 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 2694 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 2695 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 2696 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 2697 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 2698 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 2699 ierr = PetscSectionSetChart(cSection, cStart, vEnd);CHKERRQ(ierr); 2700 for (v = vStart; v < vEnd; ++v) { 2701 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 2702 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 2703 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 2704 } 2705 for (c = cStart; c < cEnd; ++c) { 2706 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &dof, NULL);CHKERRQ(ierr); 2707 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 2708 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 2709 } 2710 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 2711 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 2712 ierr = VecCreate(PetscObjectComm((PetscObject) dm), &cVec);CHKERRQ(ierr); 2713 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 2714 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 2715 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 2716 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 2717 ierr = VecSetType(cVec,VECSTANDARD);CHKERRQ(ierr); 2718 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 2719 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 2720 for (v = vStart; v < vEnd; ++v) { 2721 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 2722 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 2723 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 2724 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 2725 } 2726 ierr = DMGetWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 2727 for (c = cStart; c < cEnd; ++c) { 2728 PetscScalar *cellCoords = NULL; 2729 PetscInt b; 2730 2731 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 2732 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 2733 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 2734 for (d = 0; d < dof/bs; ++d) {ierr = DMPlexLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 2735 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 2736 } 2737 ierr = DMRestoreWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 2738 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 2739 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 2740 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 2741 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 2742 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2743 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 2744 PetscFunctionReturn(0); 2745 } 2746 2747 #undef __FUNCT__ 2748 #define __FUNCT__ "DMPlexGetDepthLabel" 2749 /*@ 2750 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 2751 2752 Not Collective 2753 2754 Input Parameter: 2755 . dm - The DMPlex object 2756 2757 Output Parameter: 2758 . depthLabel - The DMLabel recording point depth 2759 2760 Level: developer 2761 2762 .keywords: mesh, points 2763 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2764 @*/ 2765 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 2766 { 2767 PetscErrorCode ierr; 2768 2769 PetscFunctionBegin; 2770 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2771 PetscValidPointer(depthLabel, 2); 2772 if (!dm->depthLabel) {ierr = DMGetLabel(dm, "depth", &dm->depthLabel);CHKERRQ(ierr);} 2773 *depthLabel = dm->depthLabel; 2774 PetscFunctionReturn(0); 2775 } 2776 2777 #undef __FUNCT__ 2778 #define __FUNCT__ "DMPlexGetDepth" 2779 /*@ 2780 DMPlexGetDepth - Get the depth of the DAG representing this mesh 2781 2782 Not Collective 2783 2784 Input Parameter: 2785 . dm - The DMPlex object 2786 2787 Output Parameter: 2788 . depth - The number of strata (breadth first levels) in the DAG 2789 2790 Level: developer 2791 2792 .keywords: mesh, points 2793 .seealso: DMPlexGetDepthLabel(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2794 @*/ 2795 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 2796 { 2797 DMLabel label; 2798 PetscInt d = 0; 2799 PetscErrorCode ierr; 2800 2801 PetscFunctionBegin; 2802 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2803 PetscValidPointer(depth, 2); 2804 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2805 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 2806 *depth = d-1; 2807 PetscFunctionReturn(0); 2808 } 2809 2810 #undef __FUNCT__ 2811 #define __FUNCT__ "DMPlexGetDepthStratum" 2812 /*@ 2813 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 2814 2815 Not Collective 2816 2817 Input Parameters: 2818 + dm - The DMPlex object 2819 - stratumValue - The requested depth 2820 2821 Output Parameters: 2822 + start - The first point at this depth 2823 - end - One beyond the last point at this depth 2824 2825 Level: developer 2826 2827 .keywords: mesh, points 2828 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 2829 @*/ 2830 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2831 { 2832 DMLabel label; 2833 PetscInt pStart, pEnd; 2834 PetscErrorCode ierr; 2835 2836 PetscFunctionBegin; 2837 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2838 if (start) {PetscValidPointer(start, 3); *start = 0;} 2839 if (end) {PetscValidPointer(end, 4); *end = 0;} 2840 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2841 if (pStart == pEnd) PetscFunctionReturn(0); 2842 if (stratumValue < 0) { 2843 if (start) *start = pStart; 2844 if (end) *end = pEnd; 2845 PetscFunctionReturn(0); 2846 } 2847 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2848 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 2849 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 2850 PetscFunctionReturn(0); 2851 } 2852 2853 #undef __FUNCT__ 2854 #define __FUNCT__ "DMPlexGetHeightStratum" 2855 /*@ 2856 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 2857 2858 Not Collective 2859 2860 Input Parameters: 2861 + dm - The DMPlex object 2862 - stratumValue - The requested height 2863 2864 Output Parameters: 2865 + start - The first point at this height 2866 - end - One beyond the last point at this height 2867 2868 Level: developer 2869 2870 .keywords: mesh, points 2871 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 2872 @*/ 2873 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2874 { 2875 DMLabel label; 2876 PetscInt depth, pStart, pEnd; 2877 PetscErrorCode ierr; 2878 2879 PetscFunctionBegin; 2880 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2881 if (start) {PetscValidPointer(start, 3); *start = 0;} 2882 if (end) {PetscValidPointer(end, 4); *end = 0;} 2883 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2884 if (pStart == pEnd) PetscFunctionReturn(0); 2885 if (stratumValue < 0) { 2886 if (start) *start = pStart; 2887 if (end) *end = pEnd; 2888 PetscFunctionReturn(0); 2889 } 2890 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2891 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 2892 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 2893 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 2894 PetscFunctionReturn(0); 2895 } 2896 2897 #undef __FUNCT__ 2898 #define __FUNCT__ "DMPlexCreateSectionInitial" 2899 /* Set the number of dof on each point and separate by fields */ 2900 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 2901 { 2902 PetscInt *pMax; 2903 PetscInt depth, pStart = 0, pEnd = 0; 2904 PetscInt Nf, p, d, dep, f; 2905 PetscBool *isFE; 2906 PetscErrorCode ierr; 2907 2908 PetscFunctionBegin; 2909 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 2910 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 2911 for (f = 0; f < numFields; ++f) { 2912 PetscObject obj; 2913 PetscClassId id; 2914 2915 isFE[f] = PETSC_FALSE; 2916 if (f >= Nf) continue; 2917 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 2918 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 2919 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 2920 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 2921 } 2922 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2923 if (numFields > 0) { 2924 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 2925 if (numComp) { 2926 for (f = 0; f < numFields; ++f) { 2927 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 2928 } 2929 } 2930 } 2931 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2932 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 2933 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2934 ierr = PetscMalloc1(depth+1,&pMax);CHKERRQ(ierr); 2935 ierr = DMPlexGetHybridBounds(dm, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 2936 for (dep = 0; dep <= depth; ++dep) { 2937 d = dim == depth ? dep : (!dep ? 0 : dim); 2938 ierr = DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd);CHKERRQ(ierr); 2939 pMax[dep] = pMax[dep] < 0 ? pEnd : pMax[dep]; 2940 for (p = pStart; p < pEnd; ++p) { 2941 PetscInt tot = 0; 2942 2943 for (f = 0; f < numFields; ++f) { 2944 if (isFE[f] && p >= pMax[dep]) continue; 2945 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 2946 tot += numDof[f*(dim+1)+d]; 2947 } 2948 ierr = PetscSectionSetDof(*section, p, tot);CHKERRQ(ierr); 2949 } 2950 } 2951 ierr = PetscFree(pMax);CHKERRQ(ierr); 2952 ierr = PetscFree(isFE);CHKERRQ(ierr); 2953 PetscFunctionReturn(0); 2954 } 2955 2956 #undef __FUNCT__ 2957 #define __FUNCT__ "DMPlexCreateSectionBCDof" 2958 /* Set the number of dof on each point and separate by fields 2959 If bcComps is NULL or the IS is NULL, constrain every dof on the point 2960 */ 2961 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 2962 { 2963 PetscInt numFields; 2964 PetscInt bc; 2965 PetscSection aSec; 2966 PetscErrorCode ierr; 2967 2968 PetscFunctionBegin; 2969 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 2970 for (bc = 0; bc < numBC; ++bc) { 2971 PetscInt field = 0; 2972 const PetscInt *comp; 2973 const PetscInt *idx; 2974 PetscInt Nc = -1, n, i; 2975 2976 if (numFields) field = bcField[bc]; 2977 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 2978 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 2979 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 2980 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 2981 for (i = 0; i < n; ++i) { 2982 const PetscInt p = idx[i]; 2983 PetscInt numConst; 2984 2985 if (numFields) { 2986 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 2987 } else { 2988 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 2989 } 2990 /* If Nc < 0, constrain every dof on the point */ 2991 if (Nc > 0) numConst = PetscMin(numConst, Nc); 2992 if (numFields) {ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr);} 2993 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 2994 } 2995 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 2996 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 2997 } 2998 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 2999 if (aSec) { 3000 PetscInt aStart, aEnd, a; 3001 3002 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3003 for (a = aStart; a < aEnd; a++) { 3004 PetscInt dof, f; 3005 3006 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3007 if (dof) { 3008 /* if there are point-to-point constraints, then all dofs are constrained */ 3009 ierr = PetscSectionGetDof(section, a, &dof);CHKERRQ(ierr); 3010 ierr = PetscSectionSetConstraintDof(section, a, dof);CHKERRQ(ierr); 3011 for (f = 0; f < numFields; f++) { 3012 ierr = PetscSectionGetFieldDof(section, a, f, &dof);CHKERRQ(ierr); 3013 ierr = PetscSectionSetFieldConstraintDof(section, a, f, dof);CHKERRQ(ierr); 3014 } 3015 } 3016 } 3017 } 3018 PetscFunctionReturn(0); 3019 } 3020 3021 #undef __FUNCT__ 3022 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 3023 /* Set the constrained field indices on each point 3024 If bcComps is NULL or the IS is NULL, constrain every dof on the point 3025 */ 3026 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt numBC,const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 3027 { 3028 PetscSection aSec; 3029 PetscInt *indices; 3030 PetscInt numFields, maxDof, pStart, pEnd, p, bc, f, d; 3031 PetscErrorCode ierr; 3032 3033 PetscFunctionBegin; 3034 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3035 if (!numFields) PetscFunctionReturn(0); 3036 /* Initialize all field indices to -1 */ 3037 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3038 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 3039 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3040 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3041 for (p = pStart; p < pEnd; ++p) for (f = 0; f < numFields; ++f) {ierr = PetscSectionSetFieldConstraintIndices(section, p, f, indices);CHKERRQ(ierr);} 3042 /* Handle BC constraints */ 3043 for (bc = 0; bc < numBC; ++bc) { 3044 const PetscInt field = bcField[bc]; 3045 const PetscInt *comp, *idx; 3046 PetscInt Nc = -1, n, i; 3047 3048 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 3049 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3050 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 3051 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3052 for (i = 0; i < n; ++i) { 3053 const PetscInt p = idx[i]; 3054 const PetscInt *find; 3055 PetscInt fcdof, c; 3056 3057 ierr = PetscSectionGetFieldConstraintDof(section, p, field, &fcdof);CHKERRQ(ierr); 3058 if (Nc < 0) { 3059 for (d = 0; d < fcdof; ++d) indices[d] = d; 3060 } else { 3061 ierr = PetscSectionGetFieldConstraintIndices(section, p, field, &find);CHKERRQ(ierr); 3062 for (d = 0; d < fcdof; ++d) {if (find[d] < 0) break; indices[d] = find[d];} 3063 for (c = 0; c < Nc; ++c) indices[d+c] = comp[c]; 3064 ierr = PetscSortInt(d+Nc, indices);CHKERRQ(ierr); 3065 for (c = d+Nc; c < fcdof; ++c) indices[c] = -1; 3066 } 3067 ierr = PetscSectionSetFieldConstraintIndices(section, p, field, indices);CHKERRQ(ierr); 3068 } 3069 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3070 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3071 } 3072 /* Handle anchors */ 3073 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3074 if (aSec) { 3075 PetscInt aStart, aEnd, a; 3076 3077 for (d = 0; d < maxDof; ++d) indices[d] = d; 3078 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3079 for (a = aStart; a < aEnd; a++) { 3080 PetscInt dof, fdof, f; 3081 3082 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3083 if (dof) { 3084 /* if there are point-to-point constraints, then all dofs are constrained */ 3085 for (f = 0; f < numFields; f++) { 3086 ierr = PetscSectionGetFieldDof(section, a, f, &fdof);CHKERRQ(ierr); 3087 ierr = PetscSectionSetFieldConstraintIndices(section, a, f, indices);CHKERRQ(ierr); 3088 } 3089 } 3090 } 3091 } 3092 ierr = PetscFree(indices);CHKERRQ(ierr); 3093 PetscFunctionReturn(0); 3094 } 3095 3096 #undef __FUNCT__ 3097 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 3098 /* Set the constrained indices on each point */ 3099 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 3100 { 3101 PetscInt *indices; 3102 PetscInt numFields, maxDof, pStart, pEnd, p, f, d; 3103 PetscErrorCode ierr; 3104 3105 PetscFunctionBegin; 3106 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3107 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 3108 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3109 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3110 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3111 for (p = pStart; p < pEnd; ++p) { 3112 PetscInt cdof, d; 3113 3114 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 3115 if (cdof) { 3116 if (numFields) { 3117 PetscInt numConst = 0, foff = 0; 3118 3119 for (f = 0; f < numFields; ++f) { 3120 const PetscInt *find; 3121 PetscInt fcdof, fdof; 3122 3123 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 3124 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 3125 /* Change constraint numbering from field component to local dof number */ 3126 ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &find);CHKERRQ(ierr); 3127 for (d = 0; d < fcdof; ++d) indices[numConst+d] = find[d] + foff; 3128 numConst += fcdof; 3129 foff += fdof; 3130 } 3131 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 3132 } else { 3133 for (d = 0; d < cdof; ++d) indices[d] = d; 3134 } 3135 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 3136 } 3137 } 3138 ierr = PetscFree(indices);CHKERRQ(ierr); 3139 PetscFunctionReturn(0); 3140 } 3141 3142 #undef __FUNCT__ 3143 #define __FUNCT__ "DMPlexCreateSection" 3144 /*@C 3145 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 3146 3147 Not Collective 3148 3149 Input Parameters: 3150 + dm - The DMPlex object 3151 . dim - The spatial dimension of the problem 3152 . numFields - The number of fields in the problem 3153 . numComp - An array of size numFields that holds the number of components for each field 3154 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 3155 . numBC - The number of boundary conditions 3156 . bcField - An array of size numBC giving the field number for each boundry condition 3157 . bcComps - [Optional] An array of size numBC giving an IS holding the field components to which each boundary condition applies 3158 . bcPoints - An array of size numBC giving an IS holding the Plex points to which each boundary condition applies 3159 - perm - Optional permutation of the chart, or NULL 3160 3161 Output Parameter: 3162 . section - The PetscSection object 3163 3164 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 3165 number of dof for field 0 on each edge. 3166 3167 The chart permutation is the same one set using PetscSectionSetPermutation() 3168 3169 Level: developer 3170 3171 Fortran Notes: 3172 A Fortran 90 version is available as DMPlexCreateSectionF90() 3173 3174 .keywords: mesh, elements 3175 .seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation() 3176 @*/ 3177 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) 3178 { 3179 PetscSection aSec; 3180 PetscErrorCode ierr; 3181 3182 PetscFunctionBegin; 3183 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 3184 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3185 if (perm) {ierr = PetscSectionSetPermutation(*section, perm);CHKERRQ(ierr);} 3186 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3187 ierr = DMPlexGetAnchors(dm,&aSec,NULL);CHKERRQ(ierr); 3188 if (numBC || aSec) { 3189 ierr = DMPlexCreateSectionBCIndicesField(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3190 ierr = DMPlexCreateSectionBCIndices(dm, *section);CHKERRQ(ierr); 3191 } 3192 ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr); 3193 PetscFunctionReturn(0); 3194 } 3195 3196 #undef __FUNCT__ 3197 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 3198 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 3199 { 3200 PetscSection section; 3201 PetscErrorCode ierr; 3202 3203 PetscFunctionBegin; 3204 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 3205 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 3206 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 3207 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3208 PetscFunctionReturn(0); 3209 } 3210 3211 #undef __FUNCT__ 3212 #define __FUNCT__ "DMPlexGetConeSection" 3213 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 3214 { 3215 DM_Plex *mesh = (DM_Plex*) dm->data; 3216 3217 PetscFunctionBegin; 3218 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3219 if (section) *section = mesh->coneSection; 3220 PetscFunctionReturn(0); 3221 } 3222 3223 #undef __FUNCT__ 3224 #define __FUNCT__ "DMPlexGetSupportSection" 3225 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 3226 { 3227 DM_Plex *mesh = (DM_Plex*) dm->data; 3228 3229 PetscFunctionBegin; 3230 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3231 if (section) *section = mesh->supportSection; 3232 PetscFunctionReturn(0); 3233 } 3234 3235 #undef __FUNCT__ 3236 #define __FUNCT__ "DMPlexGetCones" 3237 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 3238 { 3239 DM_Plex *mesh = (DM_Plex*) dm->data; 3240 3241 PetscFunctionBegin; 3242 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3243 if (cones) *cones = mesh->cones; 3244 PetscFunctionReturn(0); 3245 } 3246 3247 #undef __FUNCT__ 3248 #define __FUNCT__ "DMPlexGetConeOrientations" 3249 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 3250 { 3251 DM_Plex *mesh = (DM_Plex*) dm->data; 3252 3253 PetscFunctionBegin; 3254 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3255 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 3256 PetscFunctionReturn(0); 3257 } 3258 3259 /******************************** FEM Support **********************************/ 3260 3261 #undef __FUNCT__ 3262 #define __FUNCT__ "DMPlexVecGetClosure_Depth1_Static" 3263 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3264 { 3265 PetscScalar *array, *vArray; 3266 const PetscInt *cone, *coneO; 3267 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3268 PetscErrorCode ierr; 3269 3270 PetscFunctionBeginHot; 3271 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3272 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3273 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3274 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3275 if (!values || !*values) { 3276 if ((point >= pStart) && (point < pEnd)) { 3277 PetscInt dof; 3278 3279 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3280 size += dof; 3281 } 3282 for (p = 0; p < numPoints; ++p) { 3283 const PetscInt cp = cone[p]; 3284 PetscInt dof; 3285 3286 if ((cp < pStart) || (cp >= pEnd)) continue; 3287 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3288 size += dof; 3289 } 3290 if (!values) { 3291 if (csize) *csize = size; 3292 PetscFunctionReturn(0); 3293 } 3294 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 3295 } else { 3296 array = *values; 3297 } 3298 size = 0; 3299 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3300 if ((point >= pStart) && (point < pEnd)) { 3301 PetscInt dof, off, d; 3302 PetscScalar *varr; 3303 3304 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3305 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3306 varr = &vArray[off]; 3307 for (d = 0; d < dof; ++d, ++offset) { 3308 array[offset] = varr[d]; 3309 } 3310 size += dof; 3311 } 3312 for (p = 0; p < numPoints; ++p) { 3313 const PetscInt cp = cone[p]; 3314 PetscInt o = coneO[p]; 3315 PetscInt dof, off, d; 3316 PetscScalar *varr; 3317 3318 if ((cp < pStart) || (cp >= pEnd)) continue; 3319 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3320 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3321 varr = &vArray[off]; 3322 if (o >= 0) { 3323 for (d = 0; d < dof; ++d, ++offset) { 3324 array[offset] = varr[d]; 3325 } 3326 } else { 3327 for (d = dof-1; d >= 0; --d, ++offset) { 3328 array[offset] = varr[d]; 3329 } 3330 } 3331 size += dof; 3332 } 3333 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3334 if (!*values) { 3335 if (csize) *csize = size; 3336 *values = array; 3337 } else { 3338 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 3339 *csize = size; 3340 } 3341 PetscFunctionReturn(0); 3342 } 3343 3344 #undef __FUNCT__ 3345 #define __FUNCT__ "DMPlexVecGetClosure_Static" 3346 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3347 { 3348 PetscInt offset = 0, p; 3349 PetscErrorCode ierr; 3350 3351 PetscFunctionBeginHot; 3352 *size = 0; 3353 for (p = 0; p < numPoints*2; p += 2) { 3354 const PetscInt point = points[p]; 3355 const PetscInt o = points[p+1]; 3356 PetscInt dof, off, d; 3357 const PetscScalar *varr; 3358 3359 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3360 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3361 varr = &vArray[off]; 3362 if (o >= 0) { 3363 for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 3364 } else { 3365 for (d = dof-1; d >= 0; --d, ++offset) array[offset] = varr[d]; 3366 } 3367 } 3368 *size = offset; 3369 PetscFunctionReturn(0); 3370 } 3371 3372 #undef __FUNCT__ 3373 #define __FUNCT__ "DMPlexVecGetClosure_Fields_Static" 3374 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3375 { 3376 PetscInt offset = 0, f; 3377 PetscErrorCode ierr; 3378 3379 PetscFunctionBeginHot; 3380 *size = 0; 3381 for (f = 0; f < numFields; ++f) { 3382 PetscInt fcomp, p; 3383 3384 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3385 for (p = 0; p < numPoints*2; p += 2) { 3386 const PetscInt point = points[p]; 3387 const PetscInt o = points[p+1]; 3388 PetscInt fdof, foff, d, c; 3389 const PetscScalar *varr; 3390 3391 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3392 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3393 varr = &vArray[foff]; 3394 if (o >= 0) { 3395 for (d = 0; d < fdof; ++d, ++offset) array[offset] = varr[d]; 3396 } else { 3397 for (d = fdof/fcomp-1; d >= 0; --d) { 3398 for (c = 0; c < fcomp; ++c, ++offset) { 3399 array[offset] = varr[d*fcomp+c]; 3400 } 3401 } 3402 } 3403 } 3404 } 3405 *size = offset; 3406 PetscFunctionReturn(0); 3407 } 3408 3409 #undef __FUNCT__ 3410 #define __FUNCT__ "DMPlexVecGetClosure" 3411 /*@C 3412 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 3413 3414 Not collective 3415 3416 Input Parameters: 3417 + dm - The DM 3418 . section - The section describing the layout in v, or NULL to use the default section 3419 . v - The local vector 3420 - point - The sieve point in the DM 3421 3422 Output Parameters: 3423 + csize - The number of values in the closure, or NULL 3424 - values - The array of values, which is a borrowed array and should not be freed 3425 3426 Fortran Notes: 3427 Since it returns an array, this routine is only available in Fortran 90, and you must 3428 include petsc.h90 in your code. 3429 3430 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3431 3432 Level: intermediate 3433 3434 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3435 @*/ 3436 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3437 { 3438 PetscSection clSection; 3439 IS clPoints; 3440 PetscScalar *array, *vArray; 3441 PetscInt *points = NULL; 3442 const PetscInt *clp; 3443 PetscInt depth, numFields, numPoints, size; 3444 PetscErrorCode ierr; 3445 3446 PetscFunctionBeginHot; 3447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3448 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3449 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3450 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3451 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3452 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3453 if (depth == 1 && numFields < 2) { 3454 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 3455 PetscFunctionReturn(0); 3456 } 3457 /* Get points */ 3458 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3459 if (!clPoints) { 3460 PetscInt pStart, pEnd, p, q; 3461 3462 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3463 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3464 /* Compress out points not in the section */ 3465 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3466 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3467 points[q*2] = points[p]; 3468 points[q*2+1] = points[p+1]; 3469 ++q; 3470 } 3471 } 3472 numPoints = q; 3473 } else { 3474 PetscInt dof, off; 3475 3476 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3477 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3478 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3479 numPoints = dof/2; 3480 points = (PetscInt *) &clp[off]; 3481 } 3482 /* Get array */ 3483 if (!values || !*values) { 3484 PetscInt asize = 0, dof, p; 3485 3486 for (p = 0; p < numPoints*2; p += 2) { 3487 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3488 asize += dof; 3489 } 3490 if (!values) { 3491 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3492 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3493 if (csize) *csize = asize; 3494 PetscFunctionReturn(0); 3495 } 3496 ierr = DMGetWorkArray(dm, asize, PETSC_SCALAR, &array);CHKERRQ(ierr); 3497 } else { 3498 array = *values; 3499 } 3500 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3501 /* Get values */ 3502 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(section, numPoints, points, numFields, vArray, &size, array);CHKERRQ(ierr);} 3503 else {ierr = DMPlexVecGetClosure_Static(section, numPoints, points, vArray, &size, array);CHKERRQ(ierr);} 3504 /* Cleanup points */ 3505 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3506 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3507 /* Cleanup array */ 3508 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3509 if (!*values) { 3510 if (csize) *csize = size; 3511 *values = array; 3512 } else { 3513 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 3514 *csize = size; 3515 } 3516 PetscFunctionReturn(0); 3517 } 3518 3519 #undef __FUNCT__ 3520 #define __FUNCT__ "DMPlexVecRestoreClosure" 3521 /*@C 3522 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 3523 3524 Not collective 3525 3526 Input Parameters: 3527 + dm - The DM 3528 . section - The section describing the layout in v, or NULL to use the default section 3529 . v - The local vector 3530 . point - The sieve point in the DM 3531 . csize - The number of values in the closure, or NULL 3532 - values - The array of values, which is a borrowed array and should not be freed 3533 3534 Fortran Notes: 3535 Since it returns an array, this routine is only available in Fortran 90, and you must 3536 include petsc.h90 in your code. 3537 3538 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3539 3540 Level: intermediate 3541 3542 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3543 @*/ 3544 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3545 { 3546 PetscInt size = 0; 3547 PetscErrorCode ierr; 3548 3549 PetscFunctionBegin; 3550 /* Should work without recalculating size */ 3551 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 3552 PetscFunctionReturn(0); 3553 } 3554 3555 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 3556 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 3557 3558 #undef __FUNCT__ 3559 #define __FUNCT__ "updatePoint_private" 3560 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[]) 3561 { 3562 PetscInt cdof; /* The number of constraints on this point */ 3563 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3564 PetscScalar *a; 3565 PetscInt off, cind = 0, k; 3566 PetscErrorCode ierr; 3567 3568 PetscFunctionBegin; 3569 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3570 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3571 a = &array[off]; 3572 if (!cdof || setBC) { 3573 if (orientation >= 0) { 3574 for (k = 0; k < dof; ++k) { 3575 fuse(&a[k], values[k]); 3576 } 3577 } else { 3578 for (k = 0; k < dof; ++k) { 3579 fuse(&a[k], values[dof-k-1]); 3580 } 3581 } 3582 } else { 3583 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3584 if (orientation >= 0) { 3585 for (k = 0; k < dof; ++k) { 3586 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3587 fuse(&a[k], values[k]); 3588 } 3589 } else { 3590 for (k = 0; k < dof; ++k) { 3591 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3592 fuse(&a[k], values[dof-k-1]); 3593 } 3594 } 3595 } 3596 PetscFunctionReturn(0); 3597 } 3598 3599 #undef __FUNCT__ 3600 #define __FUNCT__ "updatePointBC_private" 3601 PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 3602 { 3603 PetscInt cdof; /* The number of constraints on this point */ 3604 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3605 PetscScalar *a; 3606 PetscInt off, cind = 0, k; 3607 PetscErrorCode ierr; 3608 3609 PetscFunctionBegin; 3610 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3611 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3612 a = &array[off]; 3613 if (cdof) { 3614 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3615 if (orientation >= 0) { 3616 for (k = 0; k < dof; ++k) { 3617 if ((cind < cdof) && (k == cdofs[cind])) { 3618 fuse(&a[k], values[k]); 3619 ++cind; 3620 } 3621 } 3622 } else { 3623 for (k = 0; k < dof; ++k) { 3624 if ((cind < cdof) && (k == cdofs[cind])) { 3625 fuse(&a[k], values[dof-k-1]); 3626 ++cind; 3627 } 3628 } 3629 } 3630 } 3631 PetscFunctionReturn(0); 3632 } 3633 3634 #undef __FUNCT__ 3635 #define __FUNCT__ "updatePointFields_private" 3636 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[]) 3637 { 3638 PetscScalar *a; 3639 PetscInt fdof, foff, fcdof, foffset = *offset; 3640 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3641 PetscInt cind = 0, k, c; 3642 PetscErrorCode ierr; 3643 3644 PetscFunctionBegin; 3645 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3646 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3647 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3648 a = &array[foff]; 3649 if (!fcdof || setBC) { 3650 if (o >= 0) { 3651 for (k = 0; k < fdof; ++k) fuse(&a[k], values[foffset+k]); 3652 } else { 3653 for (k = fdof/fcomp-1; k >= 0; --k) { 3654 for (c = 0; c < fcomp; ++c) { 3655 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3656 } 3657 } 3658 } 3659 } else { 3660 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3661 if (o >= 0) { 3662 for (k = 0; k < fdof; ++k) { 3663 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 3664 fuse(&a[k], values[foffset+k]); 3665 } 3666 } else { 3667 for (k = fdof/fcomp-1; k >= 0; --k) { 3668 for (c = 0; c < fcomp; ++c) { 3669 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 3670 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3671 } 3672 } 3673 } 3674 } 3675 *offset += fdof; 3676 PetscFunctionReturn(0); 3677 } 3678 3679 #undef __FUNCT__ 3680 #define __FUNCT__ "updatePointFieldsBC_private" 3681 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[]) 3682 { 3683 PetscScalar *a; 3684 PetscInt fdof, foff, fcdof, foffset = *offset; 3685 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3686 PetscInt cind = 0, k, c; 3687 PetscErrorCode ierr; 3688 3689 PetscFunctionBegin; 3690 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3691 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3692 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3693 a = &array[foff]; 3694 if (fcdof) { 3695 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3696 if (o >= 0) { 3697 for (k = 0; k < fdof; ++k) { 3698 if ((cind < fcdof) && (k == fcdofs[cind])) { 3699 fuse(&a[k], values[foffset+k]); 3700 ++cind; 3701 } 3702 } 3703 } else { 3704 for (k = fdof/fcomp-1; k >= 0; --k) { 3705 for (c = 0; c < fcomp; ++c) { 3706 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) { 3707 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3708 ++cind; 3709 } 3710 } 3711 } 3712 } 3713 } 3714 *offset += fdof; 3715 PetscFunctionReturn(0); 3716 } 3717 3718 #undef __FUNCT__ 3719 #define __FUNCT__ "DMPlexVecSetClosure_Static" 3720 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3721 { 3722 PetscScalar *array; 3723 const PetscInt *cone, *coneO; 3724 PetscInt pStart, pEnd, p, numPoints, off, dof; 3725 PetscErrorCode ierr; 3726 3727 PetscFunctionBeginHot; 3728 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3729 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3730 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3731 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3732 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3733 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 3734 const PetscInt cp = !p ? point : cone[p-1]; 3735 const PetscInt o = !p ? 0 : coneO[p-1]; 3736 3737 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 3738 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3739 /* ADD_VALUES */ 3740 { 3741 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3742 PetscScalar *a; 3743 PetscInt cdof, coff, cind = 0, k; 3744 3745 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 3746 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 3747 a = &array[coff]; 3748 if (!cdof) { 3749 if (o >= 0) { 3750 for (k = 0; k < dof; ++k) { 3751 a[k] += values[off+k]; 3752 } 3753 } else { 3754 for (k = 0; k < dof; ++k) { 3755 a[k] += values[off+dof-k-1]; 3756 } 3757 } 3758 } else { 3759 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 3760 if (o >= 0) { 3761 for (k = 0; k < dof; ++k) { 3762 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3763 a[k] += values[off+k]; 3764 } 3765 } else { 3766 for (k = 0; k < dof; ++k) { 3767 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3768 a[k] += values[off+dof-k-1]; 3769 } 3770 } 3771 } 3772 } 3773 } 3774 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3775 PetscFunctionReturn(0); 3776 } 3777 3778 #undef __FUNCT__ 3779 #define __FUNCT__ "DMPlexVecSetClosure" 3780 /*@C 3781 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 3782 3783 Not collective 3784 3785 Input Parameters: 3786 + dm - The DM 3787 . section - The section describing the layout in v, or NULL to use the default section 3788 . v - The local vector 3789 . point - The sieve point in the DM 3790 . values - The array of values 3791 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 3792 3793 Fortran Notes: 3794 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3795 3796 Level: intermediate 3797 3798 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 3799 @*/ 3800 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3801 { 3802 PetscSection clSection; 3803 IS clPoints; 3804 PetscScalar *array; 3805 PetscInt *points = NULL; 3806 const PetscInt *clp; 3807 PetscInt depth, numFields, numPoints, p; 3808 PetscErrorCode ierr; 3809 3810 PetscFunctionBeginHot; 3811 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3812 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3813 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3814 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3815 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3816 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3817 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 3818 ierr = DMPlexVecSetClosure_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 3819 PetscFunctionReturn(0); 3820 } 3821 /* Get points */ 3822 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3823 if (!clPoints) { 3824 PetscInt pStart, pEnd, q; 3825 3826 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3827 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3828 /* Compress out points not in the section */ 3829 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3830 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3831 points[q*2] = points[p]; 3832 points[q*2+1] = points[p+1]; 3833 ++q; 3834 } 3835 } 3836 numPoints = q; 3837 } else { 3838 PetscInt dof, off; 3839 3840 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3841 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3842 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3843 numPoints = dof/2; 3844 points = (PetscInt *) &clp[off]; 3845 } 3846 /* Get array */ 3847 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3848 /* Get values */ 3849 if (numFields > 0) { 3850 PetscInt offset = 0, fcomp, f; 3851 for (f = 0; f < numFields; ++f) { 3852 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3853 switch (mode) { 3854 case INSERT_VALUES: 3855 for (p = 0; p < numPoints*2; p += 2) { 3856 const PetscInt point = points[p]; 3857 const PetscInt o = points[p+1]; 3858 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 3859 } break; 3860 case INSERT_ALL_VALUES: 3861 for (p = 0; p < numPoints*2; p += 2) { 3862 const PetscInt point = points[p]; 3863 const PetscInt o = points[p+1]; 3864 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 3865 } break; 3866 case INSERT_BC_VALUES: 3867 for (p = 0; p < numPoints*2; p += 2) { 3868 const PetscInt point = points[p]; 3869 const PetscInt o = points[p+1]; 3870 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 3871 } break; 3872 case ADD_VALUES: 3873 for (p = 0; p < numPoints*2; p += 2) { 3874 const PetscInt point = points[p]; 3875 const PetscInt o = points[p+1]; 3876 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 3877 } break; 3878 case ADD_ALL_VALUES: 3879 for (p = 0; p < numPoints*2; p += 2) { 3880 const PetscInt point = points[p]; 3881 const PetscInt o = points[p+1]; 3882 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 3883 } break; 3884 default: 3885 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3886 } 3887 } 3888 } else { 3889 PetscInt dof, off; 3890 3891 switch (mode) { 3892 case INSERT_VALUES: 3893 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3894 PetscInt o = points[p+1]; 3895 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3896 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 3897 } break; 3898 case INSERT_ALL_VALUES: 3899 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3900 PetscInt o = points[p+1]; 3901 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3902 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 3903 } break; 3904 case INSERT_BC_VALUES: 3905 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3906 PetscInt o = points[p+1]; 3907 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3908 updatePointBC_private(section, points[p], dof, insert, o, &values[off], array); 3909 } break; 3910 case ADD_VALUES: 3911 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3912 PetscInt o = points[p+1]; 3913 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3914 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 3915 } break; 3916 case ADD_ALL_VALUES: 3917 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3918 PetscInt o = points[p+1]; 3919 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3920 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 3921 } break; 3922 default: 3923 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3924 } 3925 } 3926 /* Cleanup points */ 3927 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3928 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3929 /* Cleanup array */ 3930 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3931 PetscFunctionReturn(0); 3932 } 3933 3934 #undef __FUNCT__ 3935 #define __FUNCT__ "DMPlexVecSetFieldClosure_Internal" 3936 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, const PetscScalar values[], InsertMode mode) 3937 { 3938 PetscSection clSection; 3939 IS clPoints; 3940 PetscScalar *array; 3941 PetscInt *points = NULL; 3942 const PetscInt *clp; 3943 PetscInt numFields, numPoints, p; 3944 PetscInt offset = 0, fcomp, f; 3945 PetscErrorCode ierr; 3946 3947 PetscFunctionBeginHot; 3948 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3949 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3950 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3951 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3952 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3953 /* Get points */ 3954 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3955 if (!clPoints) { 3956 PetscInt pStart, pEnd, q; 3957 3958 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3959 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3960 /* Compress out points not in the section */ 3961 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3962 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3963 points[q*2] = points[p]; 3964 points[q*2+1] = points[p+1]; 3965 ++q; 3966 } 3967 } 3968 numPoints = q; 3969 } else { 3970 PetscInt dof, off; 3971 3972 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3973 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3974 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3975 numPoints = dof/2; 3976 points = (PetscInt *) &clp[off]; 3977 } 3978 /* Get array */ 3979 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3980 /* Get values */ 3981 for (f = 0; f < numFields; ++f) { 3982 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3983 if (!fieldActive[f]) { 3984 for (p = 0; p < numPoints*2; p += 2) { 3985 PetscInt fdof; 3986 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 3987 offset += fdof; 3988 } 3989 continue; 3990 } 3991 switch (mode) { 3992 case INSERT_VALUES: 3993 for (p = 0; p < numPoints*2; p += 2) { 3994 const PetscInt point = points[p]; 3995 const PetscInt o = points[p+1]; 3996 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 3997 } break; 3998 case INSERT_ALL_VALUES: 3999 for (p = 0; p < numPoints*2; p += 2) { 4000 const PetscInt point = points[p]; 4001 const PetscInt o = points[p+1]; 4002 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 4003 } break; 4004 case INSERT_BC_VALUES: 4005 for (p = 0; p < numPoints*2; p += 2) { 4006 const PetscInt point = points[p]; 4007 const PetscInt o = points[p+1]; 4008 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 4009 } break; 4010 case ADD_VALUES: 4011 for (p = 0; p < numPoints*2; p += 2) { 4012 const PetscInt point = points[p]; 4013 const PetscInt o = points[p+1]; 4014 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 4015 } break; 4016 case ADD_ALL_VALUES: 4017 for (p = 0; p < numPoints*2; p += 2) { 4018 const PetscInt point = points[p]; 4019 const PetscInt o = points[p+1]; 4020 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 4021 } break; 4022 default: 4023 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4024 } 4025 } 4026 /* Cleanup points */ 4027 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4028 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4029 /* Cleanup array */ 4030 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4031 PetscFunctionReturn(0); 4032 } 4033 4034 #undef __FUNCT__ 4035 #define __FUNCT__ "DMPlexPrintMatSetValues" 4036 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 4037 { 4038 PetscMPIInt rank; 4039 PetscInt i, j; 4040 PetscErrorCode ierr; 4041 4042 PetscFunctionBegin; 4043 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 4044 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 4045 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 4046 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 4047 numCIndices = numCIndices ? numCIndices : numRIndices; 4048 for (i = 0; i < numRIndices; i++) { 4049 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 4050 for (j = 0; j < numCIndices; j++) { 4051 #if defined(PETSC_USE_COMPLEX) 4052 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 4053 #else 4054 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 4055 #endif 4056 } 4057 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 4058 } 4059 PetscFunctionReturn(0); 4060 } 4061 4062 #undef __FUNCT__ 4063 #define __FUNCT__ "indicesPoint_private" 4064 /* . off - The global offset of this point */ 4065 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4066 { 4067 PetscInt dof; /* The number of unknowns on this point */ 4068 PetscInt cdof; /* The number of constraints on this point */ 4069 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4070 PetscInt cind = 0, k; 4071 PetscErrorCode ierr; 4072 4073 PetscFunctionBegin; 4074 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4075 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4076 if (!cdof || setBC) { 4077 if (orientation >= 0) { 4078 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 4079 } else { 4080 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 4081 } 4082 } else { 4083 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4084 if (orientation >= 0) { 4085 for (k = 0; k < dof; ++k) { 4086 if ((cind < cdof) && (k == cdofs[cind])) { 4087 /* Insert check for returning constrained indices */ 4088 indices[*loff+k] = -(off+k+1); 4089 ++cind; 4090 } else { 4091 indices[*loff+k] = off+k-cind; 4092 } 4093 } 4094 } else { 4095 for (k = 0; k < dof; ++k) { 4096 if ((cind < cdof) && (k == cdofs[cind])) { 4097 /* Insert check for returning constrained indices */ 4098 indices[*loff+dof-k-1] = -(off+k+1); 4099 ++cind; 4100 } else { 4101 indices[*loff+dof-k-1] = off+k-cind; 4102 } 4103 } 4104 } 4105 } 4106 *loff += dof; 4107 PetscFunctionReturn(0); 4108 } 4109 4110 #undef __FUNCT__ 4111 #define __FUNCT__ "indicesPointFields_private" 4112 /* . off - The global offset of this point */ 4113 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4114 { 4115 PetscInt numFields, foff, f; 4116 PetscErrorCode ierr; 4117 4118 PetscFunctionBegin; 4119 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4120 for (f = 0, foff = 0; f < numFields; ++f) { 4121 PetscInt fdof, fcomp, cfdof; 4122 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4123 PetscInt cind = 0, k, c; 4124 4125 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4126 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4127 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4128 if (!cfdof || setBC) { 4129 if (orientation >= 0) { 4130 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 4131 } else { 4132 for (k = fdof/fcomp-1; k >= 0; --k) { 4133 for (c = 0; c < fcomp; ++c) { 4134 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 4135 } 4136 } 4137 } 4138 } else { 4139 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4140 if (orientation >= 0) { 4141 for (k = 0; k < fdof; ++k) { 4142 if ((cind < cfdof) && (k == fcdofs[cind])) { 4143 indices[foffs[f]+k] = -(off+foff+k+1); 4144 ++cind; 4145 } else { 4146 indices[foffs[f]+k] = off+foff+k-cind; 4147 } 4148 } 4149 } else { 4150 for (k = fdof/fcomp-1; k >= 0; --k) { 4151 for (c = 0; c < fcomp; ++c) { 4152 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 4153 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 4154 ++cind; 4155 } else { 4156 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 4157 } 4158 } 4159 } 4160 } 4161 } 4162 foff += fdof - cfdof; 4163 foffs[f] += fdof; 4164 } 4165 PetscFunctionReturn(0); 4166 } 4167 4168 #undef __FUNCT__ 4169 #define __FUNCT__ "DMPlexAnchorsModifyMat" 4170 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[]) 4171 { 4172 Mat cMat; 4173 PetscSection aSec, cSec; 4174 IS aIS; 4175 PetscInt aStart = -1, aEnd = -1; 4176 const PetscInt *anchors; 4177 PetscInt numFields, f, p, q, newP = 0; 4178 PetscInt newNumPoints = 0, newNumIndices = 0; 4179 PetscInt *newPoints, *indices, *newIndices; 4180 PetscInt maxAnchor, maxDof; 4181 PetscInt newOffsets[32]; 4182 PetscInt *pointMatOffsets[32]; 4183 PetscInt *newPointOffsets[32]; 4184 PetscScalar *pointMat[32]; 4185 PetscScalar *newValues,*tmpValues; 4186 PetscBool anyConstrained = PETSC_FALSE; 4187 PetscErrorCode ierr; 4188 4189 PetscFunctionBegin; 4190 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4191 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4192 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4193 4194 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 4195 /* if there are point-to-point constraints */ 4196 if (aSec) { 4197 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4198 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 4199 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 4200 /* figure out how many points are going to be in the new element matrix 4201 * (we allow double counting, because it's all just going to be summed 4202 * into the global matrix anyway) */ 4203 for (p = 0; p < 2*numPoints; p+=2) { 4204 PetscInt b = points[p]; 4205 PetscInt bDof = 0; 4206 4207 if (b >= aStart && b < aEnd) { 4208 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 4209 } 4210 if (bDof) { 4211 /* this point is constrained */ 4212 /* it is going to be replaced by its anchors */ 4213 PetscInt bOff, q; 4214 4215 anyConstrained = PETSC_TRUE; 4216 newNumPoints += bDof; 4217 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 4218 for (q = 0; q < bDof; q++) { 4219 PetscInt a = anchors[bOff + q]; 4220 PetscInt aDof; 4221 4222 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 4223 newNumIndices += aDof; 4224 for (f = 0; f < numFields; ++f) { 4225 PetscInt fDof; 4226 4227 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 4228 newOffsets[f+1] += fDof; 4229 } 4230 } 4231 } 4232 else { 4233 /* this point is not constrained */ 4234 newNumPoints++; 4235 ierr = PetscSectionGetDof(section,b,&bDof);CHKERRQ(ierr); 4236 newNumIndices += bDof; 4237 for (f = 0; f < numFields; ++f) { 4238 PetscInt fDof; 4239 4240 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4241 newOffsets[f+1] += fDof; 4242 } 4243 } 4244 } 4245 } 4246 if (!anyConstrained) { 4247 if (outNumPoints) *outNumPoints = 0; 4248 if (outNumIndices) *outNumIndices = 0; 4249 if (outPoints) *outPoints = NULL; 4250 if (outValues) *outValues = NULL; 4251 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4252 PetscFunctionReturn(0); 4253 } 4254 4255 for (f = 1; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 4256 4257 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 4258 4259 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 4260 4261 /* output arrays */ 4262 ierr = DMGetWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4263 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4264 4265 /* workspaces */ 4266 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4267 if (numFields) { 4268 for (f = 0; f < numFields; f++) { 4269 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4270 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4271 } 4272 } 4273 else { 4274 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4275 ierr = DMGetWorkArray(dm,numPoints,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4276 } 4277 4278 /* get workspaces for the point-to-point matrices */ 4279 if (numFields) { 4280 for (p = 0; p < numPoints; p++) { 4281 PetscInt b = points[2*p]; 4282 PetscInt bDof = 0; 4283 4284 if (b >= aStart && b < aEnd) { 4285 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4286 } 4287 if (bDof) { 4288 for (f = 0; f < numFields; f++) { 4289 PetscInt fDof, q, bOff, allFDof = 0; 4290 4291 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4292 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4293 for (q = 0; q < bDof; q++) { 4294 PetscInt a = anchors[bOff + q]; 4295 PetscInt aFDof; 4296 4297 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 4298 allFDof += aFDof; 4299 } 4300 newPointOffsets[f][p+1] = allFDof; 4301 pointMatOffsets[f][p+1] = fDof * allFDof; 4302 } 4303 } 4304 else { 4305 for (f = 0; f < numFields; f++) { 4306 PetscInt fDof; 4307 4308 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4309 newPointOffsets[f][p+1] = fDof; 4310 pointMatOffsets[f][p+1] = 0; 4311 } 4312 } 4313 } 4314 for (f = 0; f < numFields; f++) { 4315 newPointOffsets[f][0] = 0; 4316 pointMatOffsets[f][0] = 0; 4317 for (p = 0; p < numPoints; p++) { 4318 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 4319 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 4320 } 4321 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4322 } 4323 } 4324 else { 4325 for (p = 0; p < numPoints; p++) { 4326 PetscInt b = points[2*p]; 4327 PetscInt bDof = 0; 4328 4329 if (b >= aStart && b < aEnd) { 4330 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4331 } 4332 if (bDof) { 4333 PetscInt dof, bOff, q, allDof = 0; 4334 4335 ierr = PetscSectionGetDof(section, b, &dof);CHKERRQ(ierr); 4336 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4337 for (q = 0; q < bDof; q++) { 4338 PetscInt a = anchors[bOff + q], aDof; 4339 4340 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 4341 allDof += aDof; 4342 } 4343 newPointOffsets[0][p+1] = allDof; 4344 pointMatOffsets[0][p+1] = dof * allDof; 4345 } 4346 else { 4347 PetscInt dof; 4348 4349 ierr = PetscSectionGetDof(section, b, &dof);CHKERRQ(ierr); 4350 newPointOffsets[0][p+1] = dof; 4351 pointMatOffsets[0][p+1] = 0; 4352 } 4353 } 4354 newPointOffsets[0][0] = 0; 4355 pointMatOffsets[0][0] = 0; 4356 for (p = 0; p < numPoints; p++) { 4357 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 4358 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 4359 } 4360 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4361 } 4362 4363 /* get the point-to-point matrices; construct newPoints */ 4364 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 4365 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 4366 ierr = DMGetWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4367 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4368 if (numFields) { 4369 for (p = 0, newP = 0; p < numPoints; p++) { 4370 PetscInt b = points[2*p]; 4371 PetscInt o = points[2*p+1]; 4372 PetscInt bDof = 0; 4373 4374 if (b >= aStart && b < aEnd) { 4375 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4376 } 4377 if (bDof) { 4378 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 4379 4380 fStart[0] = 0; 4381 fEnd[0] = 0; 4382 for (f = 0; f < numFields; f++) { 4383 PetscInt fDof; 4384 4385 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 4386 fStart[f+1] = fStart[f] + fDof; 4387 fEnd[f+1] = fStart[f+1]; 4388 } 4389 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4390 ierr = indicesPointFields_private(cSec, b, bOff, fEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4391 4392 fAnchorStart[0] = 0; 4393 fAnchorEnd[0] = 0; 4394 for (f = 0; f < numFields; f++) { 4395 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 4396 4397 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 4398 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 4399 } 4400 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4401 for (q = 0; q < bDof; q++) { 4402 PetscInt a = anchors[bOff + q], aOff; 4403 4404 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4405 newPoints[2*(newP + q)] = a; 4406 newPoints[2*(newP + q) + 1] = 0; 4407 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4408 ierr = indicesPointFields_private(section, a, aOff, fAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4409 } 4410 newP += bDof; 4411 4412 /* get the point-to-point submatrix */ 4413 for (f = 0; f < numFields; f++) { 4414 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 4415 } 4416 } 4417 else { 4418 newPoints[2 * newP] = b; 4419 newPoints[2 * newP + 1] = o; 4420 newP++; 4421 } 4422 } 4423 } else { 4424 for (p = 0; p < numPoints; p++) { 4425 PetscInt b = points[2*p]; 4426 PetscInt o = points[2*p+1]; 4427 PetscInt bDof = 0; 4428 4429 if (b >= aStart && b < aEnd) { 4430 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4431 } 4432 if (bDof) { 4433 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 4434 4435 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4436 ierr = indicesPoint_private(cSec, b, bOff, &bEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4437 4438 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4439 for (q = 0; q < bDof; q++) { 4440 PetscInt a = anchors[bOff + q], aOff; 4441 4442 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4443 4444 newPoints[2*(newP + q)] = a; 4445 newPoints[2*(newP + q) + 1] = 0; 4446 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4447 ierr = indicesPoint_private(section, a, aOff, &bAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4448 } 4449 newP += bDof; 4450 4451 /* get the point-to-point submatrix */ 4452 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 4453 } 4454 else { 4455 newPoints[2 * newP] = b; 4456 newPoints[2 * newP + 1] = o; 4457 newP++; 4458 } 4459 } 4460 } 4461 4462 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 4463 /* multiply constraints on the right */ 4464 if (numFields) { 4465 for (f = 0; f < numFields; f++) { 4466 PetscInt oldOff = offsets[f]; 4467 4468 for (p = 0; p < numPoints; p++) { 4469 PetscInt cStart = newPointOffsets[f][p]; 4470 PetscInt b = points[2 * p]; 4471 PetscInt c, r, k; 4472 PetscInt dof; 4473 4474 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4475 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4476 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 4477 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 4478 4479 for (r = 0; r < numIndices; r++) { 4480 for (c = 0; c < nCols; c++) { 4481 for (k = 0; k < dof; k++) { 4482 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4483 } 4484 } 4485 } 4486 } 4487 else { 4488 /* copy this column as is */ 4489 for (r = 0; r < numIndices; r++) { 4490 for (c = 0; c < dof; c++) { 4491 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4492 } 4493 } 4494 } 4495 oldOff += dof; 4496 } 4497 } 4498 } 4499 else { 4500 PetscInt oldOff = 0; 4501 for (p = 0; p < numPoints; p++) { 4502 PetscInt cStart = newPointOffsets[0][p]; 4503 PetscInt b = points[2 * p]; 4504 PetscInt c, r, k; 4505 PetscInt dof; 4506 4507 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4508 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4509 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 4510 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 4511 4512 for (r = 0; r < numIndices; r++) { 4513 for (c = 0; c < nCols; c++) { 4514 for (k = 0; k < dof; k++) { 4515 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4516 } 4517 } 4518 } 4519 } 4520 else { 4521 /* copy this column as is */ 4522 for (r = 0; r < numIndices; r++) { 4523 for (c = 0; c < dof; c++) { 4524 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4525 } 4526 } 4527 } 4528 oldOff += dof; 4529 } 4530 } 4531 4532 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 4533 /* multiply constraints transpose on the left */ 4534 if (numFields) { 4535 for (f = 0; f < numFields; f++) { 4536 PetscInt oldOff = offsets[f]; 4537 4538 for (p = 0; p < numPoints; p++) { 4539 PetscInt rStart = newPointOffsets[f][p]; 4540 PetscInt b = points[2 * p]; 4541 PetscInt c, r, k; 4542 PetscInt dof; 4543 4544 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4545 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4546 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 4547 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 4548 4549 for (r = 0; r < nRows; r++) { 4550 for (c = 0; c < newNumIndices; c++) { 4551 for (k = 0; k < dof; k++) { 4552 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4553 } 4554 } 4555 } 4556 } 4557 else { 4558 /* copy this row as is */ 4559 for (r = 0; r < dof; r++) { 4560 for (c = 0; c < newNumIndices; c++) { 4561 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4562 } 4563 } 4564 } 4565 oldOff += dof; 4566 } 4567 } 4568 } 4569 else { 4570 PetscInt oldOff = 0; 4571 4572 for (p = 0; p < numPoints; p++) { 4573 PetscInt rStart = newPointOffsets[0][p]; 4574 PetscInt b = points[2 * p]; 4575 PetscInt c, r, k; 4576 PetscInt dof; 4577 4578 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4579 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4580 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 4581 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 4582 4583 for (r = 0; r < nRows; r++) { 4584 for (c = 0; c < newNumIndices; c++) { 4585 for (k = 0; k < dof; k++) { 4586 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4587 } 4588 } 4589 } 4590 } 4591 else { 4592 /* copy this row as is */ 4593 for (r = 0; r < dof; c++) { 4594 for (c = 0; c < newNumIndices; c++) { 4595 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4596 } 4597 } 4598 } 4599 oldOff += dof; 4600 } 4601 } 4602 4603 /* clean up */ 4604 ierr = DMRestoreWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4605 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4606 if (numFields) { 4607 for (f = 0; f < numFields; f++) { 4608 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4609 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4610 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4611 } 4612 } 4613 else { 4614 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4615 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4616 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4617 } 4618 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4619 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4620 4621 /* output */ 4622 *outNumPoints = newNumPoints; 4623 *outNumIndices = newNumIndices; 4624 *outPoints = newPoints; 4625 *outValues = newValues; 4626 for (f = 0; f < numFields; f++) { 4627 offsets[f] = newOffsets[f]; 4628 } 4629 PetscFunctionReturn(0); 4630 } 4631 4632 #undef __FUNCT__ 4633 #define __FUNCT__ "DMPlexGetClosureIndices" 4634 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices) 4635 { 4636 PetscSection clSection; 4637 IS clPoints; 4638 const PetscInt *clp; 4639 PetscInt *points = NULL, *pointsNew; 4640 PetscInt numPoints, numPointsNew; 4641 PetscInt offsets[32]; 4642 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 4643 PetscErrorCode ierr; 4644 4645 PetscFunctionBegin; 4646 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4647 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4648 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4649 if (numIndices) PetscValidPointer(numIndices, 4); 4650 PetscValidPointer(indices, 5); 4651 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4652 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 4653 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4654 /* Get points in closure */ 4655 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4656 if (!clPoints) { 4657 PetscInt pStart, pEnd, q; 4658 4659 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4660 /* Compress out points not in the section */ 4661 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4662 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4663 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4664 points[q*2] = points[p]; 4665 points[q*2+1] = points[p+1]; 4666 ++q; 4667 } 4668 } 4669 numPoints = q; 4670 } else { 4671 PetscInt dof, off; 4672 4673 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4674 numPoints = dof/2; 4675 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4676 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4677 points = (PetscInt *) &clp[off]; 4678 } 4679 /* Get number of indices and indices per field */ 4680 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 4681 PetscInt dof, fdof; 4682 4683 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4684 for (f = 0; f < Nf; ++f) { 4685 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4686 offsets[f+1] += fdof; 4687 } 4688 Nind += dof; 4689 } 4690 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 4691 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[Nf], Nind); 4692 /* Correct for hanging node constraints */ 4693 { 4694 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets);CHKERRQ(ierr); 4695 if (numPointsNew) { 4696 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4697 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4698 numPoints = numPointsNew; 4699 Nind = NindNew; 4700 points = pointsNew; 4701 } 4702 } 4703 /* Calculate indices */ 4704 ierr = DMGetWorkArray(dm, Nind, PETSC_INT, indices);CHKERRQ(ierr); 4705 if (Nf) { 4706 for (p = 0; p < numPoints*2; p += 2) { 4707 PetscInt o = points[p+1]; 4708 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4709 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, *indices); 4710 } 4711 } else { 4712 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4713 PetscInt o = points[p+1]; 4714 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4715 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, *indices); 4716 } 4717 } 4718 /* Cleanup points */ 4719 if (numPointsNew) { 4720 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, PETSC_INT, &pointsNew);CHKERRQ(ierr); 4721 } else { 4722 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4723 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4724 } 4725 if (numIndices) *numIndices = Nind; 4726 PetscFunctionReturn(0); 4727 } 4728 4729 #undef __FUNCT__ 4730 #define __FUNCT__ "DMPlexRestoreClosureIndices" 4731 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices) 4732 { 4733 PetscErrorCode ierr; 4734 4735 PetscFunctionBegin; 4736 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4737 PetscValidPointer(indices, 5); 4738 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, indices);CHKERRQ(ierr); 4739 PetscFunctionReturn(0); 4740 } 4741 4742 #undef __FUNCT__ 4743 #define __FUNCT__ "DMPlexMatSetClosure" 4744 /*@C 4745 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 4746 4747 Not collective 4748 4749 Input Parameters: 4750 + dm - The DM 4751 . section - The section describing the layout in v, or NULL to use the default section 4752 . globalSection - The section describing the layout in v, or NULL to use the default global section 4753 . A - The matrix 4754 . point - The sieve point in the DM 4755 . values - The array of values 4756 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 4757 4758 Fortran Notes: 4759 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4760 4761 Level: intermediate 4762 4763 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 4764 @*/ 4765 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4766 { 4767 DM_Plex *mesh = (DM_Plex*) dm->data; 4768 PetscSection clSection; 4769 IS clPoints; 4770 PetscInt *points = NULL, *newPoints; 4771 const PetscInt *clp; 4772 PetscInt *indices; 4773 PetscInt offsets[32]; 4774 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 4775 PetscScalar *newValues; 4776 PetscErrorCode ierr; 4777 4778 PetscFunctionBegin; 4779 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4780 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4781 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4782 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 4783 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4784 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 4785 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4786 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4787 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4788 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4789 if (!clPoints) { 4790 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4791 /* Compress out points not in the section */ 4792 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4793 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4794 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4795 points[q*2] = points[p]; 4796 points[q*2+1] = points[p+1]; 4797 ++q; 4798 } 4799 } 4800 numPoints = q; 4801 } else { 4802 PetscInt dof, off; 4803 4804 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4805 numPoints = dof/2; 4806 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4807 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4808 points = (PetscInt *) &clp[off]; 4809 } 4810 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 4811 PetscInt fdof; 4812 4813 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4814 for (f = 0; f < numFields; ++f) { 4815 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4816 offsets[f+1] += fdof; 4817 } 4818 numIndices += dof; 4819 } 4820 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 4821 4822 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 4823 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets);CHKERRQ(ierr); 4824 if (newNumPoints) { 4825 if (!clPoints) { 4826 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4827 } else { 4828 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4829 } 4830 numPoints = newNumPoints; 4831 numIndices = newNumIndices; 4832 points = newPoints; 4833 values = newValues; 4834 } 4835 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4836 if (numFields) { 4837 for (p = 0; p < numPoints*2; p += 2) { 4838 PetscInt o = points[p+1]; 4839 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4840 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 4841 } 4842 } else { 4843 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4844 PetscInt o = points[p+1]; 4845 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4846 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 4847 } 4848 } 4849 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 4850 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 4851 if (mesh->printFEM > 1) { 4852 PetscInt i; 4853 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 4854 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %d", indices[i]);CHKERRQ(ierr);} 4855 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 4856 } 4857 if (ierr) { 4858 PetscMPIInt rank; 4859 PetscErrorCode ierr2; 4860 4861 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 4862 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 4863 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 4864 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 4865 CHKERRQ(ierr); 4866 } 4867 if (newNumPoints) { 4868 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4869 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4870 } 4871 else { 4872 if (!clPoints) { 4873 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4874 } else { 4875 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4876 } 4877 } 4878 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4879 PetscFunctionReturn(0); 4880 } 4881 4882 #undef __FUNCT__ 4883 #define __FUNCT__ "DMPlexMatSetClosureRefined" 4884 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4885 { 4886 DM_Plex *mesh = (DM_Plex*) dmf->data; 4887 PetscInt *fpoints = NULL, *ftotpoints = NULL; 4888 PetscInt *cpoints = NULL; 4889 PetscInt *findices, *cindices; 4890 PetscInt foffsets[32], coffsets[32]; 4891 CellRefiner cellRefiner; 4892 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 4893 PetscErrorCode ierr; 4894 4895 PetscFunctionBegin; 4896 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 4897 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 4898 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 4899 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 4900 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 4901 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 4902 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 4903 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 4904 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 4905 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 4906 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 4907 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 4908 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4909 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4910 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4911 /* Column indices */ 4912 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4913 maxFPoints = numCPoints; 4914 /* Compress out points not in the section */ 4915 /* TODO: Squeeze out points with 0 dof as well */ 4916 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 4917 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 4918 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 4919 cpoints[q*2] = cpoints[p]; 4920 cpoints[q*2+1] = cpoints[p+1]; 4921 ++q; 4922 } 4923 } 4924 numCPoints = q; 4925 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 4926 PetscInt fdof; 4927 4928 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 4929 if (!dof) continue; 4930 for (f = 0; f < numFields; ++f) { 4931 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 4932 coffsets[f+1] += fdof; 4933 } 4934 numCIndices += dof; 4935 } 4936 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 4937 /* Row indices */ 4938 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 4939 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 4940 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4941 for (r = 0, q = 0; r < numSubcells; ++r) { 4942 /* TODO Map from coarse to fine cells */ 4943 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4944 /* Compress out points not in the section */ 4945 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 4946 for (p = 0; p < numFPoints*2; p += 2) { 4947 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 4948 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 4949 if (!dof) continue; 4950 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 4951 if (s < q) continue; 4952 ftotpoints[q*2] = fpoints[p]; 4953 ftotpoints[q*2+1] = fpoints[p+1]; 4954 ++q; 4955 } 4956 } 4957 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4958 } 4959 numFPoints = q; 4960 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 4961 PetscInt fdof; 4962 4963 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 4964 if (!dof) continue; 4965 for (f = 0; f < numFields; ++f) { 4966 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 4967 foffsets[f+1] += fdof; 4968 } 4969 numFIndices += dof; 4970 } 4971 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 4972 4973 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 4974 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 4975 ierr = DMGetWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 4976 ierr = DMGetWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 4977 if (numFields) { 4978 for (p = 0; p < numFPoints*2; p += 2) { 4979 PetscInt o = ftotpoints[p+1]; 4980 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4981 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 4982 } 4983 for (p = 0; p < numCPoints*2; p += 2) { 4984 PetscInt o = cpoints[p+1]; 4985 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4986 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 4987 } 4988 } else { 4989 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 4990 PetscInt o = ftotpoints[p+1]; 4991 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4992 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 4993 } 4994 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 4995 PetscInt o = cpoints[p+1]; 4996 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4997 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 4998 } 4999 } 5000 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 5001 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 5002 if (ierr) { 5003 PetscMPIInt rank; 5004 PetscErrorCode ierr2; 5005 5006 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5007 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5008 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 5009 ierr2 = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr2); 5010 ierr2 = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr2); 5011 CHKERRQ(ierr); 5012 } 5013 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5014 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5015 ierr = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5016 ierr = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5017 PetscFunctionReturn(0); 5018 } 5019 5020 #undef __FUNCT__ 5021 #define __FUNCT__ "DMPlexMatGetClosureIndicesRefined" 5022 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 5023 { 5024 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5025 PetscInt *cpoints = NULL; 5026 PetscInt foffsets[32], coffsets[32]; 5027 CellRefiner cellRefiner; 5028 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5029 PetscErrorCode ierr; 5030 5031 PetscFunctionBegin; 5032 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5033 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5034 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5035 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5036 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5037 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5038 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5039 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5040 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5041 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5042 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5043 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5044 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5045 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5046 /* Column indices */ 5047 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5048 maxFPoints = numCPoints; 5049 /* Compress out points not in the section */ 5050 /* TODO: Squeeze out points with 0 dof as well */ 5051 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5052 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5053 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5054 cpoints[q*2] = cpoints[p]; 5055 cpoints[q*2+1] = cpoints[p+1]; 5056 ++q; 5057 } 5058 } 5059 numCPoints = q; 5060 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5061 PetscInt fdof; 5062 5063 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5064 if (!dof) continue; 5065 for (f = 0; f < numFields; ++f) { 5066 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5067 coffsets[f+1] += fdof; 5068 } 5069 numCIndices += dof; 5070 } 5071 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5072 /* Row indices */ 5073 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5074 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5075 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5076 for (r = 0, q = 0; r < numSubcells; ++r) { 5077 /* TODO Map from coarse to fine cells */ 5078 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5079 /* Compress out points not in the section */ 5080 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5081 for (p = 0; p < numFPoints*2; p += 2) { 5082 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5083 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5084 if (!dof) continue; 5085 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5086 if (s < q) continue; 5087 ftotpoints[q*2] = fpoints[p]; 5088 ftotpoints[q*2+1] = fpoints[p+1]; 5089 ++q; 5090 } 5091 } 5092 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5093 } 5094 numFPoints = q; 5095 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5096 PetscInt fdof; 5097 5098 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5099 if (!dof) continue; 5100 for (f = 0; f < numFields; ++f) { 5101 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5102 foffsets[f+1] += fdof; 5103 } 5104 numFIndices += dof; 5105 } 5106 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5107 5108 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5109 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5110 if (numFields) { 5111 for (p = 0; p < numFPoints*2; p += 2) { 5112 PetscInt o = ftotpoints[p+1]; 5113 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5114 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5115 } 5116 for (p = 0; p < numCPoints*2; p += 2) { 5117 PetscInt o = cpoints[p+1]; 5118 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5119 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5120 } 5121 } else { 5122 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5123 PetscInt o = ftotpoints[p+1]; 5124 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5125 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5126 } 5127 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5128 PetscInt o = cpoints[p+1]; 5129 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5130 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5131 } 5132 } 5133 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5134 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5135 PetscFunctionReturn(0); 5136 } 5137 5138 #undef __FUNCT__ 5139 #define __FUNCT__ "DMPlexGetHybridBounds" 5140 /*@ 5141 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 5142 5143 Input Parameter: 5144 . dm - The DMPlex object 5145 5146 Output Parameters: 5147 + cMax - The first hybrid cell 5148 . fMax - The first hybrid face 5149 . eMax - The first hybrid edge 5150 - vMax - The first hybrid vertex 5151 5152 Level: developer 5153 5154 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 5155 @*/ 5156 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 5157 { 5158 DM_Plex *mesh = (DM_Plex*) dm->data; 5159 PetscInt dim; 5160 PetscErrorCode ierr; 5161 5162 PetscFunctionBegin; 5163 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5164 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5165 if (cMax) *cMax = mesh->hybridPointMax[dim]; 5166 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 5167 if (eMax) *eMax = mesh->hybridPointMax[1]; 5168 if (vMax) *vMax = mesh->hybridPointMax[0]; 5169 PetscFunctionReturn(0); 5170 } 5171 5172 #undef __FUNCT__ 5173 #define __FUNCT__ "DMPlexSetHybridBounds" 5174 /*@ 5175 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 5176 5177 Input Parameters: 5178 . dm - The DMPlex object 5179 . cMax - The first hybrid cell 5180 . fMax - The first hybrid face 5181 . eMax - The first hybrid edge 5182 - vMax - The first hybrid vertex 5183 5184 Level: developer 5185 5186 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 5187 @*/ 5188 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 5189 { 5190 DM_Plex *mesh = (DM_Plex*) dm->data; 5191 PetscInt dim; 5192 PetscErrorCode ierr; 5193 5194 PetscFunctionBegin; 5195 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5196 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5197 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 5198 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 5199 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 5200 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 5201 PetscFunctionReturn(0); 5202 } 5203 5204 #undef __FUNCT__ 5205 #define __FUNCT__ "DMPlexGetVTKCellHeight" 5206 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 5207 { 5208 DM_Plex *mesh = (DM_Plex*) dm->data; 5209 5210 PetscFunctionBegin; 5211 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5212 PetscValidPointer(cellHeight, 2); 5213 *cellHeight = mesh->vtkCellHeight; 5214 PetscFunctionReturn(0); 5215 } 5216 5217 #undef __FUNCT__ 5218 #define __FUNCT__ "DMPlexSetVTKCellHeight" 5219 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 5220 { 5221 DM_Plex *mesh = (DM_Plex*) dm->data; 5222 5223 PetscFunctionBegin; 5224 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5225 mesh->vtkCellHeight = cellHeight; 5226 PetscFunctionReturn(0); 5227 } 5228 5229 #undef __FUNCT__ 5230 #define __FUNCT__ "DMPlexCreateNumbering_Private" 5231 /* We can easily have a form that takes an IS instead */ 5232 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 5233 { 5234 PetscSection section, globalSection; 5235 PetscInt *numbers, p; 5236 PetscErrorCode ierr; 5237 5238 PetscFunctionBegin; 5239 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5240 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 5241 for (p = pStart; p < pEnd; ++p) { 5242 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 5243 } 5244 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 5245 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 5246 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 5247 for (p = pStart; p < pEnd; ++p) { 5248 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 5249 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 5250 else numbers[p-pStart] += shift; 5251 } 5252 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 5253 if (globalSize) { 5254 PetscLayout layout; 5255 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 5256 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 5257 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 5258 } 5259 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5260 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 5261 PetscFunctionReturn(0); 5262 } 5263 5264 #undef __FUNCT__ 5265 #define __FUNCT__ "DMPlexGetCellNumbering" 5266 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 5267 { 5268 DM_Plex *mesh = (DM_Plex*) dm->data; 5269 PetscInt cellHeight, cStart, cEnd, cMax; 5270 PetscErrorCode ierr; 5271 5272 PetscFunctionBegin; 5273 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5274 if (!mesh->globalCellNumbers) { 5275 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 5276 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5277 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5278 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 5279 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 5280 } 5281 *globalCellNumbers = mesh->globalCellNumbers; 5282 PetscFunctionReturn(0); 5283 } 5284 5285 #undef __FUNCT__ 5286 #define __FUNCT__ "DMPlexGetVertexNumbering" 5287 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 5288 { 5289 DM_Plex *mesh = (DM_Plex*) dm->data; 5290 PetscInt vStart, vEnd, vMax; 5291 PetscErrorCode ierr; 5292 5293 PetscFunctionBegin; 5294 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5295 if (!mesh->globalVertexNumbers) { 5296 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5297 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 5298 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 5299 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 5300 } 5301 *globalVertexNumbers = mesh->globalVertexNumbers; 5302 PetscFunctionReturn(0); 5303 } 5304 5305 #undef __FUNCT__ 5306 #define __FUNCT__ "DMPlexCreatePointNumbering" 5307 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 5308 { 5309 IS nums[4]; 5310 PetscInt depths[4]; 5311 PetscInt depth, d, shift = 0; 5312 PetscErrorCode ierr; 5313 5314 PetscFunctionBegin; 5315 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5316 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5317 /* For unstratified meshes use dim instead of depth */ 5318 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 5319 depths[0] = depth; depths[1] = 0; 5320 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 5321 for (d = 0; d <= depth; ++d) { 5322 PetscInt pStart, pEnd, gsize; 5323 5324 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 5325 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 5326 shift += gsize; 5327 } 5328 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 5329 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 5330 PetscFunctionReturn(0); 5331 } 5332 5333 #undef __FUNCT__ 5334 #define __FUNCT__ "DMPlexCheckSymmetry" 5335 /*@ 5336 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 5337 5338 Input Parameters: 5339 + dm - The DMPlex object 5340 5341 Note: This is a useful diagnostic when creating meshes programmatically. 5342 5343 Level: developer 5344 5345 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 5346 @*/ 5347 PetscErrorCode DMPlexCheckSymmetry(DM dm) 5348 { 5349 PetscSection coneSection, supportSection; 5350 const PetscInt *cone, *support; 5351 PetscInt coneSize, c, supportSize, s; 5352 PetscInt pStart, pEnd, p, csize, ssize; 5353 PetscErrorCode ierr; 5354 5355 PetscFunctionBegin; 5356 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5357 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 5358 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 5359 /* Check that point p is found in the support of its cone points, and vice versa */ 5360 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5361 for (p = pStart; p < pEnd; ++p) { 5362 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5363 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5364 for (c = 0; c < coneSize; ++c) { 5365 PetscBool dup = PETSC_FALSE; 5366 PetscInt d; 5367 for (d = c-1; d >= 0; --d) { 5368 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 5369 } 5370 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 5371 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 5372 for (s = 0; s < supportSize; ++s) { 5373 if (support[s] == p) break; 5374 } 5375 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 5376 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", p);CHKERRQ(ierr); 5377 for (s = 0; s < coneSize; ++s) { 5378 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[s]);CHKERRQ(ierr); 5379 } 5380 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5381 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", cone[c]);CHKERRQ(ierr); 5382 for (s = 0; s < supportSize; ++s) { 5383 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[s]);CHKERRQ(ierr); 5384 } 5385 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5386 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not repeatedly found in support of repeated cone point %d", p, cone[c]); 5387 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in support of cone point %d", p, cone[c]); 5388 } 5389 } 5390 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 5391 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 5392 for (s = 0; s < supportSize; ++s) { 5393 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5394 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5395 for (c = 0; c < coneSize; ++c) { 5396 if (cone[c] == p) break; 5397 } 5398 if (c >= coneSize) { 5399 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", p);CHKERRQ(ierr); 5400 for (c = 0; c < supportSize; ++c) { 5401 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[c]);CHKERRQ(ierr); 5402 } 5403 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5404 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", support[s]);CHKERRQ(ierr); 5405 for (c = 0; c < coneSize; ++c) { 5406 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[c]);CHKERRQ(ierr); 5407 } 5408 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5409 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in cone of support point %d", p, support[s]); 5410 } 5411 } 5412 } 5413 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 5414 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 5415 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %d != Total support size %d", csize, ssize); 5416 PetscFunctionReturn(0); 5417 } 5418 5419 #undef __FUNCT__ 5420 #define __FUNCT__ "DMPlexCheckSkeleton" 5421 /*@ 5422 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 5423 5424 Input Parameters: 5425 + dm - The DMPlex object 5426 . isSimplex - Are the cells simplices or tensor products 5427 - cellHeight - Normally 0 5428 5429 Note: This is a useful diagnostic when creating meshes programmatically. 5430 5431 Level: developer 5432 5433 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 5434 @*/ 5435 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5436 { 5437 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 5438 PetscErrorCode ierr; 5439 5440 PetscFunctionBegin; 5441 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5442 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5443 switch (dim) { 5444 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 5445 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 5446 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 5447 default: 5448 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %d", dim); 5449 } 5450 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5451 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5452 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5453 cMax = cMax >= 0 ? cMax : cEnd; 5454 for (c = cStart; c < cMax; ++c) { 5455 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5456 5457 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5458 for (cl = 0; cl < closureSize*2; cl += 2) { 5459 const PetscInt p = closure[cl]; 5460 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5461 } 5462 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5463 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d vertices != %d", c, coneSize, numCorners); 5464 } 5465 for (c = cMax; c < cEnd; ++c) { 5466 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5467 5468 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5469 for (cl = 0; cl < closureSize*2; cl += 2) { 5470 const PetscInt p = closure[cl]; 5471 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5472 } 5473 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5474 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %d has %d vertices > %d", c, coneSize, numHybridCorners); 5475 } 5476 PetscFunctionReturn(0); 5477 } 5478 5479 #undef __FUNCT__ 5480 #define __FUNCT__ "DMPlexCheckFaces" 5481 /*@ 5482 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 5483 5484 Input Parameters: 5485 + dm - The DMPlex object 5486 . isSimplex - Are the cells simplices or tensor products 5487 - cellHeight - Normally 0 5488 5489 Note: This is a useful diagnostic when creating meshes programmatically. 5490 5491 Level: developer 5492 5493 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 5494 @*/ 5495 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5496 { 5497 PetscInt pMax[4]; 5498 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 5499 PetscErrorCode ierr; 5500 5501 PetscFunctionBegin; 5502 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5503 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5504 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5505 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 5506 for (h = cellHeight; h < dim; ++h) { 5507 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 5508 for (c = cStart; c < cEnd; ++c) { 5509 const PetscInt *cone, *ornt, *faces; 5510 PetscInt numFaces, faceSize, coneSize,f; 5511 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 5512 5513 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 5514 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 5515 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5516 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5517 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5518 for (cl = 0; cl < closureSize*2; cl += 2) { 5519 const PetscInt p = closure[cl]; 5520 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 5521 } 5522 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5523 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d faces but should have %d", c, coneSize, numFaces); 5524 for (f = 0; f < numFaces; ++f) { 5525 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 5526 5527 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5528 for (cl = 0; cl < fclosureSize*2; cl += 2) { 5529 const PetscInt p = fclosure[cl]; 5530 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 5531 } 5532 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); 5533 for (v = 0; v < fnumCorners; ++v) { 5534 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]); 5535 } 5536 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5537 } 5538 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5539 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5540 } 5541 } 5542 PetscFunctionReturn(0); 5543 } 5544 5545 #undef __FUNCT__ 5546 #define __FUNCT__ "DMCreateInterpolation_Plex" 5547 /* Pointwise interpolation 5548 Just code FEM for now 5549 u^f = I u^c 5550 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 5551 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 5552 I_{ij} = psi^f_i phi^c_j 5553 */ 5554 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 5555 { 5556 PetscSection gsc, gsf; 5557 PetscInt m, n; 5558 void *ctx; 5559 DM cdm; 5560 PetscBool regular; 5561 PetscErrorCode ierr; 5562 5563 PetscFunctionBegin; 5564 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 5565 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 5566 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 5567 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 5568 5569 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 5570 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5571 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 5572 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 5573 5574 ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 5575 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 5576 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5577 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5578 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 5579 /* Use naive scaling */ 5580 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 5581 PetscFunctionReturn(0); 5582 } 5583 5584 #undef __FUNCT__ 5585 #define __FUNCT__ "DMCreateInjection_Plex" 5586 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 5587 { 5588 PetscErrorCode ierr; 5589 VecScatter ctx; 5590 5591 PetscFunctionBegin; 5592 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 5593 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 5594 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 5595 PetscFunctionReturn(0); 5596 } 5597 5598 #undef __FUNCT__ 5599 #define __FUNCT__ "DMCreateDefaultSection_Plex" 5600 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 5601 { 5602 PetscSection section; 5603 IS *bcPoints, *bcComps; 5604 PetscBool *isFE; 5605 PetscInt *bcFields, *numComp, *numDof; 5606 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 5607 PetscInt cStart, cEnd, cEndInterior; 5608 PetscErrorCode ierr; 5609 5610 PetscFunctionBegin; 5611 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 5612 /* FE and FV boundary conditions are handled slightly differently */ 5613 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 5614 for (f = 0; f < numFields; ++f) { 5615 PetscObject obj; 5616 PetscClassId id; 5617 5618 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5619 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 5620 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 5621 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 5622 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 5623 } 5624 /* Allocate boundary point storage for FEM boundaries */ 5625 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5626 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5627 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5628 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 5629 ierr = DMGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 5630 for (bd = 0; bd < numBd; ++bd) { 5631 PetscInt field; 5632 PetscBool isEssential; 5633 5634 ierr = DMGetBoundary(dm, bd, &isEssential, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5635 if (isFE[field] && isEssential) ++numBC; 5636 } 5637 /* Add ghost cell boundaries for FVM */ 5638 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 5639 ierr = PetscCalloc3(numBC,&bcFields,numBC,&bcPoints,numBC,&bcComps);CHKERRQ(ierr); 5640 /* Constrain ghost cells for FV */ 5641 for (f = 0; f < numFields; ++f) { 5642 PetscInt *newidx, c; 5643 5644 if (isFE[f] || cEndInterior < 0) continue; 5645 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 5646 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 5647 bcFields[bc] = f; 5648 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5649 } 5650 /* Handle FEM Dirichlet boundaries */ 5651 for (bd = 0; bd < numBd; ++bd) { 5652 const char *bdLabel; 5653 DMLabel label; 5654 const PetscInt *comps; 5655 const PetscInt *values; 5656 PetscInt bd2, field, numComps, numValues; 5657 PetscBool isEssential, duplicate = PETSC_FALSE; 5658 5659 ierr = DMGetBoundary(dm, bd, &isEssential, NULL, &bdLabel, &field, &numComps, &comps, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 5660 if (!isFE[field]) continue; 5661 ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 5662 /* Only want to modify label once */ 5663 for (bd2 = 0; bd2 < bd; ++bd2) { 5664 const char *bdname; 5665 ierr = DMGetBoundary(dm, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5666 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 5667 if (duplicate) break; 5668 } 5669 if (!duplicate && (isFE[field])) { 5670 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 5671 ierr = DMPlexLabelAddCells(dm, label);CHKERRQ(ierr); 5672 } 5673 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 5674 if (isEssential) { 5675 PetscInt *newidx; 5676 PetscInt n, newn = 0, p, v; 5677 5678 bcFields[bc] = field; 5679 if (numComps) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc]);CHKERRQ(ierr);} 5680 for (v = 0; v < numValues; ++v) { 5681 IS tmp; 5682 const PetscInt *idx; 5683 5684 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5685 if (!tmp) continue; 5686 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5687 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5688 if (isFE[field]) { 5689 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 5690 } else { 5691 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 5692 } 5693 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5694 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5695 } 5696 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 5697 newn = 0; 5698 for (v = 0; v < numValues; ++v) { 5699 IS tmp; 5700 const PetscInt *idx; 5701 5702 ierr = DMGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5703 if (!tmp) continue; 5704 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5705 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5706 if (isFE[field]) { 5707 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 5708 } else { 5709 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 5710 } 5711 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5712 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5713 } 5714 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5715 } 5716 } 5717 /* Handle discretization */ 5718 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 5719 for (f = 0; f < numFields; ++f) { 5720 PetscObject obj; 5721 5722 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5723 if (isFE[f]) { 5724 PetscFE fe = (PetscFE) obj; 5725 const PetscInt *numFieldDof; 5726 PetscInt d; 5727 5728 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 5729 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 5730 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 5731 } else { 5732 PetscFV fv = (PetscFV) obj; 5733 5734 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 5735 numDof[f*(dim+1)+dim] = numComp[f]; 5736 } 5737 } 5738 for (f = 0; f < numFields; ++f) { 5739 PetscInt d; 5740 for (d = 1; d < dim; ++d) { 5741 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."); 5742 } 5743 } 5744 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion);CHKERRQ(ierr); 5745 for (f = 0; f < numFields; ++f) { 5746 PetscFE fe; 5747 const char *name; 5748 5749 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 5750 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 5751 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 5752 } 5753 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 5754 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5755 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);ierr = ISDestroy(&bcComps[bc]);CHKERRQ(ierr);} 5756 ierr = PetscFree3(bcFields,bcPoints,bcComps);CHKERRQ(ierr); 5757 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 5758 ierr = PetscFree(isFE);CHKERRQ(ierr); 5759 PetscFunctionReturn(0); 5760 } 5761 5762 #undef __FUNCT__ 5763 #define __FUNCT__ "DMPlexGetRegularRefinement" 5764 /*@ 5765 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 5766 5767 Input Parameter: 5768 . dm - The DMPlex object 5769 5770 Output Parameter: 5771 . regular - The flag 5772 5773 Level: intermediate 5774 5775 .seealso: DMPlexSetRegularRefinement() 5776 @*/ 5777 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 5778 { 5779 PetscFunctionBegin; 5780 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5781 PetscValidPointer(regular, 2); 5782 *regular = ((DM_Plex *) dm->data)->regularRefinement; 5783 PetscFunctionReturn(0); 5784 } 5785 5786 #undef __FUNCT__ 5787 #define __FUNCT__ "DMPlexSetRegularRefinement" 5788 /*@ 5789 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 5790 5791 Input Parameters: 5792 + dm - The DMPlex object 5793 - regular - The flag 5794 5795 Level: intermediate 5796 5797 .seealso: DMPlexGetRegularRefinement() 5798 @*/ 5799 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 5800 { 5801 PetscFunctionBegin; 5802 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5803 ((DM_Plex *) dm->data)->regularRefinement = regular; 5804 PetscFunctionReturn(0); 5805 } 5806 5807 /* anchors */ 5808 #undef __FUNCT__ 5809 #define __FUNCT__ "DMPlexGetAnchors" 5810 /*@ 5811 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 5812 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 5813 5814 not collective 5815 5816 Input Parameters: 5817 . dm - The DMPlex object 5818 5819 Output Parameters: 5820 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 5821 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 5822 5823 5824 Level: intermediate 5825 5826 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 5827 @*/ 5828 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 5829 { 5830 DM_Plex *plex = (DM_Plex *)dm->data; 5831 PetscErrorCode ierr; 5832 5833 PetscFunctionBegin; 5834 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5835 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 5836 if (anchorSection) *anchorSection = plex->anchorSection; 5837 if (anchorIS) *anchorIS = plex->anchorIS; 5838 PetscFunctionReturn(0); 5839 } 5840 5841 #undef __FUNCT__ 5842 #define __FUNCT__ "DMPlexSetAnchors" 5843 /*@ 5844 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 5845 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 5846 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 5847 5848 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 5849 DMGetConstraints() and filling in the entries in the constraint matrix. 5850 5851 collective on dm 5852 5853 Input Parameters: 5854 + dm - The DMPlex object 5855 . 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). 5856 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 5857 5858 The reference counts of anchorSection and anchorIS are incremented. 5859 5860 Level: intermediate 5861 5862 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 5863 @*/ 5864 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 5865 { 5866 DM_Plex *plex = (DM_Plex *)dm->data; 5867 PetscMPIInt result; 5868 PetscErrorCode ierr; 5869 5870 PetscFunctionBegin; 5871 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5872 if (anchorSection) { 5873 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 5874 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 5875 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 5876 } 5877 if (anchorIS) { 5878 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 5879 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 5880 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 5881 } 5882 5883 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 5884 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 5885 plex->anchorSection = anchorSection; 5886 5887 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 5888 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 5889 plex->anchorIS = anchorIS; 5890 5891 #if defined(PETSC_USE_DEBUG) 5892 if (anchorIS && anchorSection) { 5893 PetscInt size, a, pStart, pEnd; 5894 const PetscInt *anchors; 5895 5896 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 5897 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 5898 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 5899 for (a = 0; a < size; a++) { 5900 PetscInt p; 5901 5902 p = anchors[a]; 5903 if (p >= pStart && p < pEnd) { 5904 PetscInt dof; 5905 5906 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 5907 if (dof) { 5908 PetscErrorCode ierr2; 5909 5910 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 5911 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %d cannot be constrained and an anchor",p); 5912 } 5913 } 5914 } 5915 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 5916 } 5917 #endif 5918 /* reset the generic constraints */ 5919 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 5920 PetscFunctionReturn(0); 5921 } 5922 5923 #undef __FUNCT__ 5924 #define __FUNCT__ "DMPlexCreateConstraintSection_Anchors" 5925 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 5926 { 5927 PetscSection anchorSection; 5928 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 5929 PetscErrorCode ierr; 5930 5931 PetscFunctionBegin; 5932 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5933 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 5934 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 5935 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 5936 if (numFields) { 5937 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 5938 } 5939 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 5940 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 5941 pStart = PetscMax(pStart,sStart); 5942 pEnd = PetscMin(pEnd,sEnd); 5943 pEnd = PetscMax(pStart,pEnd); 5944 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 5945 for (p = pStart; p < pEnd; p++) { 5946 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 5947 if (dof) { 5948 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 5949 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 5950 for (f = 0; f < numFields; f++) { 5951 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 5952 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 5953 } 5954 } 5955 } 5956 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 5957 PetscFunctionReturn(0); 5958 } 5959 5960 #undef __FUNCT__ 5961 #define __FUNCT__ "DMPlexCreateConstraintMatrix_Anchors" 5962 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 5963 { 5964 PetscSection aSec; 5965 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 5966 const PetscInt *anchors; 5967 PetscInt numFields, f; 5968 IS aIS; 5969 PetscErrorCode ierr; 5970 5971 PetscFunctionBegin; 5972 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5973 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 5974 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 5975 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 5976 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 5977 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 5978 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 5979 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 5980 /* cSec will be a subset of aSec and section */ 5981 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 5982 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 5983 i[0] = 0; 5984 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 5985 for (p = pStart; p < pEnd; p++) { 5986 ierr = PetscSectionGetDof(aSec,p,&dof);CHKERRQ(ierr); 5987 if (!dof) continue; 5988 ierr = PetscSectionGetOffset(aSec,p,&off);CHKERRQ(ierr); 5989 if (numFields) { 5990 for (f = 0; f < numFields; f++) { 5991 annz = 0; 5992 for (q = 0; q < dof; q++) { 5993 a = anchors[off + q]; 5994 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 5995 annz += aDof; 5996 } 5997 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 5998 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 5999 for (q = 0; q < dof; q++) { 6000 i[off + q + 1] = i[off + q] + annz; 6001 } 6002 } 6003 } 6004 else { 6005 annz = 0; 6006 for (q = 0; q < dof; q++) { 6007 a = anchors[off + q]; 6008 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6009 annz += aDof; 6010 } 6011 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6012 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 6013 for (q = 0; q < dof; q++) { 6014 i[off + q + 1] = i[off + q] + annz; 6015 } 6016 } 6017 } 6018 nnz = i[m]; 6019 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 6020 offset = 0; 6021 for (p = pStart; p < pEnd; p++) { 6022 if (numFields) { 6023 for (f = 0; f < numFields; f++) { 6024 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6025 for (q = 0; q < dof; q++) { 6026 PetscInt rDof, rOff, r; 6027 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6028 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6029 for (r = 0; r < rDof; r++) { 6030 PetscInt s; 6031 6032 a = anchors[rOff + r]; 6033 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6034 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 6035 for (s = 0; s < aDof; s++) { 6036 j[offset++] = aOff + s; 6037 } 6038 } 6039 } 6040 } 6041 } 6042 else { 6043 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6044 for (q = 0; q < dof; q++) { 6045 PetscInt rDof, rOff, r; 6046 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6047 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6048 for (r = 0; r < rDof; r++) { 6049 PetscInt s; 6050 6051 a = anchors[rOff + r]; 6052 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6053 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 6054 for (s = 0; s < aDof; s++) { 6055 j[offset++] = aOff + s; 6056 } 6057 } 6058 } 6059 } 6060 } 6061 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 6062 ierr = PetscFree(i);CHKERRQ(ierr); 6063 ierr = PetscFree(j);CHKERRQ(ierr); 6064 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 6065 PetscFunctionReturn(0); 6066 } 6067 6068 #undef __FUNCT__ 6069 #define __FUNCT__ "DMCreateDefaultConstraints_Plex" 6070 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 6071 { 6072 DM_Plex *plex = (DM_Plex *)dm->data; 6073 PetscSection anchorSection, section, cSec; 6074 Mat cMat; 6075 PetscErrorCode ierr; 6076 6077 PetscFunctionBegin; 6078 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6079 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 6080 if (anchorSection) { 6081 PetscDS ds; 6082 PetscInt nf; 6083 6084 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 6085 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 6086 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 6087 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 6088 ierr = PetscDSGetNumFields(ds,&nf);CHKERRQ(ierr); 6089 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 6090 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 6091 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 6092 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 6093 } 6094 PetscFunctionReturn(0); 6095 } 6096