40#include <kernel/geometry/index_set.hpp>
41#include <kernel/geometry/mesh_part.hpp>
42#include <kernel/geometry/target_set.hpp>
43#include <kernel/shape.hpp>
66 template<
typename Shape_,
typename T_>
67 class DimVector :
public DimVector<typename Shape::FaceTraits<Shape_, Shape_::dimension - 1>::ShapeType, T_>
80 std::vector<T_>&
get()
82 static_assert(dim_ <= Shape_::dimension);
94 const std::vector<T_>&
get()
const
96 static_assert(dim_ <= Shape_::dimension);
114 template<
typename T_>
122 std::vector<T_>&
get()
124 static_assert(dim_ == 0);
130 const std::vector<T_>&
get()
const
132 static_assert(dim_ == 0);
158 std::optional<Index>
left = std::nullopt;
161 std::optional<Index>
right = std::nullopt;
164 std::optional<Index>
index = std::nullopt;
186 template<
typename MeshType_>
257 template<
typename AttributeFn_>
261 const auto join_pred = [](
const JoinEntry& e) {
return e.left.has_value() && e.right.has_value(); };
264 const bool create_topology = left.has_topology() || right.has_topology();
265 return meshpart_op(left, right, attribute_merge, join_pred, create_topology);
304 template<
typename AttributeFn_>
308 const auto join_pred = [](
const JoinEntry& e) {
return e.left.has_value() || e.right.has_value(); };
310 const bool create_topology = left.has_topology() && right.has_topology();
311 return meshpart_op(left, right, attribute_merge, join_pred, create_topology);
360 !left.has_topology() && !right.has_topology(),
361 "Difference between meshparts with topology are not supported.");
364 const auto join_pred = [](
const JoinEntry& e) {
return e.left.has_value() && !e.right.has_value(); };
426 template<
typename AttributeFn_,
typename PredFn_>
430 const AttributeFn_& attribute_merge,
431 const PredFn_& join_pred,
432 const bool create_topology)
437 join_elements(join, left.get_target_set_holder(), right.get_target_set_holder());
444 std::array<Index, ShapeType::dimension + 1> size{};
445 for(
int i(0); i < ShapeType::dimension + 1; i++)
447 size[std::size_t(i)] = tsh.get_num_entities(i);
453 result.get_target_set_holder() = std::move(tsh);
459 const IndexSetHolderType* left_ish = left.has_topology() ? left.get_topology() : ∅
460 const IndexSetHolderType* right_ish = right.has_topology() ? right.get_topology() : ∅
463 *result.get_topology(),
466 left.get_target_set_holder(),
468 right.get_target_set_holder());
475 return std::move(result);
488 std::set<String> attributes;
490 for(
const auto& pair : right.get_mesh_attributes())
493 if(attribute !=
nullptr && pair.second->get_dimension() == attribute->get_dimension())
495 attributes.insert(pair.first);
516 template<
typename AttributeFn_>
518 const AttributeFn_& fn,
528 for(
const String& name : attributes)
533 const int dim = left_attribute->get_dimension();
535 auto new_attribute = std::make_unique<AttributeSetType>(result.
get_num_entities(0), dim);
537 const JoinVec& join_vec = join.template get<0>();
541 if(!t.index.has_value())
547 if(t.left.has_value() && t.right.has_value())
550 for(
int i(0); i < dim; i++)
554 new_attribute->operator()(t.index.value(), i) = fn(l, r);
557 else if(t.left.has_value())
560 for(
int i(0); i < dim; i++)
563 new_attribute->operator()(t.index.value(), i) = l;
566 else if(t.right.has_value())
569 for(
int i(0); i < dim; i++)
572 new_attribute->operator()(t.index.value(), i) = r;
577 XABORTM(
"Entity in meshpart operation result without source index");
599 template<
int dim_ = ShapeType::dimension>
608 if constexpr(dim_ == 0)
615 build_topology<dim_ - 1>(output_ish, join, left_ish, left_tsh, right_ish, right_tsh);
616 build_topology_inner<dim_, dim_ - 1>(output_ish, join, left_ish, left_tsh, right_ish, right_tsh);
636 template<
int dim_,
int codim_>
645 if constexpr(codim_ < 0)
653 build_topology_inner<dim_, codim_ - 1>(output_ish, join, left_ish, left_tsh, right_ish, right_tsh);
659 JoinVec& dim_entities = join.template get<dim_>();
660 JoinVec& codim_entities = join.template get<codim_>();
662 const IndexSetType& right_is = right_ish.template get_index_set<dim_, codim_>();
663 const IndexSetType& left_is = left_ish.template get_index_set<dim_, codim_>();
665 IndexSetType& out = output_ish.template get_index_set<dim_, codim_>();
679 codim_entities.begin(),
680 codim_entities.end(),
688 bool left_entities =
false;
694 if(!t.index.has_value())
700 if(!t.right.has_value())
706 left_entities =
true;
710 for(
int j(0); j < num_indices; j++)
718 const std::optional<Index> target(right_is[t.right.value()][j]);
719 std::optional<Index> codim_index =
search(
720 codim_entities.begin(),
721 codim_entities.end(),
723 [](
const JoinEntry& a,
const std::optional<Index>& i) { return a.right < i; });
724 XASSERT(codim_index.has_value());
726 const JoinEntry& codim_entry = codim_entities[codim_index.value()];
732 out(t.index.value(), j) = codim_entry.
index.value_or(~
Index(0));
747 codim_entities.begin(),
748 codim_entities.end(),
753 if(!t.index.has_value() || t.right.has_value() || !t.left.has_value())
761 for(
int j(0); j < num_indices; j++)
763 const std::optional<Index> target(left_is[t.left.value()][j]);
764 std::optional<Index> codim_index =
search(
765 codim_entities.begin(),
766 codim_entities.end(),
768 [](
const JoinEntry& a,
const std::optional<Index>& i) { return a.left < i; });
769 XASSERT(codim_index.has_value());
771 const JoinEntry& codim_entry = codim_entities[codim_index.value()];
772 out(t.index.value(), j) = codim_entry.
index.value_or(~
Index(0));
794 template<
int dim_ = ShapeType::dimension>
798 const std::function<
bool(
const JoinEntry&)>& pred,
802 if constexpr(dim_ < 0)
812 JoinVec& entities = join.template get<dim_>();
813 const TargetSet& right_ts = right_tsh.template get_target_set<dim_>();
814 const TargetSet& left_ts = left_tsh.template get_target_set<dim_>();
816 std::vector<Index> target_set_vec;
822 t.index = target_set_vec.size();
826 target_set_vec.push_back(left_ts[t.left.value()]);
831 target_set_vec.push_back(right_ts[t.right.value()]);
839 XABORTM(
"No source index for entity!");
846 for(
Index i(0); i < target_set_vec.size(); i++)
848 result[i] = target_set_vec[i];
852 output_tsh.template get_target_set<dim_>() = std::move(result);
871 template<
int dim_ = ShapeType::dimension>
874 if constexpr(dim_ < 0)
883 JoinVec& join_vec = join.template get<dim_>();
885 const TargetSet& left = left_tsh.template get_target_set<dim_>();
886 const TargetSet& right = right_tsh.template get_target_set<dim_>();
909 left_indices.begin(),
911 [&](
Index a,
Index b) { return left_lookup[a] < left_lookup[b]; });
912 std::sort(lbegin, lend);
918 for(
Index i(0); i < right.get_num_entities(); i++)
923 const std::optional<Index> sorted_left =
search(lbegin, lend, right[i]);
926 entry.
left = left_indices[sorted_left.value()];
929 join_vec.push_back(entry);
954 right_indices[i] = i;
958 right_indices.begin(),
960 [&](
Index a,
Index b) { return right_lookup[a] < right_lookup[b]; });
961 std::sort(rbegin, rend);
967 for(
Index i(0); i < left.get_num_entities(); i++)
969 const std::optional<Index> sorted_right =
search(rbegin, rend, left[i]);
970 if(!sorted_right.has_value())
974 join_vec.push_back(entry);
992 template<
typename Iter_,
typename T_>
993 static std::optional<Index>
search(Iter_ begin, Iter_ end,
const T_&
value)
995 Iter_ it = std::lower_bound(begin, end,
value);
996 if(it == end || *it !=
value)
1002 return std::distance(begin, it);
1020 template<
typename Iter_,
typename T_,
typename CompFn_>
1021 static std::optional<Index>
search(Iter_ begin, Iter_ end,
const T_&
value,
const CompFn_& fn)
1023 Iter_ it = std::lower_bound(begin, end,
value, fn);
1024 if(it == end || fn(*it,
value))
1026 return std::nullopt;
1030 return std::distance(begin, it);
#define XABORTM(msg)
Abortion macro definition with custom message.
#define XASSERT(expr)
Assertion macro definition.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Conformal Index-Set class template.
Utility class for storing one vector per dimension.
std::vector< T_ > & get()
accessor
std::vector< T_ > vec
Vector for current dimension.
const std::vector< T_ > & get() const
const accessor
Class template for partial meshes.
AttributeSet< AttributeDataType > AttributeSetType
Type for mesh attributes.
Index get_num_entities(int dim) const
Returns the number of entities.
MeshType::VertexSetType::CoordType AttributeDataType
Data type for attributes.
virtual bool add_attribute(std::unique_ptr< AttributeSetType > attribute, const String &identifier)
Copies one attribute to this MeshPart's AttributeHolder.
Boolean operations on mesh parts.
static MeshPartType meshpart_difference(const MeshPartType &left, const MeshPartType &right)
Compute the difference of two meshparts.
static MeshPartType meshpart_op(const MeshPartType &left, const MeshPartType &right, const AttributeFn_ &attribute_merge, const PredFn_ &join_pred, const bool create_topology)
Common logic for all meshpart operations.
std::vector< JoinEntry > JoinVec
Collection of JoinEntries.
static void copy_attributes(const AttributeFn_ &fn, const Join &join, MeshPartType &result, const MeshPartType &left, const MeshPartType &right)
Attribute copy logic.
static std::set< String > common_attributes(const MeshPartType &left, const MeshPartType &right)
Find common attributes of two meshparts.
TargetSetHolder< ShapeType > TargetSetHolderType
TargetSetHolder type.
static void join_elements(Join &join, const TargetSetHolderType &left_tsh, const TargetSetHolderType &right_tsh)
Construct a join of entities.
static std::optional< Index > search(Iter_ begin, Iter_ end, const T_ &value, const CompFn_ &fn)
Binary search.
typename MeshType::ShapeType ShapeType
Shape type.
static MeshPartType meshpart_symmetric_difference(const MeshPartType &left, const MeshPartType &right)
Compute the symmetric difference of two meshparts.
MeshType_ MeshType
Mesh type underlying all mesh parts.
static void build_topology(IndexSetHolderType &output_ish, Join &join, const IndexSetHolderType &left_ish, const TargetSetHolderType &left_tsh, const IndexSetHolderType &right_ish, const TargetSetHolderType &right_tsh)
Outer wrapper for topology construction.
static std::optional< Index > search(Iter_ begin, Iter_ end, const T_ &value)
Binary search.
typename MeshPartType::AttributeDataType AttributeDataType
Data types for meshpart attributes.
static MeshPartType meshpart_union(const MeshPartType &left, const MeshPartType &right, const AttributeFn_ &attribute_merge)
Compute the union of two meshparts.
static MeshPartType meshpart_intersection(const MeshPartType &left, const MeshPartType &right, const AttributeFn_ &attribute_merge)
Compute the intersection of two meshparts.
static void build_topology_inner(IndexSetHolderType &output_ish, Join &join, const IndexSetHolderType &left_ish, const TargetSetHolderType &left_tsh, const IndexSetHolderType &right_ish, const TargetSetHolderType &right_tsh)
Inner logc for topology construction.
static void build_target_set_holder(TargetSetHolderType &output_tsh, Join &join, const std::function< bool(const JoinEntry &)> &pred, const TargetSetHolderType &left_tsh, const TargetSetHolderType &right_tsh)
Construct target sets out of the join.
IndexSetHolder< ShapeType > IndexSetHolderType
IndexSetHolder type.
typename MeshPartType::AttributeSetType AttributeSetType
AttributeSet type.
MeshPart< MeshType > MeshPartType
Meshpart type.
Index get_num_entities() const
Returns the number of entities.
String class implementation.
IntersectionData< DT_ > merge(const IntersectionData< DT_ > &a, const IntersectionData< DT_ > &b)
Merge two intersection datas.
@ value
specifies whether the space should supply basis function values
std::uint64_t Index
Index data type.
Helper-struct for storing relationships between meshpart entities.
std::optional< Index > right
Index of this entry in the right mesh part of the join, if it exists.
std::optional< Index > left
Index of this entry in the left mesh part of the join, it it exists.
std::optional< Index > index
Index of this entry in the result mesh part, after target sets have been built.
Face traits tag struct template.