|
IBAMR
IBAMR version 0.19.
|
Encapsulates a set of DLBG edges that connect two LayerNodeSet objects. More...
#include <LayerEdgeSet.h>
Classes | |
| struct | CommunicationStruct |
| Data sorted by a hash. More... | |
Public Types | |
| enum | ParallelState { DISTRIBUTED, GLOBALIZED } |
| Names of parallel states. More... | |
| typedef LayerNode< DIM > | Node |
| typedef Node::LocalIndex | LocalIndex |
| typedef LayerNodeSet< DIM >::NodeContainer | NodeContainer |
| Container for nodes. More... | |
| typedef LayerNodeSet< DIM >::NodeContainer | NabrContainer |
| Container for neighbors. More... | |
| typedef std::map< LocalIndex, NabrContainer > | Connectivity |
| Connectivity data between two node layers. More... | |
Public Member Functions | |
| LayerEdgeSet () | |
| Constructor. More... | |
| virtual | ~LayerEdgeSet (void) |
| Destructor. More... | |
| const NodeContainer & | getNodeContainer (const int rank=-1) const |
| const Connectivity & | getConnectivity (const int rank=-1) const |
| const hier::IntVector< DIM > & | getBaseRefinementRatio () const |
| const hier::IntVector< DIM > & | getHeadRefinementRatio () const |
| void | attachPartner (LayerEdgeSet &partner) |
| Mutually attach to another layer-edge object to create a bi-directional set of edges. More... | |
| LayerEdgeSet & | createPartner (const LayerNodeSet< DIM > &partner_base, const Connectivity *partner_connectivity=NULL) |
| LayerEdgeSet & | getPartner () |
| Access the attached partner. More... | |
| const LayerEdgeSet & | getPartner () const |
| Access the attached partner. More... | |
| void | initialize (ParallelState parallel_state, const LayerNodeSet< DIM > &base_layer, const hier::IntVector< DIM > &head_refinement_ratio, const hier::IntVector< DIM > &gcw=hier::IntVector< DIM >(1), const Connectivity *connectivity=NULL) |
| Set data defining the edge set. More... | |
| LayerEdgeSet & | operator= (const LayerEdgeSet &r) |
| Assignment operator duplicates edge data and reference to layer node set and sets up a similar partner relationship and parallel mode. More... | |
Algorithms for computing edge data | |
| void | findEdges () |
| Discover and add edges between self and partner. More... | |
| void | bridge (const LayerEdgeSet &edge_to_head, const LayerEdgeSet &edge_to_base) |
| Create the layer edge data by bridging the heads of two layer edges whose base nodes are identical to each other. More... | |
| void | replaceNodes (const LayerEdgeSet &map) |
| Replace some nodes with others. More... | |
| void | setParallelState (const ParallelState parallel_state) |
| Set the parallel distribution state. More... | |
| ParallelState | getParallelState () const |
| void | deallocateData () |
| Deallocate internal data on nodes and neighbors. More... | |
| void | setMaxGhostCellWidth (const hier::IntVector< DIM > &gcw) |
| Set the max ghost cell width used to check for box intersections. More... | |
| const hier::IntVector< DIM > & | getMaxGhostCellWidth () const |
| static void | findEdges (LayerEdgeSet &a, LayerEdgeSet &b) |
For outputs, error checking and debugging. | |
| hier::IntVector< DIM > | d_gcw |
| Max ghost cell width. More... | |
| hier::IntVector< DIM > | d_head_ratio |
| Head layer refinement ratio. More... | |
| const LayerNodeSet< DIM > * | d_base |
| Reference to the base layer of nodes. More... | |
| Connectivity * | d_cnect |
| Neighbor data. More... | |
| ParallelState | d_parallel_state |
| State flag. More... | |
| LayerEdgeSet * | d_partner |
| bool | d_partner_is_managed |
| Whether partner is internally created and managed. More... | |
| const int | d_rank |
| const int | d_nprocs |
| virtual void | printClassData (std::ostream &co, int debase_depth=0) const |
| void | printEdgeStats (std::ostream &co) const |
| void | checkNodeNabrCorrespondance () const |
| Check that the node and neighbor containers have a one-to-one correspondance. More... | |
| void | checkNodeConsistency () const |
| Check that the node referenced by connectivity match those in the partner's base LayerNodeSet. More... | |
| void | checkConnectivity (const LayerNodeSet< DIM > &head) const |
| static void | checkNodeConsistency (const NodeContainer &local_nodes, const Connectivity &cnect, const LayerNodeSet< DIM > &head_layer) |
| Check that nodes referenced by a given connectivity object match nodes in the given node containers. More... | |
| Connectivity & | getConnectivity (const int rank=-1) |
| void | deallocateDataSelf () |
| Deallocate internal data but do not touch partner's data. More... | |
| void | allocateConnectivity (const NodeContainer &node_container, Connectivity &cnect) const |
| Allocate a list of neighbors for every node in a given node container. More... | |
| void | bridge_discoverEdges (const LayerEdgeSet &edge_to_head, const LayerEdgeSet &edge_to_base, std::map< LocalIndex, CommunicationStruct > &mesg_to_owners, const bool ignore_self_overlap) |
| Discover phase of bridging. More... | |
| void | bridge_shareEdges (std::map< LocalIndex, CommunicationStruct > &mesg_to_owners) |
| Share phase of bridging. More... | |
| void | findEdges_serial (LayerEdgeSet &other) |
| Discover and add edges between self and another, including remote edges. More... | |
| void | findEdges_quadratic (const LayerEdgeSet &other) |
| Discover and add edges between self and another, including remote edges. More... | |
| void | findEdges_rbbt (const LayerNodeSet< DIM > &head, const bool ignore_self_overlap=false) |
| Discover and add edges from base and externally provided head layer. More... | |
| void | getNabrOwnerSet (const Connectivity &cnect, std::set< int > &owners) const |
| Get a list of owners of neighbors. More... | |
| static LayerNodeSet< DIM > * | copyAndGlobalize (const LayerNodeSet< DIM > &r) |
Distributed Layered Box-graph (DLBG):
A box-graph is a graph where the nodes correspond to boxes and edges connect neighboring nodes. Two nodes are neighbors if their boxes overlap when one is grown by some nominal ghost-cell-width. Each edge is defined by the two nodes it connects. The box-graph is useful in SAMR because it shows which boxes directly interact with each other.
We can organize nodes of a box-graph into groups of boxes defined on the same index space. When sorted from coarsest to finest index spaces, the nodes fall into distinct layers. A "layer" is similar to a level in the hierarchy in that patches in a level share the same index space. We use layer instead of level to differentiate the graph from the hierarchy and because a layer does not necessarily have a one-to-one association with a level.
For convenience, we define
An edge is directional, like an arrow, starting at a base node and ending at a head node. Each pair of neighboring nodes has two edges, pointing in opposite directions. This goes also for LayerNodeSet and LayerEdgeSet objects. A single LayerEdgeSet object represents a set of directed edges incident from one base LayerNodeSet to one head LayerNodeSet. The edges pointing in the oposite direction are stored in a separate LayerEdgeSet object.
An object of this class can be partnered with another object that represents the directed edges in the opposite direction. The head of one partner is the base of the other. The partner does not provide additional information but it does organize the information differently. If the edge data is represented as a matrix, then one partner is the transpose of the other. A partnership allows both objects to be modified simultaneously so that their data is consistent. This avoids having to modify one after the other, which is problematic because the second modification begins with inconsistent data.
Two layers may contain edges in opposite directions and not be attached; but they would not be automatically coordinated in that case.
In parallel, a LayerNodeSet can also be in distributed or globalized (see LayerNodeSet). A locally-owned node is called a local node. Nodes owned by other processors are remote notes. Remote nodes are stilled called remote nodes when the LayerNodeSet is globalized. Local knowledge of a remote node does not make it local.
In parallel, we may partition the layer-edge and store it across many processors. The edge are classified as follows:
The parallel state of a LayerEdgeSet object can be:
The distribution state is changed by setParallelState(). Going to a more distributed state primarily means deallocating data, but going to a more serial state requires sharing of data (communicating). Currently, collected state for LayerEdgeSet objects seems to be unneeded.
The general attributes of a LayerEdgeSet are:
The connectivity depends on the base LayerNodeSet and the ghost-cell-width, so it is discarded when either of these is manually changed.
| typedef LayerNode<DIM> SAMRAI::hier::LayerEdgeSet< DIM >::Node |
| typedef Node::LocalIndex SAMRAI::hier::LayerEdgeSet< DIM >::LocalIndex |
| typedef LayerNodeSet<DIM>::NodeContainer SAMRAI::hier::LayerEdgeSet< DIM >::NodeContainer |
This is a sorted container so that it can be compared without expensive searches. A node can be removed or added without changing the indices of existing nodes.
| typedef LayerNodeSet<DIM>::NodeContainer SAMRAI::hier::LayerEdgeSet< DIM >::NabrContainer |
| typedef std::map<LocalIndex,NabrContainer> SAMRAI::hier::LayerEdgeSet< DIM >::Connectivity |
The connectivity m maps a node with index i to a set of nodes m[i], usually its neighbors. (The neighbors data is a container of nodes.)
Because Connectivity is indexed by the LocalIndex instead of a combined owner and LocalIndex, each Connectivity object is implicitly associated with just one owner process.
| enum SAMRAI::hier::LayerEdgeSet::ParallelState |
| SAMRAI::hier::LayerEdgeSet< DIM >::LayerEdgeSet | ( | ) |
The default constructor creates empty object in distributed state.
|
virtual |
Deallocate internal data.
| const NodeContainer& SAMRAI::hier::LayerEdgeSet< DIM >::getNodeContainer | ( | const int | rank = -1 | ) | const |
| const Connectivity& SAMRAI::hier::LayerEdgeSet< DIM >::getConnectivity | ( | const int | rank = -1 | ) | const |
| const hier::IntVector<DIM>& SAMRAI::hier::LayerEdgeSet< DIM >::getBaseRefinementRatio | ( | ) | const |
| const hier::IntVector<DIM>& SAMRAI::hier::LayerEdgeSet< DIM >::getHeadRefinementRatio | ( | ) | const |
| void SAMRAI::hier::LayerEdgeSet< DIM >::attachPartner | ( | LayerEdgeSet< DIM > & | partner | ) |
Preconditions on the partner and this object:
Both objects must be in the same parallel state. Their parallel states will change together for the the duration of the partnership.
Both objects are modified to reference each other as mutual partners. Both objects must be unpartnered. Multiple partners are not allowed. Once two layer edges objects are attached, they are synchronized when either calls a synchronizing method. Synchronizing means making all edges between them seen by both objects. (This does not mean that remote edges are seen in DISTRIBUTED modes though.)
The relationship between two attached objects is symmetric, that is, a.attach(b) has the same effect as b.attach(a). It is permissible to pass *this in for partner, which is how peer edges are set up.
Since the partner is not created internally, it is NOT explicitly deleted when this object goes out of scope. It will simply be detached. This is in contrast to createPartner().
| LayerEdgeSet& SAMRAI::hier::LayerEdgeSet< DIM >::createPartner | ( | const LayerNodeSet< DIM > & | partner_base, |
| const Connectivity * | partner_connectivity = NULL |
||
| ) |
| LayerEdgeSet& SAMRAI::hier::LayerEdgeSet< DIM >::getPartner | ( | ) |
Error if no partner is attached.
| const LayerEdgeSet& SAMRAI::hier::LayerEdgeSet< DIM >::getPartner | ( | ) | const |
Error if no partner is attached.
| void SAMRAI::hier::LayerEdgeSet< DIM >::initialize | ( | ParallelState | parallel_state, |
| const LayerNodeSet< DIM > & | base_layer, | ||
| const hier::IntVector< DIM > & | head_refinement_ratio, | ||
| const hier::IntVector< DIM > & | gcw = hier::IntVector< DIM >(1), |
||
| const Connectivity * | connectivity = NULL |
||
| ) |
The object must not be attached to a partner. This method resets enough data to make coordination with partners irrelevant. You must detach the partner (if any) before calling this method. There should be no reason to use this method while attached.
A reference is made to the given LayerNodeSet. The ghost cell width is copied. If connectivity is given, a copy is made from it. This is meant for use when you have an external means for computing the connectivity data. (The accuracy and consistency of the connectivity is not checked!) If connectivity is not given, it should be created using findEdges() before calling a method that uses it.
The parallel state is initialized to the given parallel_state. If state is GLOBALIZED:
base_layer must be in GLOBALIZED mode.A reference is made to the given LayerNodeSet, replacing the current node reference.
When debug is enabled, some checks are made to assert that base_layer and connectivity are consistent with each other.
| LayerEdgeSet& SAMRAI::hier::LayerEdgeSet< DIM >::operator= | ( | const LayerEdgeSet< DIM > & | r | ) |
If r is attached to itself, self-attach. If r is attached but not to itself, create a duplicate partner and attach to it.
All other data is directly copied.
| void SAMRAI::hier::LayerEdgeSet< DIM >::findEdges | ( | ) |
Obviously, a partner must be attached. Neighbor information on both the object and its partner is modified. The effect is the same as if findEdges() were called for the partner.
This method simply calls findEdges(LayerEdgeSet &a, LayerEdgeSet &b) with the partner in the argument. See that method for communication implications.
If the partner is the same object (finding peer edges), edges between a node and itself will be ignored.
|
static |
| void SAMRAI::hier::LayerEdgeSet< DIM >::bridge | ( | const LayerEdgeSet< DIM > & | edge_to_head, |
| const LayerEdgeSet< DIM > & | edge_to_base | ||
| ) |
(bridge base) ------------bridge-------------> (bridge head)
<-------reverse bridge----------
^ ^
| |
| |
| |
+--edge to base-- (middle layer) --edge to head--+The bases of the two given layers are known as the middle layer. For each node in this layer, the two given layers give the sets of neighboring nodes at the head and base layers of the current object. These two sets are checked against each other for node intersections.
Conditions:
edge_to_head and edge_to_base must be incident from identical sets of nodes.edge_to_head and edge_to_base must have attached partners.To find peer edges, use identical layer-edges for the leg to head and leg to base.
A partner must be attached.
| void SAMRAI::hier::LayerEdgeSet< DIM >::replaceNodes | ( | const LayerEdgeSet< DIM > & | map | ) |
Given the LayerEdgeSet object map, which maps some nodes in the head of the current LayerEdgeSet to new nodes (also in the head), replace each given node in the head layer by its neighbors in the tail of map.
map
(old head) ---------> (new head)
^ ^
\ /
edge before mapping -> \ / <- edge after mapping
\ /
\ /
(base)
Representing the map by a LayerEdgeSet implicitly requires that any set of nodes replacing an old node must overlap the old ones they replace. A special algorithm taking advantage of this restriction is used to update this object. If you want to manipulate the edge data generally, DO NOT use this method.
map is a layer edge from nodes to be removed to nodes to be in its place. If any edges in map references nodes not locally owned, communication with the owner is triggered. In these cases, it is CRITICAL that the same mapping is introduced on the owner processes.
We could do the same with a bridge() operation centered at the tail of the map. but that requires that map maps the unchanged nodes in the tail to itself, and it also requires doing work to map unchanged nodes to themselves. This is a lot of extra overhead when map is very small. If map maps each unchanged node to itself, a.replaceNodes(map) is equivalent to a.bridge(map,a.getPartner()).
The partner's base will be replaced by the new head.
Conditions:
map must be based at the head of the current object.map and the current object must have attached partners.map must not map any node outside the range of the node's current box.| map | Mapping between old head and new head. A partner must be attached. |
| void SAMRAI::hier::LayerEdgeSet< DIM >::setParallelState | ( | const ParallelState | parallel_state | ) |
Before putting a LayerEdgeSet in a GLOBALIZED state, The LayerNodeSet given in initialize() must already be in GLOBALIZED mode. The layer-node set must always be in GLOBALIZED mode as long as the layer-edge set is.
In GLOBALIZED state, the entire layer is independently duplicated on every process. (For consistency, it is imperative that the layer is operated on uniformly across all processes.) All edges (not just local and semilocal) are found when operations to find them are executed.
This method is not necessarily trivial. More memory is required to store additional parts of the graph.
If a partner is attached, the parallel state of the partner is affected the same way.
Changing parallel state preserves existing neighbor information used by the new parallel state. Neighbor information not used by the new parallel state gets deallocated.
For efficiency reasons, this method NEVER implicitly discovers new neighbor information after going to a GLOBALIZED state. To get this data, call findEdges() explicitly.
For serial (one processor) runs, there is no difference between the parallel states (except for the names), and there is no real cost for switching parallel states.
| ParallelState SAMRAI::hier::LayerEdgeSet< DIM >::getParallelState | ( | ) | const |
| void SAMRAI::hier::LayerEdgeSet< DIM >::deallocateData | ( | ) |
If a partner exists, its internal data is deallocated also. This method does NOT detach the partner.
| void SAMRAI::hier::LayerEdgeSet< DIM >::setMaxGhostCellWidth | ( | const hier::IntVector< DIM > & | gcw | ) |
The default max ghost cell width is 1. The max ghost cell width affects the overlap comparison, so the old edge data is no longer valid. The old data is discarded. For efficiency reasons, new edge data is not automatically generated. To get this data, call findEdges() explicitly.
For attached LayerEdgeSet objects, the ratio of the ghost-cell-width of the two partners must be equal to the inverse ratio of their base layer refinement ratios. This ensures that the overlap check gives the same result regardless of the layer whose boxes are grown for the overlap check. If a partner is attached, the partner's ghost-cell-width is automatically changed to satisfy this requirement.
| const hier::IntVector<DIM>& SAMRAI::hier::LayerEdgeSet< DIM >::getMaxGhostCellWidth | ( | ) | const |
|
virtual |
| void SAMRAI::hier::LayerEdgeSet< DIM >::printEdgeStats | ( | std::ostream & | co | ) | const |
| void SAMRAI::hier::LayerEdgeSet< DIM >::checkNodeNabrCorrespondance | ( | ) | const |
| void SAMRAI::hier::LayerEdgeSet< DIM >::checkNodeConsistency | ( | ) | const |
Obviously, the object must have a partner. If the partner's base is not GLOBALIZED, a temporary copy is made and globalized for checking, triggering communication.
|
static |
| local_nodes | A node container. |
| cnect | Connectivity data for nodes. |
| head_layer | LayerNodeSet describing the head with respect to the given connectivity. This object must be in GLOBALIZED state. |
| void SAMRAI::hier::LayerEdgeSet< DIM >::checkConnectivity | ( | const LayerNodeSet< DIM > & | head | ) | const |
Assert that connectivity data is correct for the base and head (partner's base).
This is an expensive operation and should only be used for debugging. It creates a globalized version of the layer-node data (if this data is not already globalized), uses the data to compute the edges and compares the result to the current edges.
The object must be partnered and be in hybrid mode for checking to work.
Checking is done as follows:
Currently, the rebuilt edges are rebuilt using findEdges(). Thus, it may be pointless to use this method as a check for that method.
|
private |
|
private |
|
private |
For each node in the node_container, add a corresponding neighbor container that coresponds to index node.getLocalIndex() to cnect.
|
staticprivate |
|
private |
Given a set of edges from a "middle" layer to a "head" layer and a set of edges from the same "middle" layer to a "base" layer, discover edges between the head and base.
If partner is self (discovering peer edges), a node's intersection with itself is are disregarded.
Edges connecting nonlocal nodes may be discovered. Such information is appended to messages to be sent to the owners of those nodes. See bridge_shareEdges().
|
private |
Messages are created by bridge_discoverEdges().
|
private |
Neighbor information on both the object and its partner is modified. Edges found are added to appropriate neighbor lists. No edge is removed. If existing edges are invalid, remove them first.
This method is symmetric.
|
private |
Neighbor information on both the object and its partner is modified. Edges found are added to appropriate neighbor lists. No edge is removed. If existing edges are invalid, remove them first.
This method is not symmetric.
|
private |
Edges found are added to appropriate neighbor lists. No edge is removed. If existing edges are invalid, remove them first.
|
private |
|
private |
When determining intersection of two boxes, the box in the node layer with finer refinement ratio is grown by this amount. If both layers are at the same ratio, it does not matter which is grown.
|
private |
The neighbors in d_cnect correspond to this ratio. The partner (if any) must have a base layer with this ratio. (The base layer refinement ratio is in d_nodes.)
|
private |
This pointer references an object that may be shared among many LayerEdgeSet. Therefore, it will not be modified by this class.
|
private |
In serial mode, this is an array of Connectivity objects, one for each process. In non-serial mode, this is a single Connectivity object for the local process.
|
private |
Modified by setParallelState().
|
private |
|
private |
Set by attachPartner() and createPartner().
|
private |
|
private |
1.8.17