Peano
|
Translate grid traversal automaton's transitions into user events. More...
#include <GridTraversalEventGenerator.h>
Public Member Functions | |
GridTraversalEventGenerator (int id) | |
bool | isVertexAdjacentToLocalSpacetree (GridVertex vertex, const SplitSpecification &splitTriggered, const std::set< int > &splitting, const std::set< int > &joinTriggered, const std::set< int > &joining, bool splittingIsConsideredLocal, bool joiningIsConsideredLocal) const |
Study the adjacency flags and do ignore hanging nodes. | |
bool | isSpacetreeNodeLocal (GridVertex vertices[TwoPowerD], const SplitSpecification &splitTriggered, const std::set< int > &splitting, const std::set< int > &joinTriggered, const std::set< int > &joining, bool splittingIsConsideredLocal, bool joiningIsConsideredLocal) const |
A spacetree node as 2^d adjacent vertices. | |
GridTraversalEvent | createEnterCellTraversalEvent (GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD], const AutomatonState &state, const SplitSpecification &splitTriggered, const std::set< int > &splitting, const std::set< int > &joinTriggered, const std::set< int > &joining, const std::set< int > &hasSplit, const tarch::la::Vector< Dimensions, int > &relativePositionToFather, bool spacetreeStateIsRunning) const |
Create description of an enter cell traversal. | |
GridTraversalEvent | createLeaveCellTraversalEvent (GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD], const AutomatonState &state, const SplitSpecification &splitTriggered, const std::set< int > &splitting, const std::set< int > &joinTriggered, const std::set< int > &joining, const std::set< int > &hasSplit, const tarch::la::Vector< Dimensions, int > &relativePositionToFather, bool spacetreeStateIsRunning) const |
Create description of a leave cell traversal. | |
GridTraversalEvent | createPrunedEnterCellTraversalEvent (SpacetreeState spacetreeState, const GridTraversalEvent &event) const |
When we fork or join, the worker's locality analysis identifies local vertices and faces. | |
GridTraversalEvent | createPrunedLeaveCellTraversalEvent (SpacetreeState spacetreeState, const GridTraversalEvent &event) const |
int | getTreeOwningSpacetreeNode (GridVertex vertices[TwoPowerD], const SplitSpecification &splitTriggered, const std::set< int > &splitting, const std::set< int > &joinTriggered, const std::set< int > &joining) const |
We run over the \( 2^d \) adjacent vertices of the cell and look at each vertex's adjacency list. | |
tarch::la::Vector< TwoPowerD, int > | getAdjacentRanksOfFace (GridVertex vertex[TwoPowerD], int faceNumber, bool useBackedUpAdjacencyInformation) const |
Static Public Member Functions | |
static CellType | getCellType (GridVertex coarseGridVertices[TwoPowerD], tarch::la::Vector< Dimensions, int > positionOfCell) |
You pass in the vertices and it gives you back the cell type. | |
static VertexType | getVertexType (GridVertex coarseGridVertices[TwoPowerD], tarch::la::Vector< Dimensions, int > position, int dimension=Dimensions-1) |
Simple recursive type analysis. | |
Private Member Functions | |
GridTraversalEvent | createGenericCellTraversalEvent (GridVertex coarseGridVertices[TwoPowerD], GridVertex fineGridVertices[TwoPowerD], const AutomatonState &state, const SplitSpecification &splitTriggered, const std::set< int > &splitting, const std::set< int > &joinTriggered, const std::set< int > &joining, const tarch::la::Vector< Dimensions, int > &relativePositionToFather, bool spacetreeStateIsRunning) const |
std::bitset< TwoPowerD > | areVerticesAdjacentToParallelDomainBoundary (GridVertex vertices[TwoPowerD], const SplitSpecification &splitTriggered, const std::set< int > &splitting, const std::set< int > &joinTriggered, const std::set< int > &joining, bool calledByLeaveCell) const |
A vertex is inside the domain, if all of its ids equal _id. | |
std::bitset< TwoTimesD > | areFacesAdjacentToParallelDomainBoundary (GridVertex vertices[TwoPowerD], const SplitSpecification &splitTriggered, const std::set< int > &splitting, const std::set< int > &joinTriggered, const std::set< int > &joining, bool calledByLeaveCell) const |
std::bitset< TwoPowerD > | areVerticesLocal (GridVertex vertices[TwoPowerD], const SplitSpecification &splitTriggered, const std::set< int > &splitting, const std::set< int > &joinTriggered, const std::set< int > &joining) const |
Vertices are local. | |
std::bitset< TwoTimesD > | areFacesLocal (GridVertex vertices[TwoPowerD], const SplitSpecification &splitTriggered, const std::set< int > &splitting, const std::set< int > &joinTriggered, const std::set< int > &joining) const |
Identifies for the \( 2 \cdot d \) faces whether they are local or not. | |
Static Private Member Functions | |
static FaceType | getFaceType (GridVertex coarseGridVertices[TwoPowerD], tarch::la::Vector< Dimensions, int > positionOfCell, int faceNumber) |
Identify type of vertex. | |
Private Attributes | |
const int | _id |
Number of underlying tree. | |
Static Private Attributes | |
static tarch::logging::Log | _log |
Friends | |
class | peano4::grid::tests::GridTraversalEventGeneratorTest |
Translate grid traversal automaton's transitions into user events.
The majority of these routines is all about identifying ownership. So we might also call the class something around ownership analysis.
The generated events trigger the following things per grid sweep on the user side:
Definition at line 77 of file GridTraversalEventGenerator.h.
peano4::grid::GridTraversalEventGenerator::GridTraversalEventGenerator | ( | int | id | ) |
Definition at line 11 of file GridTraversalEventGenerator.cpp.
|
private |
Definition at line 166 of file GridTraversalEventGenerator.cpp.
References peano4::grid::Spacetree::RankOfPeriodicBoundaryCondition, TwoPowerD, and TwoTimesD.
|
private |
Identifies for the \( 2 \cdot d \) faces whether they are local or not.
I assume that all adjacency information/locality information on vertices is correctly set, i.e. is interpolated from the next coarser level. So I have valid neighbours on the vertex per se. Actually, however, the neighbour might be wrong, as an adjacent cell might have been given away to another rank.
We however have to be aware that a hanging vertex entry might be wrong if the corresponding adjacency value is not the one pointing towards our cell and the vertex is also hanging. So these constellations have to be ignored.
Definition at line 29 of file GridTraversalEventGenerator.cpp.
References peano4::grid::GridVertex::HangingVertex, and TwoPowerD.
Referenced by peano4::grid::tests::GridTraversalEventGeneratorTest::testAreFacesLocal2().
|
private |
A vertex is inside the domain, if all of its ids equal _id.
We use the backup of the ids here, as we study the current (committed) state. The routine runs over all \( 2^d \) vertices and analyses their status w.r.t. inside.
Definition at line 142 of file GridTraversalEventGenerator.cpp.
References peano4::grid::Spacetree::RankOfPeriodicBoundaryCondition, and TwoPowerD.
|
private |
Vertices are local.
I consider splitting and joining vertices to be local, too. It is therefore consistent with areFacesLocal().
Definition at line 14 of file GridTraversalEventGenerator.cpp.
peano4::grid::GridTraversalEvent peano4::grid::GridTraversalEventGenerator::createEnterCellTraversalEvent | ( | GridVertex | coarseGridVertices[TwoPowerD], |
GridVertex | fineGridVertices[TwoPowerD], | ||
const AutomatonState & | state, | ||
const SplitSpecification & | splitTriggered, | ||
const std::set< int > & | splitting, | ||
const std::set< int > & | joinTriggered, | ||
const std::set< int > & | joining, | ||
const std::set< int > & | hasSplit, | ||
const tarch::la::Vector< Dimensions, int > & | relativePositionToFather, | ||
bool | spacetreeStateIsRunning ) const |
Create description of an enter cell traversal.
The routine sets entries in the load instruction manually from "take from the in stream" to NoData if the entry refers to a remote grid entity. That is, if a face for example is not local, then we should not move it over the streams. After the fork, we should throw it away.
Throughout a fork, grid elements remain local on the master. We still call all events there while we are splitting. After that, we have to get rid of the data. This gives us two opportunities: We can either throw away data after the splitting traversal or we can throw it away one iteration later. There is however not really a decision to be made: We send out data (stream) after we have piped data to the output stream. That is, we still have to write all user data to the output stream throughout the splitting traversal even if this data will become remote afterwards. It is the output stream from where the spacetree will pick data and stream it over. So we have to use the iteration after splitting to get rid of data. Getting rid means simply: load it but do not store it anymore. It helps us in this context that data streams are monotoneous. We throw away stuff but we never re-create stuff (cmp joining below which poses an exception).
So, when we decide whether to load data, we first of all check whether a grid entity is local. If so, we have to load it from the input stream. If it is not local, we have to check whether a rank that is contained within _hasSplit is contained. If this is the case, we still load the data despite the fact that we might not run any routine on them.
createEnterCellTraversalEvent | Piped through to createGenericCellTraversalEvent(). |
Definition at line 473 of file GridTraversalEventGenerator.cpp.
References assertion1, tarch::la::contains(), peano4::grid::TraversalObserver::CreateOrDestroyHangingGridEntity, peano4::grid::TraversalObserver::CreateOrDestroyPersistentGridEntity, peano4::grid::Delete, peano4::grid::GridVertex::Delete, peano4::grid::GridVertex::EraseTriggered, peano4::grid::GridVertex::Erasing, peano4::grid::PeanoCurve::getCellReadStackNumber(), peano4::grid::PeanoCurve::getFaceNumberAlongCurve(), peano4::grid::PeanoCurve::getFaceReadStackNumber(), peano4::grid::PeanoCurve::getFirstVertexIndex(), peano4::grid::PeanoCurve::getVertexReadStackNumber(), peano4::grid::Hanging, peano4::grid::GridVertex::HangingVertex, peano4::grid::PeanoCurve::isInOutStack(), logDebug, logTraceInWith7Arguments, logTraceOutWith3Arguments, peano4::grid::New, peano4::grid::GridVertex::New, peano4::grid::TraversalObserver::NoData, peano4::grid::Persistent, peano4::grid::GridVertex::Refined, peano4::grid::GridVertex::RefinementTriggered, peano4::grid::GridVertex::Refining, state, peano4::grid::AutomatonState::toString(), TwoPowerD, TwoTimesD, and peano4::grid::GridVertex::Unrefined.
|
private |
Don't use the result's toString() operation in the traceOut statement. The event is not yet totally populated (we don't know the data-specific properties and only befill the generic stuff). As a consequence any toString() will cause valgrind's memchecker to raise (falsely) an alarm.
spacetreeStateIsRunning | spacetreeState == SpacetreeState::Running |
Definition at line 210 of file GridTraversalEventGenerator.cpp.
References dfor2, peano4::utils::dLinearised(), enddforx, peano4::grid::AutomatonState::getH(), peano4::grid::AutomatonState::getLevel(), peano4::grid::AutomatonState::getX(), peano4::grid::GridVertex::HangingVertex, peano4::grid::haveVerticesBeenRefined(), peano4::grid::isSpacetreeNodeLocal(), logTraceInWith3Arguments, logTraceInWith7Arguments, logTraceOutWith2Arguments, peano4::grid::GridTraversalEvent::setX(), state, peano4::grid::AutomatonState::toString(), peano4::grid::GridTraversalEvent::toString(), TwoPowerD, and peano4::grid::willVerticesBeRefined().
peano4::grid::GridTraversalEvent peano4::grid::GridTraversalEventGenerator::createLeaveCellTraversalEvent | ( | GridVertex | coarseGridVertices[TwoPowerD], |
GridVertex | fineGridVertices[TwoPowerD], | ||
const AutomatonState & | state, | ||
const SplitSpecification & | splitTriggered, | ||
const std::set< int > & | splitting, | ||
const std::set< int > & | joinTriggered, | ||
const std::set< int > & | joining, | ||
const std::set< int > & | hasSplit, | ||
const tarch::la::Vector< Dimensions, int > & | relativePositionToFather, | ||
bool | spacetreeStateIsRunning ) const |
Create description of a leave cell traversal.
Definition at line 281 of file GridTraversalEventGenerator.cpp.
References assertion1, peano4::grid::TraversalObserver::CreateOrDestroyHangingGridEntity, peano4::grid::TraversalObserver::CreateOrDestroyPersistentGridEntity, peano4::grid::Delete, peano4::grid::GridVertex::Delete, peano4::grid::GridVertex::EraseTriggered, peano4::grid::GridVertex::Erasing, peano4::grid::PeanoCurve::getCellWriteStackNumber(), peano4::grid::PeanoCurve::getFaceNumberAlongCurve(), peano4::grid::PeanoCurve::getFaceWriteStackNumber(), peano4::grid::PeanoCurve::getFirstVertexIndex(), peano4::grid::PeanoCurve::getVertexWriteStackNumber(), peano4::grid::Hanging, peano4::grid::GridVertex::HangingVertex, peano4::grid::PeanoCurve::isInOutStack(), logDebug, logTraceInWith3Arguments, logTraceOutWith3Arguments, peano4::grid::New, peano4::grid::GridVertex::New, peano4::grid::TraversalObserver::NoData, peano4::grid::Persistent, peano4::grid::GridVertex::Refined, peano4::grid::GridVertex::RefinementTriggered, peano4::grid::GridVertex::Refining, state, peano4::grid::AutomatonState::toString(), TwoPowerD, TwoTimesD, and peano4::grid::GridVertex::Unrefined.
peano4::grid::GridTraversalEvent peano4::grid::GridTraversalEventGenerator::createPrunedEnterCellTraversalEvent | ( | SpacetreeState | spacetreeState, |
const GridTraversalEvent & | event ) const |
When we fork or join, the worker's locality analysis identifies local vertices and faces.
It also identifies local cells. That's all correct. However, despite the fact that they are local, we should not invoke any user event on them. We should move data over the stacks, and we should (maybe) exchange data, but we should never call user code within the observers, as the reponsibility of the user operations remains with the original owner prior to the fork or join. See links below.
Therefore, we need a pruned version of the event with all local flags unset. We still need the version of the event with set local flags, as they feed into the boundary data exchange. But for enterCell and leaveCell, we need copies without these flags. Pruned copies.
The actual data transfer, i.e. which data goes from one stack to which other one, has to remain in place however: The additional sweeps that we run on a new rank/core are there to get the spacetree data into the right order and to send out all boundary data. It is thus essential that the data transfers stay in. It is "just" the user routines (computations) that shall not be invoked and therefore we have to unset the local flags.
I originally thought about having the pruning mechanism as a part of createEnterCellTraversalEvent() or createLeaveCellTraversalEvent(). This does not work however, as the data exchange et al need the real inside/ outside flag whereas a pruned version of the event might disable all of these flags to effectively switch off the invocation of user events.
Definition at line 415 of file GridTraversalEventGenerator.cpp.
References peano4::grid::EmptyRun, peano4::grid::Joining, peano4::grid::NewFromSplit, peano4::grid::GridTraversalEvent::setIsCellLocal(), peano4::grid::GridTraversalEvent::setIsFaceLocal(), peano4::grid::GridTraversalEvent::setIsParentCellLocal(), and peano4::grid::GridTraversalEvent::setIsVertexLocal().
peano4::grid::GridTraversalEvent peano4::grid::GridTraversalEventGenerator::createPrunedLeaveCellTraversalEvent | ( | SpacetreeState | spacetreeState, |
const GridTraversalEvent & | event ) const |
Definition at line 444 of file GridTraversalEventGenerator.cpp.
References peano4::grid::EmptyRun, peano4::grid::Joining, peano4::grid::NewFromSplit, peano4::grid::GridTraversalEvent::setIsCellLocal(), peano4::grid::GridTraversalEvent::setIsFaceLocal(), peano4::grid::GridTraversalEvent::setIsParentCellLocal(), and peano4::grid::GridTraversalEvent::setIsVertexLocal().
tarch::la::Vector< TwoPowerD, int > peano4::grid::GridTraversalEventGenerator::getAdjacentRanksOfFace | ( | GridVertex | vertex[TwoPowerD], |
int | faceNumber, | ||
bool | useBackedUpAdjacencyInformation ) const |
useBackedUpAdjacencyInformation | If this one is true, I use the backup of the adjacency list and not the new data. In most cases, I could thus call it calledByReceivingProcess. |
Definition at line 852 of file GridTraversalEventGenerator.cpp.
References assertion3, peano4::grid::GridVertex::Delete, dfore, peano4::utils::dLinearised(), peano4::grid::GridVertex::HangingVertex, peano4::grid::InvalidRank(), peano4::grid::GridVertex::New, and TwoPowerD.
|
static |
You pass in the vertices and it gives you back the cell type.
This routine translates the 2^d vertices of a cell into a cell type.
Definition at line 689 of file GridTraversalEventGenerator.cpp.
References assertion, peano4::grid::Delete, peano4::grid::Hanging, logDebug, peano4::grid::New, peano4::grid::Persistent, and TwoPowerD.
|
staticprivate |
Identify type of vertex.
Find out what type a face has, i.e. is it a new one, one that is to be deleted, or is it a persistent one. The outcome will decide where to take a vertex from and where to store it. It also will determine which cascade of events we will invoke.
Different to getVertexType(), we can work with the the fine grid's vertices here already. The implementation might not be the most elegant one: We loop over all four or eight vertices, respectively, but we use the normal of the faceNumber to alter the vertex index such that we eventually study only half of the vertices; those adjacent to the face.
There are four potential outcomes: new, hanging, persistent, delete. They derive as follows:
So while I use the vertex states, I cannot directly use the vertices. They have already gone through the vertex lifecycle, i.e. new vertices might already have the new flag. Instead, I have to go through getVertexType(). This might be inefficient and leave room for improvements, but is does the job for the time being.
Definition at line 640 of file GridTraversalEventGenerator.cpp.
References peano4::grid::Delete, peano4::grid::Hanging, logTraceInWith1Argument, logTraceOutWith4Arguments, peano4::grid::New, peano4::grid::Persistent, peano4::grid::toString(), and TwoPowerD.
int peano4::grid::GridTraversalEventGenerator::getTreeOwningSpacetreeNode | ( | GridVertex | vertices[TwoPowerD], |
const SplitSpecification & | splitTriggered, | ||
const std::set< int > & | splitting, | ||
const std::set< int > & | joinTriggered, | ||
const std::set< int > & | joining ) const |
We run over the \( 2^d \) adjacent vertices of the cell and look at each vertex's adjacency list.
Usually they should all agree on the who's gonna own a cell. It is only hanging vertices which we should exclude from our check. These vertices might carry invalid adjacency lists.
Other vertices which might hold invalid data are remote vertices. If a cell adjacent to the local domain changes its owner, the adjacency lists of the shared vertices all are updated. But those vertices further away, inside the remote area, are not updated. So we have to ignore these guys.
The latter data inconsistency leads to the case that we might run through all \( 2^d \) vertices and not find a single vertex where we can be sure that it holds the right data. So we also run a second result datum (weakID). This one is always updated unless we encounter a hanging vertex or an invalid id. So we basically cover this second case which occurs at the vertical interface of two domains: The coarser level is local, the finer level is remote and thus would not yield any owner. However, as we do not rebalance (fork) along vertical cuts, we can trust in the weakId in this case.
Definition at line 808 of file GridTraversalEventGenerator.cpp.
References assertion1, assertion8, dfor2, enddforx, peano4::grid::GridVertex::HangingVertex, peano4::grid::InvalidRank(), peano4::grid::isSpacetreeNodeLocal(), peano4::grid::toString(), and TwoPowerD.
|
static |
Simple recursive type analysis.
We run over the parent vertices and merge along the faces (per dimension). The priority of flags should be taken from the code directly.
Definition at line 730 of file GridTraversalEventGenerator.cpp.
References assertion3, peano4::grid::Delete, peano4::grid::GridVertex::Delete, peano4::utils::dLinearised(), peano4::grid::GridVertex::EraseTriggered, peano4::grid::GridVertex::Erasing, peano4::grid::Hanging, peano4::grid::GridVertex::HangingVertex, logTraceInWith2Arguments, logTraceOutWith1Argument, peano4::grid::New, peano4::grid::GridVertex::New, peano4::grid::Persistent, peano4::grid::GridVertex::Refined, peano4::grid::GridVertex::RefinementTriggered, peano4::grid::GridVertex::Refining, peano4::grid::toString(), and peano4::grid::GridVertex::Unrefined.
bool peano4::grid::GridTraversalEventGenerator::isSpacetreeNodeLocal | ( | GridVertex | vertices[TwoPowerD], |
const SplitSpecification & | splitTriggered, | ||
const std::set< int > & | splitting, | ||
const std::set< int > & | joinTriggered, | ||
const std::set< int > & | joining, | ||
bool | splittingIsConsideredLocal, | ||
bool | joiningIsConsideredLocal ) const |
A spacetree node as 2^d adjacent vertices.
So there are 2^d integers stored within these vertices that overlap with the current node. They all have to be the same. If they identify the local _id, then the node is local. They are also local if the markers are set to RankOfCellWitchWillBeJoined. This magic constant identifies cells on a worker which might join into their master.
Throughout the splitting process, an id might be already set to a remote rank, though it still is technically and logically local. So this routine interprets locality pretty technical and even marks those cells as non-local (anymore) which still are for another grid sweep or two.
Definition at line 109 of file GridTraversalEventGenerator.cpp.
References dfor2, enddforx, peano4::grid::GridVertex::HangingVertex, and TwoPowerD.
bool peano4::grid::GridTraversalEventGenerator::isVertexAdjacentToLocalSpacetree | ( | GridVertex | vertex, |
const SplitSpecification & | splitTriggered, | ||
const std::set< int > & | splitting, | ||
const std::set< int > & | joinTriggered, | ||
const std::set< int > & | joining, | ||
bool | splittingIsConsideredLocal, | ||
bool | joiningIsConsideredLocal ) const |
Study the adjacency flags and do ignore hanging nodes.
A vertex is remote, if all its adjacent cells are handled by another rank. However, this rank may not have the attribute fork-triggered (because then it does not yet exist) or joining (because then it is already forwarding its work to its master), or forking. The latter case means that the rank is just about to forward all vertices to the new worker, i.e. it does not compute anything anymore on the local vertex, but it still has to do the send/receive stuff, i.e. it still has to handle the vertices.
We assume that the adjacency information of hanging vertices is properly set. So I have valid neighbours. Actually, the neighbour might be wrong, but if it is the local neighbour, then it is correct. Therefore, we can distinguish hanging remote and hanging local vertices.
The treatment of hanging nodes in the action sets digesting the events thus differs from how we handle hanging nodes within the core spacetree. For the lattern, hanging vertices are never local to the current spacetree.
Definition at line 76 of file GridTraversalEventGenerator.cpp.
References assertion, logTraceInWith3Arguments, logTraceOutWith1Argument, and TwoPowerD.
|
friend |
Definition at line 79 of file GridTraversalEventGenerator.h.
|
private |
Number of underlying tree.
Definition at line 86 of file GridTraversalEventGenerator.h.
|
staticprivate |
Definition at line 81 of file GridTraversalEventGenerator.h.