chombo-discharge
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | Protected Member Functions | Static Protected Member Functions | Protected Attributes | Static Protected Attributes | List of all members
PolyhedralGeometryShop Class Reference

Geometry generation whose moments are exact integrals of an explicit surface. More...

#include <CD_PolyhedralGeometryShop.H>

Inheritance diagram for PolyhedralGeometryShop:
Inheritance graph
[legend]
Collaboration diagram for PolyhedralGeometryShop:
Collaboration graph
[legend]

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 > &regularBoxes, 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.
 

Static Protected Attributes

static constexpr Real s_weldSpacing = 1.0E-6
 Fraction of the finest grid spacing within which two vertices are the same vertex in sanityCheck.
 
static constexpr Real s_divergenceTolerance = 1.0E-9
 Residual above which the stored moments and the ones PolyGeom recomputes disagree.
 

Detailed Description

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.

Member Enumeration Documentation

◆ UnresolvedAction

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.

Enumerator
Warn 

Report the cells and carry on, leaving it to the user to raise the geometric resolution.

Cover 

Turn the cell solid, so that neither it nor anything cut from it is ever multi valued.

Collapse 

Keep the pieces in one body, taking every moment from their sum and moving only the volume centroid.

For a cell whose interface is one sheet twisted into a saddle, so that cutting it for a refinement leaves a child holding its fluid in two pieces. The pieces are joined a cell away, so the saddle is resolved geometry and is merged rather than covered. A cell holding more than one sheet is still filled.

Conserved: the volume fraction, the apertures, the boundary area vector and the boundary centroid are the exact sums of the pieces', satisfy the divergence identity, and coarsen back to the parent exactly. Face centroids are left as the exact first moment of the open face, even where two patches put it on covered face between them, since the flux stencils read it as a quadrature point.

Not conserved: the scalar boundary area, the length of the summed area vector, is smaller than the area of the interface itself when the pieces face different ways; the interface's own area is kept beside it. And the volume centroid, which is the one moment moved.

The repair: the volume centroid is the exact first moment of the merged fluid, a weighted average of the pieces' centroids, and it can fall in the solid between them. Where it lies in the fluid it is kept. Where it does not, it is replaced by the nearest point of the fluid, moved slightly inside it. That point no longer sums back to the parent's first moment, so coarsening this body's centroid misses the parent's by the distance moved, weighted by this body's volume.

Constructor & Destructor Documentation

◆ PolyhedralGeometryShop()

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.

Parameters
[in]a_localGeomThe implicit function for the geometry
[in]a_verbosityVerbosity
[in]a_dxResolution on the finest level
[in]a_probLoPhysical coordinates of the lower-left corner of the domain
[in]a_finestDomainFinest grid level
[in]a_scanLevelLevel on which to initiate the load balancing sequence
[in]a_ebGhostNumber of EB ghost cells
[in]a_thrshdVoFVolume fraction below which a cut cell is dropped
[in]a_strictWhether a declined cell aborts the run

Member Function Documentation

◆ buildGraphs()

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.

◆ buildSurface()

void PolyhedralGeometryShop::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 
)
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.

Parameters
[in]a_functionImplicit function
[in,out]a_interceptEdge-centred crossing cache
[out]a_surfaceThe values the cell's body is reconstructed from
[in]a_nodeValuesNode-centred implicit function values
[in]a_cellThe cell
[in]a_probLoLower-left corner of computational domain
[in]a_dxGrid resolution

◆ collectFacets()

void PolyhedralGeometryShop::collectFacets ( Vector< Real > &  a_facets,
const int  a_level 
) const
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.

Parameters
[out]a_facetsTriangle coordinates, appended to.
[in]a_levelLevel to collect from.

◆ defineBody()

void PolyhedralGeometryShop::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
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.

Parameters
[out]a_bodyThe body.
[in]a_graphGraph of the cell's level.
[in]a_surfacesSurfaces of the cell's box, from the graph.
[in]a_statesCell states of the cell's box, from the graph.
[in]a_refinedRefined mask of the cell's box, from the graph.
[in]a_cellThe cell.

◆ defineIntercepts()

void PolyhedralGeometryShop::defineIntercepts ( BaseFab< Real >  a_intercept[SpaceDim],
const Box &  a_region 
)
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.

Parameters
[out]a_interceptEdge-centred cache, one fab per direction
[in]a_regionCell-centred region whose edges are wanted

◆ edgeCrossing()

Real PolyhedralGeometryShop::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 
)
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.

Parameters
[in]a_functionImplicit function
[in,out]a_interceptEdge-centred cache, one component per direction
[in]a_cellCell the edge is being read from
[in]a_edgeEdge index within the cell
[in]a_loImplicit function at the edge's low corner
[in]a_hiImplicit function at the edge's high corner
[in]a_probLoLower-left corner of computational domain
[in]a_dxGrid resolution
Returns
Position along the edge, parameterised from its low corner.

◆ edgeRoot()

Real PolyhedralGeometryShop::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 
)
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.

Parameters
[in]a_functionImplicit function.
[in]a_edgeIVNode at the low end of the edge.
[in]a_dirDirection the edge runs in.
[in]a_loValueImplicit function at the low end.
[in]a_hiValueImplicit function at the high end.
[in]a_probLoLower-left corner of the domain.
[in]a_dxGrid spacing.
Returns
Position along the edge, in [0,1].

