|
chombo-discharge
|
Geometry generation whose moments are exact integrals of an explicit surface. More...
#include <CD_PolyhedralGeometryShop.H>


Public Types | |
| enum class | UnresolvedAction { Warn , Cover , Collapse } |
| What to do with a cell this generator cannot describe at the refinement the mesh will ask for. More... | |
Public Member Functions | |
| PolyhedralGeometryShop ()=delete | |
| Disallowed default constructor. | |
| PolyhedralGeometryShop (const BaseIF &a_localGeom, const int a_verbosity, const Real a_dx, const RealVect &a_probLo, const ProblemDomain &a_finestDomain, const ProblemDomain &a_scanLevel, const int a_ebGhost, const Real a_thrshdVoF, const bool a_strict) | |
| Constructor. | |
| ~PolyhedralGeometryShop () override | |
| Destructor. | |
| PolyhedralGeometryShop (const PolyhedralGeometryShop &a_other)=delete | |
| Disallow copy construction. | |
| PolyhedralGeometryShop & | operator= (const PolyhedralGeometryShop &a_other)=delete |
| Disallow copy assignment. | |
| void | fillGraph (BaseFab< int > &a_regIrregCovered, Vector< IrregNode > &a_nodes, const Box &a_validRegion, const Box &a_ghostRegion, const ProblemDomain &a_domain, const RealVect &a_probLo, const Real &a_dx, const DataIndex &a_di) const override |
| Fill the graph and the nodes for one box. | |
| void | setGrids (const ComputationalGeometry &a_compGeom, const phase::which_phase a_phase) noexcept |
| Say which grids the polyhedra are built over, and which phase this generator serves on them. | |
| void | buildGraphs () |
| Build the graph of every tiled level: the cut cells, their surfaces, and what every face opens onto. | |
| const PolyhedralEBGraph & | getGraph (const int a_level) const noexcept |
| The graph of a level, undefined below the start level. Stops the run before buildGraphs. | |
| void | verifySurface () const |
| Build the polyhedra over the grids, check that they form a surface, and write it if asked. | |
| void | sanityCheck () const |
| Check that the interface triangles form a surface that is closed except on the domain boundary. | |
| void | reportUnresolvedRefinement () const |
| Report the cells that cannot be cut for a refinement without falling into more than one piece. | |
| void | testGraphCopy () const |
| Copy every graph onto a layout that splits each of its tiles into octants with the ranks shuffled, and then onto the tiles themselves with the ranks shuffled; run sanityCheck over the copies each time, copy them back onto the original layouts and require equality bit for bit. | |
Public Member Functions inherited from ScanShop | |
| ScanShop ()=delete | |
| Disallowed default constructor. | |
| ScanShop (const BaseIF &a_localGeom, int a_verbosity, Real a_dx, const RealVect &a_probLo, const ProblemDomain &a_finestDomain, const ProblemDomain &a_scanLevel, int a_ebGhost=4, Real a_thrshdVoF=1.0e-16) | |
| Constructor. | |
| ~ScanShop () override | |
| Destructor (does nothing) | |
| ScanShop (const ScanShop &)=delete | |
| Disallow copy construction. | |
| ScanShop & | operator= (const ScanShop &)=delete |
| Disallow copy assignment. | |
| ScanShop (ScanShop &&)=delete | |
| Disallow move construction. | |
| ScanShop & | operator= (ScanShop &&)=delete |
| Disallow move assignment. | |
| void | setProfileFileName (std::string a_fileName) |
| If doing profiling, set the output name. | |
| void | makeGrids (const ProblemDomain &a_domain, DisjointBoxLayout &a_grids, const int &a_maxGridSize, const int &a_maxIrregGridSize) override |
| This grid generation method is called by EBISLevel when using distributed data. | |
| GeometryService::InOut | InsideOutside (const Box &a_region, const ProblemDomain &a_domain, const RealVect &a_probLo, const Real &a_dx, const DataIndex &a_dit) const override |
| This method is called by EBSILevel when using distributed data. | |
| void | fillGraph (BaseFab< int > &a_regIrregCovered, Vector< IrregNode > &a_nodes, const Box &a_validRegion, const Box &a_ghostRegion, const ProblemDomain &a_domain, const RealVect &a_probLo, const Real &a_dx, const DataIndex &a_di) const override |
| Override of GeometryShop's fillGraph. | |
Static Public Member Functions | |
| static bool | isDust (const PolyhedralEB::CutCellBody &a_body) noexcept |
| Whether a cut body holds nothing at all and is therefore a regular cell. | |
| static void | fillNodeValues (const BaseIF &a_function, BaseFab< Real > &a_nodeValues, const Box &a_region, const RealVect &a_probLo, const Real &a_dx) |
| Evaluate the implicit function at every node of a region. | |
| static void | defineIntercepts (BaseFab< Real > a_intercept[SpaceDim], const Box &a_region) |
| Size the edge-crossing cache for a region and mark every edge as not yet bisected. | |
| static Real | edgeCrossing (const BaseIF &a_function, BaseFab< Real > a_intercept[SpaceDim], const IntVect &a_cell, const int a_edge, const Real a_lo, const Real a_hi, const RealVect &a_probLo, const Real &a_dx) |
| Find where the implicit function changes sign along a cell edge. | |
| static void | fillCorners (PolyhedralEB::CutCellSurface &a_surface, const BaseFab< Real > &a_nodeValues, const IntVect &a_cell) |
| Read one cell's corner values off the node values. | |
| static void | buildSurface (const BaseIF &a_function, BaseFab< Real > a_intercept[SpaceDim], PolyhedralEB::CutCellSurface &a_surface, const BaseFab< Real > &a_nodeValues, const IntVect &a_cell, const RealVect &a_probLo, const Real &a_dx) |
| Gather the corner values and edge crossings one cell's surface is built from. | |
| static Real | edgeRoot (const BaseIF &a_function, const IntVect &a_edgeIV, const int a_dir, const Real a_loValue, const Real a_hiValue, const RealVect &a_probLo, const Real a_dx) noexcept |
| Bisect one cell edge for the crossing on it. | |
| static Real | snappedValue (const BaseIF &a_function, const RealVect &a_point, const Real a_dx) noexcept |
| Read the implicit function at a point, with a value within s_snapTolerance of a cell width of zero read as exactly zero, and a zero that is a tangency read from beside the point instead. | |
| static Real | resolveTangency (const BaseIF &a_function, const RealVect &a_point, const Real a_dx) noexcept |
| Read the implicit function beside a point where it is zero, when no surface passes through the point. | |
Static Public Attributes | |
| static constexpr Real | s_snapTolerance = 1.0E-12 |
| Fraction of a cell width within which an implicit-function value is read as exactly zero. | |
| static constexpr Real | s_rootSnap = 1.0E-4 |
| Distance along an edge, from an endpoint that is exactly zero, within which a root is put on it. | |
| static constexpr Real | s_probeSpacing = 1.0E-6 |
| Fraction of a cell width the implicit function is read at either side of a point, to tell a surface through the point from a zero no surface passes through. | |
Protected Member Functions | |
| void | collectFacets (Vector< Real > &a_facets, const int a_level) const |
| Interface triangles of one level, from this rank's share of its irregular boxes, nine reals each. | |
| void | sanityCheck (const Vector< RefCountedPtr< PolyhedralEBGraph > > &a_graphs) const |
| The closure check over a given set of graphs, one per level as m_graphs holds them. | |
| void | defineBody (PolyhedralEB::CutCellBody &a_body, const PolyhedralEBGraph &a_graph, const IVSFAB< PolyhedralEB::CutCellSurface > &a_surfaces, const BaseFab< signed char > &a_states, const BaseFab< signed char > &a_refined, const IntVect &a_cell) const |
| Build the body of a cut cell of a graph, restricted on every face the finer level describes. | |
| void | writeSurface (const std::string &a_fileName, const Vector< Vector< Real > > &a_facets) const |
| Write the surface, the boxes it was built over and the boxes that split, as one HDF5 file per phase. | |
| void | fillNode (IrregNode &a_node, const PolyhedralEB::CutCellBody &a_body, const BaseFab< int > &a_regIrregCovered, const IntVect &a_cell, const ProblemDomain &a_domain) const |
| Write a cut cell's node from its body. | |
Protected Member Functions inherited from ScanShop | |
| void | makeDomains (Real a_dx, const RealVect &a_probLo, const ProblemDomain &a_finestDomain, const ProblemDomain &a_scanLevel) |
| Create the problem domain and resolutions. | |
| void | buildFinerLevels (int a_coarserLevel, int a_maxGridSize) |
| Refine levels recursively down to the finest level. | |
| void | buildCoarseLevel (int a_level, int a_maxGridSize) |
| Build the "coarse level" where we initiate the recursion process. | |
| int | getScanSkip (Real a_slack, Real a_dx) const |
| Number of cells along the scan line that can be passed over without evaluating the implicit function. | |
| bool | isRegular (Box a_box, const RealVect &a_probLo, Real a_dx) const |
| Check if every point in input box is regular. | |
| bool | isCovered (Box a_box, const RealVect &a_probLo, Real a_dx) const |
| Check if every point in box is covered. | |
| std::vector< std::pair< Box, int > > | getSortedBoxesAndTypes (const Vector< Box > &a_boxes, const Vector< int > &a_types) const |
| Sort boxes lexicographically. | |
| void | defineLevel (Vector< Box > &coveredBoxes, Vector< Box > ®ularBoxes, Vector< Box > &cutCellBoxes, int a_level) |
| Define the "box map" on a specified level. | |
Static Protected Member Functions | |
| static void | indexFacets (const Vector< Real > &a_facets, const Real a_tolerance, std::vector< Real > &a_vertices, std::vector< int > &a_connectivity) |
| Identify the vertices of a triangle soup, giving each one once and each triangle three indices. | |
Protected Attributes | |
| const ComputationalGeometry * | m_compGeom |
| The geometry whose grids the polyhedra are built over, or null before setGrids. | |
| Vector< RefCountedPtr< PolyhedralEBGraph > > | m_graphs |
| Graph of every level, indexed as the geometry indexes its levels; undefined where a level has no tiles. | |
| phase::which_phase | m_phase |
| Phase this generator serves on those grids. | |
| bool | m_writeSurface |
| Whether verifySurface writes the surface. PolyhedralGeometryShop.write_surface, off by default. | |
| bool | m_sanityCheck |
| Whether verifySurface runs sanityCheck. PolyhedralGeometryShop.sanity_check. | |
| bool | m_profile |
| Whether verifySurface reports its timings. PolyhedralGeometryShop.profile, off by default. | |
| int | m_maxRefinement |
| How far below the geometry's own grids a cell must stay single valued. PolyhedralGeometryShop.max_refinement, one – that is, off – by default. | |
| UnresolvedAction | m_unresolvedAction |
| What becomes of a cell that fails that test. PolyhedralGeometryShop.unresolved_cells, warn by default. | |
| bool | m_testCopy |
| Whether verifySurface runs testGraphCopy. PolyhedralGeometryShop.test_copy, off by default. | |
| bool | m_verbose |
| Whether the member functions that run once per level or per phase announce themselves in pout. PolyhedralGeometryShop.verbose, off by default. The functions that run per cell never announce themselves. | |
| bool | m_strict |
| Whether a declined cell aborts the run rather than falling back. | |
| Real | m_volumeThreshold |
| Volume fraction below which a cut cell carries no fluid worth keeping. | |
Protected Attributes inherited from ScanShop | |
| std::string | m_fileName |
| Set output file name (if doing profiling) | |
| BoxSorting | m_boxSorting |
| For arranging boxes in space when we load balance. | |
| Timer | m_timer |
| Timer for when we use run-time profiling. | |
| bool | m_profile |
| Bool for run-time profiling of ScanShop. | |
| bool | m_distanceSkip |
| Whether or not the box scan may skip cells using the implicit function value as a distance. | |
| int | m_scanLevel |
| Scan level where we first begin to break up boxes. This is relative the EBIS level. | |
| int | m_ebGhost |
| Maximum number of ghost cells near the EB. | |
| RealVect | m_probLo |
| Lower-left corner of simulation domain. | |
| const BaseIF * | m_baseIF |
| Implicit function used to generate geometries. | |
| bool | m_hasScanLevel |
| Check if scan level has been built. | |
| Vector< Real > | m_dx |
| Level resolutions. Note that index 0 is the finest level. | |
| Vector< ProblemDomain > | m_domains |
| Level domains. Note that index 0 is the finest level. | |
| Vector< DisjointBoxLayout > | m_grids |
| Grids on each level, used for generating the EBIS information. | |
| Vector< RefCountedPtr< LayoutData< GeometryService::InOut > > > | m_boxMap |
| Box maps. | |
| std::vector< bool > | m_hasThisLevel |
| Check if level has been scanned. 0 = false, != 0 implies true. | |
Geometry generation whose moments are exact integrals of an explicit surface.
Takes the same topology as GeometryShop – the same classification, the same graph and the same covered-cell fix-ups – and replaces only the quadrature. Where GeometryShop integrates the arc the interface really follows, this assembles the closed polyhedron whose faces are bounded by straight chords between the edge crossings and integrates that.
The difference is deliberate and costs accuracy on curved geometry, where the apertures drop from third order to second. What it buys is that the moments are the moments of a body, so they satisfy the relations Chombo's own coarsening applies to them, and a subdivision of that body sums back to it exactly.
Cells are declined rather than approximated when the assembled polygons do not close. That is fatal by default: it has never fired on any geometry tested, and a cell that trips it is an edge case worth seeing rather than absorbing.
|
strong |
What to do with a cell this generator cannot describe at the refinement the mesh will ask for.
A cell whose fluid falls into more than one piece when it is cut for a refinement cannot be carried single valued at that ratio, and there is no reformulation of the interior that avoids it: the only representation guaranteed to keep every descendant single valued is a planar interface, and a planar interface cannot meet the face chords a cell shares with its neighbours. So the cell is a choice rather than a bug, and the choice belongs to whoever set up the run.
| PolyhedralGeometryShop::PolyhedralGeometryShop | ( | const BaseIF & | a_localGeom, |
| const int | a_verbosity, | ||
| const Real | a_dx, | ||
| const RealVect & | a_probLo, | ||
| const ProblemDomain & | a_finestDomain, | ||
| const ProblemDomain & | a_scanLevel, | ||
| const int | a_ebGhost, | ||
| const Real | a_thrshdVoF, | ||
| const bool | a_strict | ||
| ) |
Constructor.
| [in] | a_localGeom | The implicit function for the geometry |
| [in] | a_verbosity | Verbosity |
| [in] | a_dx | Resolution on the finest level |
| [in] | a_probLo | Physical coordinates of the lower-left corner of the domain |
| [in] | a_finestDomain | Finest grid level |
| [in] | a_scanLevel | Level on which to initiate the load balancing sequence |
| [in] | a_ebGhost | Number of EB ghost cells |
| [in] | a_thrshdVoF | Volume fraction below which a cut cell is dropped |
| [in] | a_strict | Whether a declined cell aborts the run |
| void PolyhedralGeometryShop::buildGraphs | ( | ) |
Build the graph of every tiled level: the cut cells, their surfaces, and what every face opens onto.
One PolyhedralEBGraph per level from the geometry's start level up, over that level's cut tiles, each defined from this phase's implicit function with one ghost cell and then linked to the level above it so that the coarse side of every level boundary knows which of its cells and faces the finer level describes. The levels below the start level carry no graph. Collective. Requires setGrids.
|
static |
Gather the corner values and edge crossings one cell's surface is built from.
The corners come from the shared node values and every edge whose ends disagree gets its crossing through the shared cache, so every caller that reconstructs a cell – the graph, the surface pass and the grid builder's curvature test – builds the same cell.
| [in] | a_function | Implicit function |
| [in,out] | a_intercept | Edge-centred crossing cache |
| [out] | a_surface | The values the cell's body is reconstructed from |
| [in] | a_nodeValues | Node-centred implicit function values |
| [in] | a_cell | The cell |
| [in] | a_probLo | Lower-left corner of computational domain |
| [in] | a_dx | Grid resolution |
|
protected |
Interface triangles of one level, from this rank's share of its irregular boxes, nine reals each.
Cells the next finer level carries are skipped. A cut cell with such a cell across one of its faces has that face restricted to the finer cells' chords (restrictFace) and its interface rebuilt (closeInterface). A coarse edge that carries no crossing while both finer edges under it do is a multi-valued coarse cell in disguise and stops the run, as does a body that will not close.
| [out] | a_facets | Triangle coordinates, appended to. |
| [in] | a_level | Level to collect from. |
|
protected |
Build the body of a cut cell of a graph, restricted on every face the finer level describes.
The body is defined from the cell's surface, and every face onto a refined neighbour is replaced by the chords of the cell's own children, reconstructed from the implicit function at the finer spacing, after the check that no coarse edge on that face is crossed twice at the finer spacing; the interface is closed again afterwards. A face onto a cell the graph filled is closed instead, through CutCellBody::snapFace, and the footprint it gives up becomes interface lying in the plane of that face, so the surface closes over the filled cell rather than ending against it. A body that will not close, a face that cannot be restricted or closed, or a doubly crossed edge stops the run.
| [out] | a_body | The body. |
| [in] | a_graph | Graph of the cell's level. |
| [in] | a_surfaces | Surfaces of the cell's box, from the graph. |
| [in] | a_states | Cell states of the cell's box, from the graph. |
| [in] | a_refined | Refined mask of the cell's box, from the graph. |
| [in] | a_cell | The cell. |
|
static |
Size the edge-crossing cache for a region and mark every edge as not yet bisected.
One fab per direction, over the edges of the region's cells, addressed by the node at the low end of the edge as edgeCrossing addresses them.
| [out] | a_intercept | Edge-centred cache, one fab per direction |
| [in] | a_region | Cell-centred region whose edges are wanted |
|
static |
Find where the implicit function changes sign along a cell edge.
Bisection between the two endpoints, looked up in a cache first. Every cut edge is reached from both of its adjoining faces and from each neighbouring cell, always with the same endpoints, so the root is found once and reused. That is what makes two cells agree on a shared aperture bit for bit.
| [in] | a_function | Implicit function |
| [in,out] | a_intercept | Edge-centred cache, one component per direction |
| [in] | a_cell | Cell the edge is being read from |
| [in] | a_edge | Edge index within the cell |
| [in] | a_lo | Implicit function at the edge's low corner |
| [in] | a_hi | Implicit function at the edge's high corner |
| [in] | a_probLo | Lower-left corner of computational domain |
| [in] | a_dx | Grid resolution |
|
staticnoexcept |
Bisect one cell edge for the crossing on it.
An endpoint at exactly zero is not taken to be the crossing: the function may be zero along a stretch of the edge (a face of the geometry lying in the edge's plane), and the crossing is where it leaves that stretch. The bisection walks through zeros, which the fluid predicate reads as solid, and a root that lands within s_snapTolerance of an endpoint that is exactly zero is put exactly on it.
| [in] | a_function | Implicit function. |
| [in] | a_edgeIV | Node at the low end of the edge. |
| [in] | a_dir | Direction the edge runs in. |
| [in] | a_loValue | Implicit function at the low end. |
| [in] | a_hiValue | Implicit function at the high end. |
| [in] | a_probLo | Lower-left corner of the domain. |
| [in] | a_dx | Grid spacing. |
|
static |
Read one cell's corner values off the node values.
Corner c of the cell is the node offset by ((c >> d) & 1) in each direction d.
| [out] | a_surface | Surface whose corners are filled. Its crossings are left alone. |
| [in] | a_nodeValues | Node-centred implicit function values |
| [in] | a_cell | The cell |
|
override |
Fill the graph and the nodes for one box.
Classifies the cells, reuses GeometryShop's fix-up for the regular cells bordering a covered one, and then builds each remaining irregular cell's node from the polyhedron rather than from a quadrature of the implicit function.
| [in,out] | a_regIrregCovered | Regular/Covered/Irregular cells |
| [in,out] | a_nodes | Nodes |
| [in] | a_validRegion | Grid region |
| [in] | a_ghostRegion | Grid region, including ghost cells |
| [in] | a_domain | Domain |
| [in] | a_probLo | Lower-left corner of computational domain |
| [in] | a_dx | Grid resolution |
| [in] | a_di | Grid index |
|
protected |
Write a cut cell's node from its body.
The arcs come from the covered set and the domain rather than from the moments, so the graph this produces is the one GeometryShop would have produced. The apertures, the centroids and the volume fraction come from the body.
| [out] | a_node | The node to fill |
| [in] | a_body | The cell's assembled polyhedron |
| [in] | a_regIrregCovered | Regular/Covered/Irregular cells |
| [in] | a_cell | The cell |
| [in] | a_domain | Domain |
|
static |
Evaluate the implicit function at every node of a region.
One evaluation per node rather than per cell corner, since the cells meeting at a node share it and must agree on its value. Values are read through snappedValue.
| [in] | a_function | Implicit function |
| [out] | a_nodeValues | Node-centred values over a_region |
| [in] | a_region | Cell-centred region whose nodes are wanted |
| [in] | a_probLo | Lower-left corner of computational domain |
| [in] | a_dx | Grid resolution |
|
noexcept |
The graph of a level, undefined below the start level. Stops the run before buildGraphs.
| [in] | a_level | Level, 0 being the coarsest of the geometry's levels. |
|
staticprotected |
Identify the vertices of a triangle soup, giving each one once and each triangle three indices.
Two positions closer than the tolerance are one vertex. Candidates are taken from the lattice cell of the tolerance a position falls in and the twenty-six around it, which is what keeps this out of the quadratic scan a surface meeting the mesh squarely would otherwise provoke, with every candidate still measured against so that two positions either side of a lattice wall are not told apart.
| [in] | a_facets | Triangles, nine reals each. |
| [in] | a_tolerance | Distance within which two positions are the same vertex. |
| [out] | a_vertices | The vertices, three reals each. |
| [out] | a_connectivity | Three vertex indices per triangle. |
|
staticnoexcept |
Whether a cut body holds nothing at all and is therefore a regular cell.
A node that lands exactly on the interface is solid by rule, so the cells around it classify as cut from their corners while their bodies hold no solid and no interface whatsoever – the reconstruction finds an empty polyhedron. Those cells are regular, and dropping them discards nothing, since there is no surface in them for a neighbour to meet. Emptiness is exact rather than thresholded: a body with any solid in it, however little, keeps its cell, because its interface is what closes the surface against its neighbours, and a rule that discarded it by size would leave a hole the size of what it discarded. A cell whose interface lies in one of its faces has no solid volume either, but it does have boundary area, and it is not dust.
| [in] | a_body | Body of the cell. |
| void PolyhedralGeometryShop::reportUnresolvedRefinement | ( | ) | const |
Report the cells that cannot be cut for a refinement without falling into more than one piece.
Asked of every cut cell the level itself describes, at the ratio m_maxRefinement names, and of the body the consumers build – which on a refinement boundary is the one whose faces were taken from the finer level, since stitching lengthens the interface loop and it is that loop the question is about. A cell whose interface is planar is exempt without being cut, because its fluid is then convex and convexity survives every ratio.
What happens to a failing cell is m_unresolvedAction's to decide. Only Warn is wired: the cells are named and the run continues, leaving it to whoever set it up to raise the geometric resolution. Runs regardless of m_sanityCheck, since it reports on the geometry the run will actually use rather than on this generator's own consistency. Requires buildGraphs.
|
staticnoexcept |
Read the implicit function beside a point where it is zero, when no surface passes through the point.
A composite function can be zero over a whole region that is not its surface: a difference of two bodies sharing a face evaluates to the maximum of zero and something negative over the whole of that face. Taken at face value such a zero is material by the fluid rule, and it invents an interface where the geometry has none and displaces the interfaces of whatever else the cell holds. It is told apart from a surface by the function's sign a probe spacing off the point, along each axis in turn. A surface through the point changes the sign across it along any axis the surface is not parallel to, and since a surface has a normal there is always such an axis, so one sign change is enough to leave the zero alone. The zero is read through only on the evidence of an axis whose two readings are both away from zero and of the same sign, which is what a function that touches zero without a surface being there looks like; the largest such reading stands in for the zero. One reading of zero is not evidence of anything – it is the point's own zero again, which is what an axis along a face of the geometry returns, and what both axes along the faces meeting at a convex edge return.
| [in] | a_function | Implicit function. |
| [in] | a_point | Point the function is zero at. |
| [in] | a_dx | Grid spacing that sets the probe spacing. |
| void PolyhedralGeometryShop::sanityCheck | ( | ) | const |
Check that the interface triangles form a surface that is closed except on the domain boundary.
A triangle edge can be shared only by cells that touch, so every edge of a cell's interface must be used exactly twice among the interface triangles of the cell and of its 3^D neighbourhood: on the cell's own level through the ghost surfaces the graph holds, and across a level boundary through the finer cells behind a face the finer level describes, reconstructed for the purpose. An edge in the domain boundary is used once, an edge in a face the coarser level describes is checked from that side, and an edge in a face onto a cell the graph filled has no partner to meet, since that face is closed. Every rank checks its own cells, vertices are welded at s_weldSpacing times the finest spacing, the counts are summed, and a violation stops the run. A regular cell sharing a face with a covered one stops the run as well: the four nodes of that face belong to both cells and cannot be fluid for one and solid for the other, so the pair can only come from a classification that disagrees with itself, and there would be no cut cell to carry the interface between them. A filled cell is covered whatever its nodes read, which is why the graph keeps a neighbour of one as a cut cell holding the whole of itself rather than a regular one; the test is what says it did. That test is dimension-independent and runs on every graph, including the cells beyond the tiles, which is where the edge of the tiled region meets what no tile carries. Switched by PolyhedralGeometryShop.sanity_check, on by default in a build that keeps its assertions. Requires buildGraphs.
|
protected |
The closure check over a given set of graphs, one per level as m_graphs holds them.
| [in] | a_graphs | Graphs, undefined entries skipped. |
|
noexcept |
Say which grids the polyhedra are built over, and which phase this generator serves on them.
| [in] | a_compGeom | Builder holding the boxes and their classifications per level. |
| [in] | a_phase | Phase whose classifications and implicit function this generator uses. |
|
staticnoexcept |
Read the implicit function at a point, with a value within s_snapTolerance of a cell width of zero read as exactly zero, and a zero that is a tangency read from beside the point instead.
A face of the geometry lying in a node plane evaluates to zero there only up to round-off: the same face comes back as plus zero, minus zero and a few parts in 1e19 at neighbouring nodes, and cells on either side of it would then be classified by which of those they were handed. Reading everything within a fixed fraction of the cell width of zero as zero puts every such node on one side by rule, in the corner values and in the bisection alike. A zero that no surface passes through is then read through resolveTangency, so that nothing downstream sees it.
| [in] | a_function | Implicit function. |
| [in] | a_point | Point to evaluate at. |
| [in] | a_dx | Grid spacing that sets the scale. |
| void PolyhedralGeometryShop::testGraphCopy | ( | ) | const |
Copy every graph onto a layout that splits each of its tiles into octants with the ranks shuffled, and then onto the tiles themselves with the ranks shuffled; run sanityCheck over the copies each time, copy them back onto the original layouts and require equality bit for bit.
A stand-in, until the index space is generated over the graphs, for what a consumer on another layout does: take the graph's data through a Copier and read it there. Switched by PolyhedralGeometryShop.test_copy. Collective. Requires buildGraphs.
| void PolyhedralGeometryShop::verifySurface | ( | ) | const |
Build the polyhedra over the grids, check that they form a surface, and write it if asked.
Every cut cell of every irregular box is reconstructed at its own level, cells the next finer level carries are skipped, and a face shared with such a cell is restricted to the finer chords and the interface closed. The interface triangles of every level are then checked by sanityCheck when PolyhedralGeometryShop.sanity_check is set, and written to the geometry directory as an indexed surface mesh when PolyhedralGeometryShop.write_surface is set. Collective; every rank reconstructs its share of the boxes and writes its own share of the mesh. Requires setGrids.
|
protected |
Write the surface, the boxes it was built over and the boxes that split, as one HDF5 file per phase.
One group per level, holding the level's triangles as an indexed mesh – the vertices once each and a triple of indices per triangle – rather than as a soup of coordinates, which is what a viewer wants and what an XDMF description can point at. The boxes of the level and the boxes that split on it go in the same group, so that the surface can be read against the grids it was built on without a second file. The distance within which two positions are one vertex is written alongside them. An XDMF description of the file is written next to it. Collective: every rank writes its own stretch of every dataset, so a vertex on a boundary between two ranks is written by each, since vertices are identified within a rank and not across them.
| [in] | a_fileName | File to write, without a suffix. |
| [in] | a_facets | This rank's triangles of each level, nine reals each. |
|
protected |
How far below the geometry's own grids a cell must stay single valued. PolyhedralGeometryShop.max_refinement, one – that is, off – by default.
A power of two. One asks for nothing and skips the check entirely; two asks that the cells one refinement below the geometry grid are each a single piece of fluid, four that the cells two below are, and so on. The property is not inherited – a cell whose children are all single valued can still have a grandchild that is not – so this has to name the ratio the mesh will actually use rather than being derived from one level.
Off by default because the test costs a subdivision of every cut cell whose interface is not planar, which is two to three times what building the geometry costs in the first place, and because nothing downstream reads a subdivided cell yet. It becomes worth its price once it does.
|
protected |
Whether verifySurface runs sanityCheck. PolyhedralGeometryShop.sanity_check.
On by default in a build that keeps its assertions and off in one that does not, since the check tells the generator nothing it uses and only reports. Either default can be overridden from the inputs.
|
staticconstexpr |
Fraction of a cell width the implicit function is read at either side of a point, to tell a surface through the point from a zero no surface passes through.
Large enough that a function of unit gradient reads well clear of s_snapTolerance beside the point, and small enough that the reading belongs to the point rather than to its neighbourhood.
|
staticconstexpr |
Distance along an edge, from an endpoint that is exactly zero, within which a root is put on it.
A surface tangent to a node reads as zero for a stretch either side of it under the value snap, of length about sqrt(2 R tol / dx) for a radius of curvature R – a few parts in 1e6 of an edge for any R that is not itself below the cell width. A root that close to a corner the surface passes through is that stretch's end, not a second crossing; a genuine second crossing within 1e-4 of a cell width of the first would be a feature no cell resolves.