Wildmeshing Toolkit
Loading...
Searching...
No Matches
SplitNewAttributeStrategy.cpp
Go to the documentation of this file.
4
8
9
10namespace wmtk::operations {
11
12template <typename T>
14{
15 return m_will_throw || m_will_throw_rib;
16}
17template <typename T>
19{
20 return fmt::format("SplitNewAttributeStrategy[{}]", m_handle.name());
21}
22
23template <typename T>
25 T>::standard_split_strategy(SplitBasicStrategy optype, const std::string_view& name)
26{
28
29 switch (optype) {
30 default: [[fallthrough]];
31 case SplitBasicStrategy::Default: [[fallthrough]];
33 return [](const VT& a, const std::bitset<2>&) -> std::array<VT, 2> {
34 return std::array<VT, 2>{{a, a}};
35 };
37 return [](const VT& a, const std::bitset<2>&) -> std::array<VT, 2> {
38 return std::array<VT, 2>{{a / T(2), a / T(2)}};
39 };
41 std::string mn(name);
42 return [mn](const VT&, const std::bitset<2>&) -> std::array<VT, 2> {
43 log_and_throw_error("Split should have a new attribute for [{}]", mn);
44 };
45 }
46 case SplitBasicStrategy::None: return {};
47 }
48 return {};
49}
50
51template <>
53 Rational>::standard_split_strategy(SplitBasicStrategy optype, const std::string_view& name)
54{
56
57 switch (optype) {
58 default: [[fallthrough]];
59 case SplitBasicStrategy::Default: [[fallthrough]];
61 return [](const VT& a, const std::bitset<2>&) -> std::array<VT, 2> {
62 return std::array<VT, 2>{{a, a}};
63 };
65 return [](const VT& a, const std::bitset<2>&) -> std::array<VT, 2> {
66 return std::array<VT, 2>{{a / Rational(2, true), a / Rational(2, true)}};
67 };
69 std::string mn(name);
70 return [mn](const VT&, const std::bitset<2>&) -> std::array<VT, 2> {
71 log_and_throw_error("Split should have a new attribute for [{}]", mn);
72 };
73 }
74 case SplitBasicStrategy::None: return {};
75 }
76 return {};
77}
78
79
80template <typename T>
82 T>::standard_split_rib_strategy(SplitRibBasicStrategy optype, const std::string_view& name)
83{
85
86 switch (optype) {
87 default: [[fallthrough]];
89 if constexpr (std::is_same_v<T, double> || std::is_same_v<T, Rational>) {
91 } else {
92 return standard_split_rib_strategy(SplitRibBasicStrategy::CopyTuple);
93 }
95 return [](const VT& a, const VT& b, const std::bitset<2>& bs) -> VT {
96 // if both are boundary then return a (failed link anyway but oh well)
97 // if a is boundary but b is interior get b though
98 if (!bs[1] && bs[0]) {
99 return b;
100 } else {
101 return a;
102 }
103 };
105 return [](const VT& a, const VT& b, const std::bitset<2>& bs) -> VT {
106 if (!bs[0] && bs[1]) {
107 return a;
108 } else {
109 return b;
110 }
111 };
113 return [](const VT& a, const VT& b, const std::bitset<2>& bs) -> VT {
114 if (bs[0] == bs[1]) {
115 return (a + b) / T(2);
116 } else if (bs[0]) {
117 return a;
118
119 } else {
120 return b;
121 }
122 };
124 std::string mn(name);
125 return [mn](const VT&, const VT&, const std::bitset<2>&) -> VT {
126 log_and_throw_error("Split should have a new attribute [{}]", mn);
127 };
128 }
129 case SplitRibBasicStrategy::None: return {};
130 }
131 return {};
132}
133template <>
137 const std::string_view& name)
138{
140
141 switch (optype) {
142 default: [[fallthrough]];
144 return standard_split_rib_strategy(SplitRibBasicStrategy::Mean);
146 return [](const VT& a, const VT& b, const std::bitset<2>& bs) -> VT {
147 // if both are boundary then return a (failed link anyway but oh well)
148 // if a is boundary but b is interior get b though
149 if (!bs[1] && bs[0]) {
150 return b;
151 } else {
152 return a;
153 }
154 };
156 return [](const VT& a, const VT& b, const std::bitset<2>& bs) -> VT {
157 if (!bs[0] && bs[1]) {
158 return a;
159 } else {
160 return b;
161 }
162 };
164 return [](const VT& a, const VT& b, const std::bitset<2>& bs) -> VT {
165 if (bs[0] == bs[1]) {
166 return (a + b) / Rational(2, true);
167 } else if (bs[0]) {
168 return a;
169
170 } else {
171 return b;
172 }
173 };
175 std::string mn(name);
176 return [mn](const VT&, const VT&, const std::bitset<2>&) -> VT {
177 log_and_throw_error("Split should have a new attribute [{}]", mn);
178 };
179 }
180 case SplitRibBasicStrategy::None: return {};
181 }
182 return {};
183}
184
185
186template <typename T>
189 : m_handle(h)
190 , m_split_rib_op(nullptr)
191 , m_split_op(nullptr)
192{
193 assert(h.holds<T>());
196
197 auto& mesh = m_handle.mesh();
198 assert(
200 PrimitiveType::Vertex); // attribute new is not valid on free meshes
201
204 std::make_unique<edge_mesh::SplitNewAttributeTopoInfo>(static_cast<EdgeMesh&>(mesh));
207 std::make_unique<tri_mesh::SplitNewAttributeTopoInfo>(static_cast<TriMesh&>(mesh));
210 std::make_unique<tet_mesh::SplitNewAttributeTopoInfo>(static_cast<TetMesh&>(mesh));
211 } else {
212 log_and_throw_error("Invalid mesh");
213 }
214}
215
216template <typename T>
218 Mesh& m,
219 const ReturnData& data,
220 const OperationInOutData& op_datas) const
221{
222 if (!bool(m_split_rib_op) && !bool(m_split_op)) {
223 return;
224 }
225
226 if (op_datas.find(&mesh()) == op_datas.end()) return;
227 assert(&m == &mesh());
228 const std::vector<std::tuple<simplex::NavigatableSimplex, Tuple>>& tuple_pairs =
229 op_datas.at(&mesh());
230
231 const PrimitiveType pt = primitive_type();
232 auto acc = m.create_accessor(m_handle.as<T>());
233 for (const auto& tuple_pair : tuple_pairs) {
234 const simplex::NavigatableSimplex& input_simplex = std::get<0>(tuple_pair);
235 const Tuple& output_tuple = std::get<1>(tuple_pair);
236
237
238 const auto& return_data_variant = data.get_variant(mesh(), input_simplex);
239
240 // for (const PrimitiveType pt : wmtk::utils::primitive_below(mesh().top_simplex_type()))
241 {
242 // copy attributes opposing ears
243 auto old_simps =
244 m_topo_info->input_ear_simplices(return_data_variant, input_simplex.tuple(), pt);
245 auto new_simps =
246 m_topo_info->output_rib_simplices(return_data_variant, output_tuple, pt);
247
248
249 assert(old_simps.size() == new_simps.size());
250
251 for (size_t s = 0; s < old_simps.size(); ++s) {
252 assign_split_ribs(acc, old_simps[s], new_simps[s]);
253 }
254 }
255 {
256 auto old_simps =
257 m_topo_info->input_split_simplices(return_data_variant, input_simplex.tuple(), pt);
258 auto new_simps =
259 m_topo_info->output_split_simplices(return_data_variant, output_tuple, pt);
260
261
262 assert(old_simps.size() == new_simps.size());
263
264 for (size_t s = 0; s < old_simps.size(); ++s) {
265 assign_split(acc, old_simps[s], new_simps[s]);
266 }
267 }
268 if (mesh().is_free()) {
269 assert(m_handle.primitive_type() == PrimitiveType::Vertex);
270
271 auto pairs = m_topo_info->output_duplicated_free_simplices(return_data_variant, pt);
272 for (const auto& [first, second] : pairs) {
273 acc.vector_attribute(second) = acc.const_vector_attribute(first);
274 }
275 }
276 }
277}
278
279
280template <typename T>
283 const std::array<Tuple, 2>& input_ears,
284 const Tuple& final_simplex) const
285{
286 if (!bool(m_split_rib_op)) {
287 return;
288 }
289 assert(acc.primitive_type() == primitive_type());
290
291 auto old_values = m_handle.mesh().parent_scope([&]() {
292 return std::make_tuple(
293 acc.const_vector_attribute(input_ears[0]),
294 acc.const_vector_attribute(input_ears[1]));
295 });
296
297 VecType a, b;
298 std::tie(a, b) = old_values;
299 auto new_value = acc.vector_attribute(final_simplex);
300
301 const auto old_pred = this->evaluate_predicate(acc.primitive_type(), input_ears);
302
303 new_value = m_split_rib_op(a, b, old_pred);
304}
305
306template <typename T>
309 const Tuple& input_simplex,
310 const std::array<Tuple, 2>& split_simplices) const
311{
312 if (!bool(m_split_op)) {
313 return;
314 }
315 assert(acc.primitive_type() == primitive_type());
316 const VecType old_value =
317 m_handle.mesh().parent_scope([&]() { return acc.const_vector_attribute(input_simplex); });
318
319 std::bitset<2> pred = this->evaluate_predicate(acc.primitive_type(), split_simplices);
320
321 auto arr = m_split_op(old_value, pred);
322 for (size_t j = 0; j < 2; ++j) {
323 acc.vector_attribute(split_simplices[j]) = arr[j];
324 }
325}
326
327
328template <typename T>
330{
331 set_rib_strategy(standard_split_rib_strategy(t, m_handle.name()));
332 m_will_throw_rib = t == SplitRibBasicStrategy::Throw;
333}
334template <typename T>
336{
337 set_strategy(standard_split_strategy(t, m_handle.name()));
338 m_will_throw = t == SplitBasicStrategy::Throw;
339}
340
341template <typename T>
343{
344 m_split_rib_op = std::move(f);
345 m_will_throw_rib = false;
346}
347template <typename T>
349{
350 m_split_op = std::move(f);
351 m_will_throw = false;
352}
353
354template <typename T>
356{
357 return m_handle.mesh();
358}
359
360template <typename T>
362{
363 return m_handle.primitive_type();
364}
365
366template <typename T>
371
372template <typename T>
374 const attribute::MeshAttributeHandle& handle) const
375{
376 return handle == m_handle;
377}
378
379
384
385} // namespace wmtk::operations
bool is_free() const
Definition Mesh.hpp:971
PrimitiveType top_simplex_type() const
Definition Mesh.hpp:980
attribute::Accessor< T, Mesh, attribute::CachingAttribute< T >, D > create_accessor(const attribute::MeshAttributeHandle &handle)
The Tuple is the basic navigation tool in our mesh data structure.
Definition Tuple.hpp:19
An Accessor that uses tuples for accessing attributes instead of indices.
Definition Accessor.hpp:44
MapResult< std::max(D, Dim)> vector_attribute(const ArgType &t)
Access function for a vector attribute.
ConstMapResult< std::max(D, Dim)> const_vector_attribute(const ArgType &t) const
Constant access function for a vector attribute.
PrimitiveType primitive_type() const
Definition Accessor.hxx:181
BaseSplitNewAttributeStrategy::OperationInOutData OperationInOutData
BaseSplitNewAttributeStrategy::ReturnData ReturnData
void update(Mesh &m, const ReturnData &ret_data, const OperationInOutData &op_data) const final override
std::function< VecType(const VecType &, const VecType &, const std::bitset< 2 > &)> SplitRibFuncType
std::unique_ptr< SplitNewAttributeTopoInfo > m_topo_info
void assign_split_ribs(wmtk::attribute::Accessor< T > &accessor, const std::array< Tuple, 2 > &input_ears, const Tuple &final_simplex) const
SplitNewAttributeStrategy(const wmtk::attribute::MeshAttributeHandle &h)
void assign_split(wmtk::attribute::Accessor< T > &accessor, const Tuple &input_simplex, const std::array< Tuple, 2 > &split_simplices) const
bool matches_attribute(const attribute::MeshAttributeHandle &) const override
static SplitRibFuncType standard_split_rib_strategy(SplitRibBasicStrategy optype, const std::string_view &={})
std::function< std::array< VecType, 2 >(const VecType &, const std::bitset< 2 > &)> SplitFuncType
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:101