◆ fillCorners()

void PolyhedralGeometryShop::fillCorners ( PolyhedralEB::CutCellSurface &  a_surface,
const BaseFab< Real > &  a_nodeValues,
const IntVect &  a_cell 
)
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.

Parameters
[out]a_surfaceSurface whose corners are filled. Its crossings are left alone.
[in]a_nodeValuesNode-centred implicit function values
[in]a_cellThe cell

◆ fillGraph()

void PolyhedralGeometryShop::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.

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.

Parameters
[in,out]a_regIrregCoveredRegular/Covered/Irregular cells
[in,out]a_nodesNodes
[in]a_validRegionGrid region
[in]a_ghostRegionGrid region, including ghost cells
[in]a_domainDomain
[in]a_probLoLower-left corner of computational domain
[in]a_dxGrid resolution
[in]a_diGrid index

◆ fillNode()

void PolyhedralGeometryShop::fillNode ( IrregNode &  a_node,
const PolyhedralEB::CutCellBody &  a_body,
const BaseFab< int > &  a_regIrregCovered,
const IntVect &  a_cell,
const ProblemDomain &  a_domain 
) const
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.

Parameters
[out]a_nodeThe node to fill
[in]a_bodyThe cell's assembled polyhedron
[in]a_regIrregCoveredRegular/Covered/Irregular cells
[in]a_cellThe cell
[in]a_domainDomain

◆ fillNodeValues()

void PolyhedralGeometryShop::fillNodeValues ( const BaseIF &  a_function,
BaseFab< Real > &  a_nodeValues,
const Box &  a_region,
const RealVect &  a_probLo,
const Real &  a_dx 
)
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.

Parameters
[in]a_functionImplicit function
[out]a_nodeValuesNode-centred values over a_region
[in]a_regionCell-centred region whose nodes are wanted
[in]a_probLoLower-left corner of computational domain
[in]a_dxGrid resolution

◆ getGraph()

const PolyhedralEBGraph & PolyhedralGeometryShop::getGraph ( const int  a_level) const
noexcept

The graph of a level, undefined below the start level. Stops the run before buildGraphs.

Parameters
[in]a_levelLevel, 0 being the coarsest of the geometry's levels.
Returns
The graph.

◆ indexFacets()

void PolyhedralGeometryShop::indexFacets ( const Vector< Real > &  a_facets,
const Real  a_tolerance,
std::vector< Real > &  a_vertices,
std::vector< int > &  a_connectivity 
)
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.

Parameters
[in]a_facetsTriangles, nine reals each.
[in]a_toleranceDistance within which two positions are the same vertex.
[out]a_verticesThe vertices, three reals each.
[out]a_connectivityThree vertex indices per triangle.

◆ isDust()

bool PolyhedralGeometryShop::isDust ( const PolyhedralEB::CutCellBody &  a_body)
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.

Parameters
[in]a_bodyBody of the cell.
Returns
True if the cell should be treated as regular.

◆ reportUnresolvedRefinement()

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.

◆ resolveTangency()

Real PolyhedralGeometryShop::resolveTangency ( const BaseIF &  a_function,
const RealVect &  a_point,
const Real  a_dx 
)
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.

Parameters
[in]a_functionImplicit function.
[in]a_pointPoint the function is zero at.
[in]a_dxGrid spacing that sets the probe spacing.
Returns
The reading beside the point, or exactly zero if a surface passes through it.

◆ sanityCheck() [1/2]

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.

◆ sanityCheck() [2/2]

void PolyhedralGeometryShop::sanityCheck ( const Vector< RefCountedPtr< PolyhedralEBGraph > > &  a_graphs) const
protected

The closure check over a given set of graphs, one per level as m_graphs holds them.

Parameters
[in]a_graphsGraphs, undefined entries skipped.

◆ setGrids()

void PolyhedralGeometryShop::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.

Parameters
[in]a_compGeomBuilder holding the boxes and their classifications per level.
[in]a_phasePhase whose classifications and implicit function this generator uses.

◆ snappedValue()

Real PolyhedralGeometryShop::snappedValue ( const BaseIF &  a_function,
const RealVect &  a_point,
const Real  a_dx 
)
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.

Parameters
[in]a_functionImplicit function.
[in]a_pointPoint to evaluate at.
[in]a_dxGrid spacing that sets the scale.
Returns
The value, or exactly zero.

◆ testGraphCopy()

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.

◆ verifySurface()

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.

◆ writeSurface()

void PolyhedralGeometryShop::writeSurface ( const std::string &  a_fileName,
const Vector< Vector< Real > > &  a_facets 
) const
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.

Parameters
[in]a_fileNameFile to write, without a suffix.
[in]a_facetsThis rank's triangles of each level, nine reals each.

Member Data Documentation

◆ m_maxRefinement

int PolyhedralGeometryShop::m_maxRefinement
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.

◆ m_sanityCheck

bool PolyhedralGeometryShop::m_sanityCheck
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.

◆ s_probeSpacing

constexpr Real PolyhedralGeometryShop::s_probeSpacing = 1.0E-6
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.

◆ s_rootSnap

constexpr Real PolyhedralGeometryShop::s_rootSnap = 1.0E-4
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.


The documentation for this class was generated from the following files: