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.index_access().vector_attribute(second) =
274 acc.index_access().const_vector_attribute(first);
275 }
276 }
277 }
278}
279
280
281template <typename T>
284 const std::array<Tuple, 2>& input_ears,
285 const Tuple& final_simplex) const
286{
287 if (!bool(m_split_rib_op)) {
288 return;
289 }
290 assert(acc.primitive_type() == primitive_type());
291
292 auto old_values = m_handle.mesh().parent_scope([&]() {
293 return std::make_tuple(
294 acc.const_vector_attribute(input_ears[0]),
295 acc.const_vector_attribute(input_ears[1]));
296 });
297
298 VecType a, b;
299 std::tie(a, b) = old_values;
300 auto new_value = acc.vector_attribute(final_simplex);
301
302 const auto old_pred = this->evaluate_predicate(acc.primitive_type(), input_ears);
303
304 new_value = m_split_rib_op(a, b, old_pred);
305}
306
307template <typename T>
310 const Tuple& input_simplex,
311 const std::array<Tuple, 2>& split_simplices) const
312{
313 if (!bool(m_split_op)) {
314 return;
315 }
316 assert(acc.primitive_type() == primitive_type());
317 const VecType old_value =
318 m_handle.mesh().parent_scope([&]() { return acc.const_vector_attribute(input_simplex); });
319
320 std::bitset<2> pred = this->evaluate_predicate(acc.primitive_type(), split_simplices);
321
322 auto arr = m_split_op(old_value, pred);
323 for (size_t j = 0; j < 2; ++j) {
324 acc.vector_attribute(split_simplices[j]) = arr[j];
325 }
326}
327
328
329template <typename T>
331{
332 set_rib_strategy(standard_split_rib_strategy(t, m_handle.name()));
333 m_will_throw_rib = t == SplitRibBasicStrategy::Throw;
334}
335template <typename T>
337{
338 set_strategy(standard_split_strategy(t, m_handle.name()));
339 m_will_throw = t == SplitBasicStrategy::Throw;
340}
341
342template <typename T>
344{
345 m_split_rib_op = std::move(f);
346 m_will_throw_rib = false;
347}
348template <typename T>
350{
351 m_split_op = std::move(f);
352 m_will_throw = false;
353}
354
355template <typename T>
357{
358 return m_handle.mesh();
359}
360
361template <typename T>
363{
364 return m_handle.primitive_type();
365}
366
367template <typename T>
372
373template <typename T>
375 const attribute::MeshAttributeHandle& handle) const
376{
377 return handle == m_handle;
378}
379
380
385
386} // namespace wmtk::operations
bool is_free() const
Definition Mesh.hpp:973
attribute::Accessor< T, Mesh, D > create_accessor(const attribute::MeshAttributeHandle &handle)
PrimitiveType top_simplex_type() const
Definition Mesh.hpp:982
The Tuple is the basic navigation tool in our mesh data structure.
Definition Tuple.hpp:19
PrimitiveType primitive_type() const
A CachingAccessor that uses tuples for accessing attributes instead of indices.
Definition Accessor.hpp:28
MapResult< D > vector_attribute(const ArgType &t)
ConstMapResult< D > const_vector_attribute(const ArgType &t) const
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