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