15 return m_will_throw || m_will_throw_rib;
20 return fmt::format(
"SplitNewAttributeStrategy[{}]", m_handle.name());
30 default: [[fallthrough]];
33 return [](
const VT& a,
const std::bitset<2>&) -> std::array<VT, 2> {
34 return std::array<VT, 2>{{a, a}};
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)}};
42 return [mn](
const VT&,
const std::bitset<2>&) -> std::array<VT, 2> {
58 default: [[fallthrough]];
61 return [](
const VT& a,
const std::bitset<2>&) -> std::array<VT, 2> {
62 return std::array<VT, 2>{{a, a}};
65 return [](
const VT& a,
const std::bitset<2>&) -> std::array<VT, 2> {
70 return [mn](
const VT&,
const std::bitset<2>&) -> std::array<VT, 2> {
87 default: [[fallthrough]];
89 if constexpr (std::is_same_v<T, double> || std::is_same_v<T, Rational>) {
95 return [](
const VT& a,
const VT& b,
const std::bitset<2>& bs) -> VT {
98 if (!bs[1] && bs[0]) {
105 return [](
const VT& a,
const VT& b,
const std::bitset<2>& bs) -> VT {
106 if (!bs[0] && bs[1]) {
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);
124 std::string mn(name);
125 return [mn](
const VT&,
const VT&,
const std::bitset<2>&) -> VT {
137 const std::string_view& name)
142 default: [[fallthrough]];
146 return [](
const VT& a,
const VT& b,
const std::bitset<2>& bs) -> VT {
149 if (!bs[1] && bs[0]) {
156 return [](
const VT& a,
const VT& b,
const std::bitset<2>& bs) -> VT {
157 if (!bs[0] && bs[1]) {
164 return [](
const VT& a,
const VT& b,
const std::bitset<2>& bs) -> VT {
165 if (bs[0] == bs[1]) {
175 std::string mn(name);
176 return [mn](
const VT&,
const VT&,
const std::bitset<2>&) -> VT {
186 template <
typename T>
190 , m_split_rib_op(nullptr)
191 , m_split_op(nullptr)
193 assert(h.
holds<T>());
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));
216 template <
typename T>
222 if (!
bool(m_split_rib_op) && !
bool(m_split_op)) {
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());
233 for (
const auto& tuple_pair : tuple_pairs) {
235 const Tuple& output_tuple = std::get<1>(tuple_pair);
238 const auto& return_data_variant = data.get_variant(mesh(), input_simplex);
244 m_topo_info->input_ear_simplices(return_data_variant, input_simplex.
tuple(), pt);
246 m_topo_info->output_rib_simplices(return_data_variant, output_tuple, pt);
249 assert(old_simps.size() == new_simps.size());
251 for (
size_t s = 0; s < old_simps.size(); ++s) {
252 assign_split_ribs(acc, old_simps[s], new_simps[s]);
257 m_topo_info->input_split_simplices(return_data_variant, input_simplex.
tuple(), pt);
259 m_topo_info->output_split_simplices(return_data_variant, output_tuple, pt);
262 assert(old_simps.size() == new_simps.size());
264 for (
size_t s = 0; s < old_simps.size(); ++s) {
265 assign_split(acc, old_simps[s], new_simps[s]);
268 if (mesh().is_free()) {
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);
281 template <
typename T>
284 const std::array<Tuple, 2>& input_ears,
285 const Tuple& final_simplex)
const
287 if (!
bool(m_split_rib_op)) {
292 auto old_values = m_handle.mesh().parent_scope([&]() {
293 return std::make_tuple(
299 std::tie(a, b) = old_values;
302 const auto old_pred = this->evaluate_predicate(acc.
primitive_type(), input_ears);
304 new_value = m_split_rib_op(a, b, old_pred);
307 template <
typename T>
310 const Tuple& input_simplex,
311 const std::array<Tuple, 2>& split_simplices)
const
313 if (!
bool(m_split_op)) {
320 std::bitset<2> pred = this->evaluate_predicate(acc.
primitive_type(), split_simplices);
322 auto arr = m_split_op(old_value, pred);
323 for (
size_t j = 0; j < 2; ++j) {
329 template <
typename T>
332 set_rib_strategy(standard_split_rib_strategy(t, m_handle.name()));
335 template <
typename T>
338 set_strategy(standard_split_strategy(t, m_handle.name()));
342 template <
typename T>
345 m_split_rib_op = std::move(f);
346 m_will_throw_rib =
false;
348 template <
typename T>
351 m_split_op = std::move(f);
352 m_will_throw =
false;
355 template <
typename T>
358 return m_handle.mesh();
361 template <
typename T>
364 return m_handle.primitive_type();
367 template <
typename T>
373 template <
typename T>
377 return handle == m_handle;
attribute::Accessor< T, Mesh, D > create_accessor(const attribute::MeshAttributeHandle &handle)
PrimitiveType top_simplex_type() const
A CachingAccessor that uses tuples for accessing attributes instead of indices.
MapResult< D > vector_attribute(const ArgType &t)
PrimitiveType primitive_type() const
ConstMapResult< D > const_vector_attribute(const ArgType &t) const
PrimitiveType primitive_type() const
wmtk::multimesh::operations::SplitReturnData ReturnData
wmtk::multimesh::operations::OperationInOutData OperationInOutData
void update_handle_mesh(Mesh &m) override
wmtk::attribute::MeshAttributeHandle m_handle
bool invalid_state() const final override
void update(Mesh &m, const ReturnData &ret_data, const OperationInOutData &op_data) const final override
std::string name() const final override
std::function< VecType(const VecType &, const VecType &, const std::bitset< 2 > &)> SplitRibFuncType
void set_rib_strategy(SplitRibFuncType &&f)
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)
PrimitiveType primitive_type() const override
void set_strategy(SplitFuncType &&f)
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
const Tuple & tuple() const
void log_and_throw_error(const std::string &msg)