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(); };
 
  365      return meshpart_op(left, right, merge, join_pred, 
false);
 
  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[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.
@ 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.