Proto  3.2
Proto_MBGraph.H
Go to the documentation of this file.
1 #pragma once
2 
3 #ifndef _PROTO_MB_GRAPH_
4 #define _PROTO_MB_GRAPH_
5 
6 namespace Proto
7 {
8  /// @brief Defines what type is used for indexing block entities
9  typedef int BlockIndex;
10 
11  /// @brief An internal structure defining an arc in the MBGraph
12  struct MBGraphArc
13  {
14  inline MBGraphArc(
15  BlockIndex srcBlock,
16  BlockIndex dstBlock,
19  {
20  this->srcBlock = srcBlock;
21  this->dstBlock = dstBlock;
22  this->srcToDst = srcToDst;
23  this->dstToSrc = dstToSrc;
24  }
25 
26  inline ~MBGraphArc(){}
27 
28  inline bool operator==(const MBGraphArc& rhs) const
29  {
30  return (srcBlock == rhs.srcBlock)
31  && (dstBlock == rhs.dstBlock)
32  && (srcToDst == rhs.srcToDst)
33  && (dstToSrc == rhs.dstToSrc)
34  && (R == rhs.R);
35  }
36 
37  std::string str() const
38  {
39  std::ostringstream oss;
40  oss << "MBGraphArc";
41  oss << " | srcBlock: " << srcBlock;
42  oss << " | dstBlock: " << dstBlock;
43  oss << " | srcToDst: " << srcToDst;
44  oss << " | dstToSrc: " << dstToSrc;
45  return oss.str();
46  }
47 
48  inline void print(std::ostream& stream = std::cout) const { stream << str() << std::endl; }
49 
50  BlockIndex srcBlock; ///< The block index at the arc's origin
51  BlockIndex dstBlock; ///< The block index at the arc's end
52  Point srcToDst; ///< Direction of dstBlock relative to srcBlock in src coords
53  Point dstToSrc; ///< Direction of srcBlock relative to dstBlock in dst coords
54  CoordPermutation R; ///< Coordinate transformation from src to dst coords
55  };
56 
57  /// @brief An internal structure defining a node in the MBGraph
58  struct MBGraphNode
59  {
60  inline MBGraphNode(BlockIndex index);
61 
62  /// @brief Adds an arc to this node, ingoring self and redundant arcs.
63  /// The new arc represents a connection to block along direction toDst
64  /// with a reverse arc direction fromDst (from dst to this). Note that
65  /// toDst is in the local coordinates and fromDst is in the dst coordinates
66  inline void addArc(BlockIndex block, Point toDst, Point fromDst);
67 
68  /// @brief Get the rotation object associated with the arc from
69  /// this along dir to block
70  inline CoordPermutation& rotation(Point dir, BlockIndex block);
71 
72  /// @brief Equality established by value
73  inline bool operator==(const MBGraphNode& rhs) const
74  {
75  return (index == rhs.index)
76  && (arcs == rhs.arcs);
77  }
78 
79  /// @brief Print the block associated with this node and any arcs extending from it
80  /// @param stream
81  inline void print(std::ostream& stream = std::cout) const;
82 
83  BlockIndex index; ///< The block associated with this node
84  mutable std::map<Point, std::vector<MBGraphArc>> arcs; /// Map from direction from this to all arcs in that direction
85  };
86 
87  class MBProblemDomain;
88 
89  /// @brief Graph of a mapped multiblock domain. Nodes represent blocks and arcs represent
90  /// boundaries between blocks. Does not contain any information about the size of blocks;
91  /// that information is provided by MBProblemDomain.
92  ///
93  /// MBGraph stores connections of all codimensionalities between connected blocks.
94  /// This means that if two blocks are connected
95  /// by a codimension 1 boundary (sharing faces in R3) then the MBGraph also stores the
96  /// codimension 2 boundaries associated with the faces' edges, codimension 3 boundaries associated
97  /// with the faces' corners, etc. up to codimension = DIM.
98  ///
99  /// MBGraph currently does not completely support configurations wherein two blocks form a topological
100  /// cycle. For example, two blocks cannot have multiple codimension-1 boundaries with eachother; there
101  /// must be at least one other block in the circuit for the structure to be valid.
102  ///
103  /// MBGraphs usually do not need to be constructed directly, but are created implicitly when a user
104  /// constructs an MBProblemDomain.
105  class MBGraph
106  {
107  friend class MBProblemDomain;
108  public:
109 
110  /// Constructor
111  /** Creates an empty graph with a specified number of nodes and no connections */
112  inline MBGraph(BlockIndex numBlocks);
113 
114  /// Define Boundary
115  /** Adds a codimension-1 boundary to the graph. This function creates both directional
116  * arcs that are implied by the boundary (i.e. there is no need to call this function
117  * twice for each pair of connected blocks), but doing so will not corrupt the graph
118  *
119  * Implicitly creates any codimension-2+ boundaries. This function will result
120  * in an error if a codimension-2+ boundary or invalid geometry is specified.
121  *
122  * Cannot be called after this->close() has been called
123  *
124  * \param srcBlock Block A
125  * \param dstBlock Block B
126  * \param dir Codimension-1 direction from A to B in the coords of block A
127  * \param rotation Coordinate permutation from A to B
128  */
129  inline void defineBoundary(
130  BlockIndex srcBlock,
131  BlockIndex dstBlock,
132  Point dir,
133  CoordPermutation& rotation);
134 
135  /// Define Boundary overload using dir + side syntax instead of Point
136  inline void defineBoundary(
137  BlockIndex srcBlock,
138  BlockIndex dstBlock,
139  unsigned int dir,
140  Side::LoHiSide side,
141  CoordPermutation& rotation);
142 
143  /** @brief executes post processing steps once all boundaries of this graph have been defined
144  * This function must be called before the graph can be used.
145  *
146  * Many functions of MBGraph will fail if the graph has not been closed.
147  *
148  * One of the purposes of this function is to implicitly compute higher codimensional boundaries
149  * between blocks and the coordinate permutations associated with those connections. This process
150  * is correct for codimension-2 boundaries, but may be incorrect for codimension-3 boundaries
151  * for graphs with a non-trivial 3 dimensional structure at the time of writing - 9/2/2025
152  */
153  inline void close();
154 
155  /// @brief Number of blocks in the graph
156  inline unsigned int numBlocks() const {return m_blocks.size(); }
157 
158  /// @brief Number of boundaries block has in direction dir
159  /// @param srcBlock a BlockIndex
160  /// @param dir a direction specified in the coordinates of srcBlock
161  inline unsigned int numBoundaries(BlockIndex srcBlock, Point& dir) const;
162 
163  /// @brief Retrieve a vector of arcs associated with boundaries from srcBlock
164  /// in the direction dir
165  /// @param srcBlock a BlockIndex
166  /// @param dir a direction specified in the coordinates of srcBlock
167  inline std::vector<MBGraphArc> boundaries(
168  BlockIndex srcBlock,
169  Point dir) const;
170 
171  /// @brief Returns the list of all directions along which srcBlock is connected to
172  /// dstBlock. If two blocks share a codimension-D boundary, this list will contain a single
173  /// direction of codimension-D and all of the higher codimensional connections associated with
174  /// the shared edges, corners, etc of the boundary between blocks.
175  ///
176  /// Intended for internal use only; don't use this unless you know what you are doing.
177  ///
178  /// @param srcBlock The source block of the implied boundary
179  /// @param dstBlock The destination block of the implied boundary
180  /// @return The directions associated with the implied boundary. Empty if no boundary exists.
181  inline std::vector<Point> fullConnectivity(
182  BlockIndex srcBlock,
183  BlockIndex dstBlock) const;
184 
185  /// @brief Returns the lowest codimension direction associated with the boundary between
186  /// two blocks. This direction is guaranteed to be unique since MBGraph does not support
187  /// two-block topological cycles. This is the direction associated with the "true" boundary
188  /// between blocks.
189  ///
190  /// @param srcBlock The source block of the implied boundary
191  /// @param dstBlock The destination block of the implied boundary
192  /// @return The direction (srcBlock coordinates) of the implied boundary. Returns Point::Zeros if no boundary exists.
193  /// FIXME: This should return std::optional<Point> with no value if the boundary doesn't exist
194  inline Point connectivity(
195  BlockIndex srcBlock,
196  BlockIndex dstBlock) const;
198  /** @brief Returns the direction from dstBlock to srcBlock given the direction from srcBlock to dstBlock.
199  * Fails by assertion if the arc implied by the inputs is not in the graph
200  * FIXME: This should return std::optional<Point> with no value if the arc doesn't exist
201  *
202  * @param srcBlock the source block of the implied boundary
203  * @param dstBlock the destination block of the implied boundary
204  * @param dir the direction associated with an arc from source to destination (srcBlock coordinates)
205  * @return the direction along the same arc as dir from destination to source (dstBlock coordinates)
206  */
207  inline Point reverseArc(
208  BlockIndex srcBlock,
209  BlockIndex dstBlock,
210  Point dir) const;
211 
212  /** @brief Given a direction in srcBlock's coordinates, mirror the direction across the boundary with
213  * dstBlock and return the result in dstBlock's coordinates. If R is the coordinate rotation from
214  * srcBlock to dstBlock and dir has normal and tangential components to the boundary n and t respectively,
215  * the output is R(t) - R(n).
216  *
217  * Fails by assertion if there is no boundary between srcBlock and dstBlock
218  * @param srcBlock the source block of the implied boundary
219  * @param dstBlock the destination block of the implied boundary
220  * @param dir a direction in srcBlock's coordinates
221  * @return a direction corresponding to dir being mirrored across the implied boundary
222  */
223  inline Point mirrorDirAcrossBoundary(
224  BlockIndex srcBlock,
225  BlockIndex dstBlock,
226  Point dir) const;
228  /** @brief Attempts to retrieve the coordinate permutation from srcBlock to dstBlock
229  * Fails by assertion if the input blocks don't share a boundary
230  *
231  * @param srcBlock the source block of the implied boundary
232  * @param dstBlock the destination block of the implied boundary
233  * @return the permutation from srcBlock's coordinates to dstBlock's coordinates
234  */
235  inline CoordPermutation rotation(
236  BlockIndex srcBlock,
237  BlockIndex dstBlock) const;
238 
239  /** @brief Get the block adjacent to srcBlock in the specified codimension-1 direction
240  * Since the direction is codimension-1, the block - should it exist - is guaranteed to be unique
241  * @param srcBlock the block whose adjacency is desired
242  * @param dir the coordinate axis along which to search for an adjacency
243  * @param side the side (high / low) to search for the adjacency on
244  */
245  inline BlockIndex adjacentBlock(
246  BlockIndex srcBlock,
247  unsigned int dir,
248  Side::LoHiSide side) const;
249 
250  /** @brief Get the block adjacent to srcBlock in the specified codimension-1 direction
251  * Fails if codim1Dir.codim() != 1
252  * @param srcBlock a valid block index
253  * @param codim1Dir a codimension-1 direction
254  */
255  inline BlockIndex adjacentBlock(
256  BlockIndex srcBlock,
257  Point codim1Dir) const;
258 
259  /** @brief Get a vector of all blocks adjacent to this block in direction dir
260  *
261  * @param srcBlock a valid block index
262  * @param dir a direction
263  */
264  inline std::set<BlockIndex> adjacentBlocks(
265  BlockIndex srcBlock,
266  Point dir) const;
268  /** @brief Equality operator. Equality is determined by value */
269  inline bool operator==(const MBGraph& rhs) const;
270 
271  /** @brief Determine if the block - direction pair represents the boundary of a block
272  * This function returns true if dir points to a "triple point" region even though the
273  * graph has no arcs from the node associated with srcBlock in the direction dir
274  *
275  * @param srcBlock a valid block index
276  * @param dir a direction
277  */
278  inline bool isBlockBoundary(BlockIndex srcBlock, Point dir) const;
279 
280 
281  /** @brief returns true if the specified block boundary corresponds to a "triple point".
282  * In this context, a "triple point" is a codimension-2 block boundary where exactly
283  * three blocks meet. This function is used to infer corrections that must be made
284  * when building interpolation operators in such regions.
285  *
286  * Example: A "Triple Point" Configuration in 2D
287  * \
288  * \ Block 2
289  * Block 0 >-------
290  * / Block 1
291  * /
292  */
293  inline bool isTriplePoint(
294  BlockIndex srcBlock,
295  Point dir) const;
296 
297  /** @brief return a list of codimension-1 direction pairs which represent "triple point circuits"
298  * two codimension-1 directions represent a circuit relative to srcBlock if srcBlock has a
299  * codimension-1 boundary in those directions with two other blocks which in turn have a codimenison-1
300  * boundary which lies in the same logical "plane" as the two directions defining the circuit.
301  *
302  * This function is not recommended for public use.
303  *
304  * If DIM==2, there will be at most one circuit for a given block. In higher dimensions, there will in
305  * general be many, and will result in the function being called recursively.
306  *
307  * At the time of writing, there are no dependencies in Proto which use this function, but it is likely
308  * that it will be useful for more complex graphs. - Chris Bozhart - 9/2/2025
309  *
310  * @param srcBlock the reference block from which the search for triple point circuits is executed
311  * @param dir the direction in which triple point circuits are searched
312  */
313  std::vector<std::pair<Point, Point>>
314  getTriplePointCircuits(
315  BlockIndex srcBlock,
316  Point dir) const;
318  /** @brief returns true if there are no blocks adjacent to srcBlock in the direction dir. This situation
319  * is assumed to correspond to a "domain boundary"
320  * @param srcBlock the reference block from which domain boundaries are searched for
321  * @param dir the direction which constitutes the query for a domain boundary
322  */
323  inline bool isDomainBoundary(
324  BlockIndex srcBlock,
325  Point dir) const;
326 
327  /// @brief prints all of the MBGraphNode objects in this graph (one for each block)
328  /** which in turn prints all of the arcs extending from each block
329  */
330  inline void print() const;
331 
332 
333 
334  private:
335 
336  /** @brief internal function called inside of "close" adjusts errors in the implicitly constructed
337  * coordinate permutations between blocks with high codimensional connectivity.
338  */
339  inline void fixRotations();
340 
341  /** @brief obtain a reference to the coordinate permuation object stored in the graph. Used
342  * by "close" to fix internal boundary rotations, and not intended for public use. If you think you
343  * need to use this externally, there is probably a bug in MBGraph::close that needs addressing instead
344  */
345  inline CoordPermutation& rotation(
346  BlockIndex srcBlock,
347  Point dir,
348  BlockIndex dstBlock) const;
349 
350  /** @brief obtain a reference to the coordinate permuation object stored in the graph. Used
351  * by "close" to fix internal boundary rotations, and not intended for public use. If you think you
352  * need to use this externally, there is probably a bug in MBGraph::close that needs addressing instead
353  */
354  inline CoordPermutation& rotation(
355  BlockIndex block,
356  Point dir) const;
357 
358  /** @brief for a given block - direction pair, return all of the codimension-2 boundaries
359  * that are projections of dir which also represent triple point boundaries.
360  *
361  * This function is highly experimental and not well tested.
362  * This function only has true utility for DIM >= 3. For an illustrative example of when
363  * This function has value, consider a graph of 4 blocks connected in such a way that
364  * the arcs for a tetrahedron. It is completely unused at the time of writing, but
365  * may come in handy in the future.
366  * - Chris Bozhart - 8/28/2025
367  */
368  inline std::vector<Point> codim2TriplePointBoundaries(
369  BlockIndex srcBlock,
370  Point dir) const;
371 
372 
373  bool m_closed; ///< Has "close" been called on this
374  std::vector<std::shared_ptr<MBGraphNode>> m_blocks; ///< The nodes of this graph
375  };
376 #include "implem/Proto_MBGraphImplem.H"
377 } // end namespace Proto
378 #endif // end include guard
std::map< Point, std::vector< MBGraphArc > > arcs
Definition: Proto_MBGraph.H:84
bool operator==(const MBGraphNode &rhs) const
Equality established by value.
Definition: Proto_MBGraph.H:73
LoHiSide
Side Enum.
Definition: Proto_Face.H:23
Graph of a mapped multiblock domain. Nodes represent blocks and arcs represent boundaries between blo...
Definition: Proto_MBGraph.H:105
int BlockIndex
Defines what type is used for indexing block entities.
Definition: Proto_MBGraph.H:9
void print(std::ostream &stream=std::cout) const
Definition: Proto_MBGraph.H:48
MBGraphArc(BlockIndex srcBlock, BlockIndex dstBlock, Point srcToDst, Point dstToSrc)
Definition: Proto_MBGraph.H:14
std::vector< std::shared_ptr< MBGraphNode > > m_blocks
The nodes of this graph.
Definition: Proto_MBGraph.H:374
BlockIndex index
The block associated with this node.
Definition: Proto_MBGraph.H:83
Defines discrete rotations in logically rectangular coordinate systems.
Definition: Proto_CoordPermutation.H:13
Point srcToDst
Direction of dstBlock relative to srcBlock in src coords.
Definition: Proto_MBGraph.H:52
BlockIndex dstBlock
The block index at the arc&#39;s end.
Definition: Proto_MBGraph.H:51
CoordPermutation R
Coordinate transformation from src to dst coords.
Definition: Proto_MBGraph.H:54
std::string str() const
Definition: Proto_MBGraph.H:37
Mapped Multi-Block Problem Domain.
Definition: Proto_MBProblemDomain.H:76
std::string str() const
BlockIndex srcBlock
The block index at the arc&#39;s origin.
Definition: Proto_MBGraph.H:50
unsigned int numBlocks() const
Number of blocks in the graph.
Definition: Proto_MBGraph.H:156
CoordPermutation & rotation(BlockIndex srcBlock, Point dir, BlockIndex dstBlock) const
obtain a reference to the coordinate permuation object stored in the graph. Used by "close" to fix in...
Definition: Proto_MBGraph.H:330
Definition: Proto_Array.H:17
uint64_t index
Definition: Proto_MBBoxPartition.H:15
An internal structure defining an arc in the MBGraph.
Definition: Proto_MBGraph.H:12
Integer Valued Vector.
Definition: Proto_Point.H:24
~MBGraphArc()
Definition: Proto_MBGraph.H:26
Point dstToSrc
Direction of srcBlock relative to dstBlock in dst coords.
Definition: Proto_MBGraph.H:53
std::map< Point, MBPatchBoundInfo > boundaries
Definition: Proto_MBBoxPartition.H:88
bool m_closed
Has "close" been called on this.
Definition: Proto_MBGraph.H:373
bool operator==(const MBGraphArc &rhs) const
Definition: Proto_MBGraph.H:28
Point dir
Definition: Proto_MBBoxPartition.H:16
An internal structure defining a node in the MBGraph.
Definition: Proto_MBGraph.H:58
void defineBoundary(BlockIndex srcBlock, BlockIndex dstBlock, Point dir, CoordPermutation &rotation)
Define Boundary.
Definition: Proto_MBGraph.H:127