Wildmeshing Toolkit
Loading...
Searching...
No Matches
MultiMeshVisitor.hpp
Go to the documentation of this file.
1#pragma once
2#include <type_traits>
3#include <variant> //to get monostage
4#include <wmtk/Mesh.hpp>
5#include <wmtk/Primitive.hpp>
14#if !defined(NDEBUG)
15#include <cassert>
16#endif
17
18// TODO: extend this visitor to support const and non-const references
19#define WMTK_MESH_VISITOR_ONLY_SUPPORTS_NONCONST_REFERENCE
20
21namespace wmtk::multimesh {
22
23// if NodeFunctor returns a value then
24template <typename MMVisitor>
25class MultiMeshVisitorExecutor;
26
27template <typename NodeFunctor_>
29{
30public:
32 using NodeFunctor = NodeFunctor_;
33
34 using ReturnDataType = wmtk::utils::metaprogramming::
35 ReferenceWrappedFunctorReturnCache<NodeFunctor, MeshVariantTraits>;
37
38 using TypeHelper = wmtk::utils::metaprogramming::detail::
39 ReferenceWrappedFunctorReturnType<NodeFunctor, MeshVariantTraits::AllReferenceTuple>;
40
41
42 /* @brief constructor that takes in the node and edge functors
43 *
44 * @param f The functor that will be run on each mesh in the tree
45 * */
49
50
51 template <typename MMVisitor_>
54
55 /* @brief executes the node functor (and potentially edge functor) from the subtree of the input
56 * node
57 * @param mesh the mesh in the tree that the operation needs to run from
58 * @param simplex the simplex on the input mesh that we want to run the operation from
59 * @return a ReferenceWrappedFunctorReturnCache that lets one request (mesh,simplex) ->
60 * NodeFunctor Return type
61 * */
62 template <typename MeshType>
63 void execute_mesh(MeshType&& mesh)
64 {
65 static_assert(
66 !std::is_same_v<std::decay_t<MeshType>, Mesh>,
67 "Don't pass in a mesh, use variant/visitor to get its derived type");
68 Executor exec(*this);
69 exec.execute(std::forward<MeshType>(mesh));
70 }
71
72 /* @brief executes the node functor (and potentially edge functor) from the entire graph
73 * @param mesh some mesh in the tree that the operation needs to run from
74 * @param simplex the simplex on the input mesh that we want to run the operation from
75 * @return a ReferenceWrappedFunctorReturnCache that lets one request (mesh,simplex) ->
76 * NodeFunctor Return type
77 * */
78 // even if you try to use an interior mesh node this always just uses the root
80 {
81 // if the user passed in a mesh class lets try re-invoking with a derived type
82 Mesh& root_base_mesh = mesh.get_multi_mesh_root();
83 auto mesh_root_variant = wmtk::utils::metaprogramming::as_mesh_variant(root_base_mesh);
84 Executor exec(*this);
85 std::visit([&](auto&& root) { execute_mesh(root.get()); }, mesh_root_variant);
86 }
87
88
89protected:
91};
92
93// if NodeFunctor returns a value then
94template <typename MMVisitor>
96{
97public:
99 using NodeFunctor = typename MMVisitor::NodeFunctor;
100 // template <bool IsConst, typename MeshType>
101
102 MultiMeshVisitorExecutor(const MMVisitor& v)
103 : visitor(v)
104 {}
105
106 const MMVisitor& visitor;
107
108
109 /* @brief runs the node functor on every node in the subgraph and then runs hte edge functor if
110 * it exists
111 * @param mesh the mesh whose subgraph will be run
112 * @param simplex the simplex whose subgraph will be run
113 * */
114 template <typename MeshType>
115 void execute(MeshType&& mesh)
116 {
117 static_assert(std::is_base_of_v<Mesh, std::decay_t<MeshType>>);
118 run(std::forward<MeshType>(mesh));
119 }
120
121
122private:
123 /* @brief runs the node functor on every node in the subgraph
124 * @param mesh the mesh whose subgraph will be run
125 * @param simplex the simplex whose subgraph will be run
126 * */
127 template <typename MeshType_>
128 void run(MeshType_&& current_mesh)
129 {
130 using MeshType = std::decay_t<MeshType_>;
131
132
133 // short circuit operations that happen below the desired dimension
134 constexpr static int64_t MeshDim = wmtk::utils::metaprogramming::cell_dimension_v<MeshType>;
135
136
137 // pre-compute all of the child tuples in case the node functor changes the mesh that
138 // breaks the traversal down
139 auto& child_datas = current_mesh.m_multi_mesh_manager.children();
140
141 // go over each child mesh / child simplices and run the node functor on them
142 // then recurses this function onto the children
143 for (size_t child_index = 0; child_index < child_datas.size(); ++child_index) {
144 auto&& child_data = child_datas[child_index];
145 Mesh& child_mesh_base = *child_data.mesh;
146
147
148 auto child_mesh_variant =
150 std::visit(
151 [&](auto&& child_mesh_) noexcept {
152 auto&& child_mesh = child_mesh_.get();
153 using ChildType = std::decay_t<decltype(child_mesh)>;
154
155 constexpr static int64_t ChildDim =
156 wmtk::utils::metaprogramming::cell_dimension_v<ChildType>;
157
158 // std::visit compiles all combinations of meshes, and
159 // the behavior is undefined if MeshDim < ChildDim.
160 //
161 // we assert this to make sure the code is correct at
162 // runtime, we if constexpr after to make sure the
163 // compiler doesn't try to compile code in these cases
164 assert(MeshDim >= ChildDim);
165
166 if constexpr (MeshDim >= ChildDim) {
167 run(child_mesh);
168 }
169 },
170 child_mesh_variant);
171 }
172
173 visitor.m_node_functor(current_mesh);
174 }
175};
176
177
178template <typename NodeFunctor>
180
181
182} // namespace wmtk::multimesh
Mesh & get_multi_mesh_root()
returns a reference to the root of a multimesh tree
typename MMVisitor::NodeFunctor NodeFunctor
wmtk::utils::metaprogramming::ReferenceWrappedFunctorReturnCache< NodeFunctor, MeshVariantTraits > ReturnDataType
DerivedReferenceWrapperVariantTraits< Mesh, PointMesh, EdgeMesh, TriMesh, TetMesh > MeshVariantTraits
MeshVariantType as_mesh_variant(Mesh &mesh)