#include <source/hierarchy/dlbg/LayerEdgeSet.h>
Algorithms for computing edge data | |
void | findEdges () |
Discover and add edges between self and partner. | |
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. | |
void | replaceNodes (const LayerEdgeSet &map) |
Replace some nodes with others. | |
static void | findEdges (LayerEdgeSet &a, LayerEdgeSet &b) |
For outputs, error checking and debugging. | |
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. | |
void | checkNodeConsistency () const |
Check that the node referenced by connectivity match those in the partner's base LayerNodeSet. | |
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. | |
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. | |
typedef LayerNodeSet< DIM >::NodeContainer | NabrContainer |
Container for neighbors. | |
typedef std::map< LocalIndex, NabrContainer > | Connectivity |
Connectivity data between two node layers. | |
Public Member Functions | |
LayerEdgeSet () | |
Constructor. | |
virtual | ~LayerEdgeSet (void) |
Destructor. | |
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. | |
LayerEdgeSet & | createPartner (const LayerNodeSet< DIM > &partner_base, const Connectivity *partner_connectivity=NULL) |
LayerEdgeSet & | getPartner () |
Access the attached partner. | |
const LayerEdgeSet & | getPartner () const |
Access the attached partner. | |
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. | |
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. | |
void | setParallelState (const ParallelState parallel_state) |
Set the parallel distribution state. | |
ParallelState | getParallelState () const |
void | deallocateData () |
Deallocate internal data on nodes and neighbors. | |
void | setMaxGhostCellWidth (const hier::IntVector< DIM > &gcw) |
Set the max ghost cell width used to check for box intersections. | |
const hier::IntVector< DIM > & | getMaxGhostCellWidth () const |
Classes | |
struct | CommunicationStruct |
Data sorted by a hash. More... |
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 |
Container for nodes.
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 |
Container for neighbors.
typedef std::map<LocalIndex,NabrContainer> SAMRAI::hier::LayerEdgeSet< DIM >::Connectivity |
Connectivity data between two node layers.
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 | ( | ) |
Constructor.
The default constructor creates empty object in distributed state.
SAMRAI::hier::LayerEdgeSet< DIM >::~LayerEdgeSet | ( | void | ) | [virtual] |
Destructor.
Deallocate internal data.
const LayerEdgeSet< DIM >::NodeContainer & SAMRAI::hier::LayerEdgeSet< DIM >::getNodeContainer | ( | const int | rank = -1 |
) | const [inline] |
const LayerEdgeSet< DIM >::Connectivity & SAMRAI::hier::LayerEdgeSet< DIM >::getConnectivity | ( | const int | rank = -1 |
) | const |
const hier::IntVector< DIM > & SAMRAI::hier::LayerEdgeSet< DIM >::getBaseRefinementRatio | ( | ) | const [inline] |
const hier::IntVector< DIM > & SAMRAI::hier::LayerEdgeSet< DIM >::getHeadRefinementRatio | ( | ) | const [inline] |
void SAMRAI::hier::LayerEdgeSet< DIM >::attachPartner | ( | LayerEdgeSet< DIM > & | partner | ) |
Mutually attach to another layer-edge object to create a bi-directional set of edges.
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< DIM > & SAMRAI::hier::LayerEdgeSet< DIM >::createPartner | ( | const LayerNodeSet< DIM > & | partner_base, | |
const Connectivity * | partner_connectivity = NULL | |||
) |
LayerEdgeSet< DIM > & SAMRAI::hier::LayerEdgeSet< DIM >::getPartner | ( | ) |
Access the attached partner.
Error if no partner is attached.
const LayerEdgeSet< DIM > & SAMRAI::hier::LayerEdgeSet< DIM >::getPartner | ( | ) | const |
Access the attached partner.
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 | |||
) |
Set data defining the edge set.
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< DIM > & SAMRAI::hier::LayerEdgeSet< DIM >::operator= | ( | const LayerEdgeSet< DIM > & | r | ) |
Assignment operator duplicates edge data and reference to layer node set and sets up a similar partner relationship and parallel mode.
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 | ( | ) |
Discover and add edges between self and partner.
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.
void SAMRAI::hier::LayerEdgeSet< DIM >::findEdges | ( | LayerEdgeSet< DIM > & | a, | |
LayerEdgeSet< DIM > & | b | |||
) | [static] |
void SAMRAI::hier::LayerEdgeSet< DIM >::bridge | ( | const LayerEdgeSet< DIM > & | edge_to_head, | |
const LayerEdgeSet< DIM > & | edge_to_base | |||
) |
Create the layer edge data by bridging the heads of two layer edges whose base nodes are identical to each other.
(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 | ) |
Replace some nodes with others.
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 | ) |
Set the parallel distribution 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.
LayerEdgeSet< DIM >::ParallelState SAMRAI::hier::LayerEdgeSet< DIM >::getParallelState | ( | ) | const [inline] |
void SAMRAI::hier::LayerEdgeSet< DIM >::deallocateData | ( | ) |
Deallocate internal data on nodes and neighbors.
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 | ) |
Set the max ghost cell width used to check for box intersections.
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 [inline] |
void SAMRAI::hier::LayerEdgeSet< DIM >::printClassData | ( | std::ostream & | co, | |
int | debase_depth = 0 | |||
) | const [virtual] |
void SAMRAI::hier::LayerEdgeSet< DIM >::printEdgeStats | ( | std::ostream & | co | ) | const |
void SAMRAI::hier::LayerEdgeSet< DIM >::checkNodeNabrCorrespondance | ( | ) | const |
Check that the node and neighbor containers have a one-to-one correspondance.
void SAMRAI::hier::LayerEdgeSet< DIM >::checkNodeConsistency | ( | ) | const |
Check that the node referenced by connectivity match those in the partner's base LayerNodeSet.
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.
void SAMRAI::hier::LayerEdgeSet< DIM >::checkNodeConsistency | ( | const NodeContainer & | local_nodes, | |
const Connectivity & | cnect, | |||
const LayerNodeSet< DIM > & | head_layer | |||
) | [static] |
Check that nodes referenced by a given connectivity object match nodes in the given node containers.
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.