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