9#include <kernel/adjacency/coloring.hpp>
10#include <kernel/adjacency/cuthill_mckee.hpp>
11#include <kernel/adjacency/graph.hpp>
12#include <kernel/adjacency/permutation.hpp>
13#include <kernel/geometry/index_set.hpp>
14#include <kernel/geometry/target_set.hpp>
15#include <kernel/geometry/vertex_set.hpp>
30 template<
typename Shape_,
int face_dim_ = Shape_::dimension-1>
34 static void render(std::array<Adjacency::Graph, Shape_::dimension>& idx,
35 const IndexSetWrapper<Shape_, face_dim_>& isw)
37 ISWRenderer<Shape_, face_dim_-1>::render(idx, isw);
38 idx.at(face_dim_) = Adjacency::Graph(Adjacency::RenderType::as_is,
39 isw.template get_index_set<face_dim_>());
43 template<
typename Shape_>
44 class ISWRenderer<Shape_, 0>
47 static void render(std::array<Adjacency::Graph, Shape_::dimension>& idx,
48 const IndexSetWrapper<Shape_, 0>& isw)
50 idx.at(0) = Adjacency::Graph(Adjacency::RenderType::as_is,
51 isw.template get_index_set<0>());
56 template<
typename Coord_,
int dim_>
63 Tiny::Vector<Coord_, dim_> v;
66 static constexpr Coord_ tol_ = Coord_(1e-6);
72 explicit LexiPoint(Index _idx) :
79 explicit LexiPoint(Index _idx,
const Tiny::Vector<Coord_, dim_, s_>& _vtx) :
91 void add(
const Tiny::Vector<Coord_, dim_, s_>& vtx)
96 bool operator<(
const LexiPoint& other)
const
99 for(
int i(dim_-1); i > 0; --i)
101 if(v[i] + tol_ <
other.v[i])
103 if(
other.v[i] + tol_ <= v[i])
107 return v[0] <
other.v[0];
112 template<
typename Shape_,
int shape_dim_ = Shape_::dimension>
116 template<
int nc_,
typename Coord_>
118 std::array<Adjacency::Permutation, Shape_::dimension + 1>& perms,
119 const IndexSetHolder<Shape_>& ish,
const VertexSet<nc_, Coord_>& vtx)
122 LexiPermuter<Shape_, shape_dim_-1>::compute(perms, ish, vtx);
125 const auto& idx = ish.template get_index_set<shape_dim_, 0>();
126 const Index n = idx.get_num_entities();
127 const int nidx = idx.get_num_indices();
129 std::vector<LexiPoint<Coord_, nc_>> vset(n);
132 for(Index i(0); i < n; ++i)
134 LexiPoint<Coord_, nc_> v(i);
135 for(
int j(0); j < nidx; ++j)
136 v.add(vtx[idx(i,j)]);
141 std::sort(vset.begin(), vset.end());
144 Adjacency::Permutation p(n);
145 Index* vp = p.get_perm_pos();
146 for(
auto it = vset.begin(); it != vset.end(); ++it, ++vp)
148 p.calc_swap_from_perm();
149 perms.at(shape_dim_) = std::move(p);
154 template<
typename Shape_>
155 class LexiPermuter<Shape_, 0>
158 template<
int nc_,
typename Coord_>
160 std::array<Adjacency::Permutation, Shape_::dimension + 1>& perms,
161 const IndexSetHolder<Shape_>&,
const VertexSet<nc_, Coord_>& vtx)
163 const Index n = vtx.get_num_vertices();
164 std::vector<LexiPoint<Coord_, nc_>> vset(n);
167 for(Index i(0); i < n; ++i)
169 vset.at(i) = LexiPoint<Coord_, nc_>(i, vtx[i]);
173 std::sort(vset.begin(), vset.end());
176 Adjacency::Permutation p(n);
177 Index* vp = p.get_perm_pos();
178 for(
auto it = vset.begin(); it != vset.end(); ++it, ++vp)
180 p.calc_swap_from_perm();
181 perms.front() = std::move(p);
359 template<
typename Shape_>
370 typedef std::array<Adjacency::Permutation, shape_dim+1>
PermArray;
405 template<
int num_coords_,
typename Coord_>
408 const IndexSetHolder<Shape_>& ish,
412 this->
create(strategy, ish, vtx);
456 this->_strategy =
other._strategy;
457 for(std::size_t i(0); i <= std::size_t(
shape_dim); ++i)
459 this->_perms[i] =
other._perms[i].clone();
460 this->_inv_perms[i] =
other._inv_perms[i].clone();
462 this->_element_coloring =
other._element_coloring;
463 this->_element_layering =
other._element_layering;
478 for(std::size_t i(0); i <= std::size_t(
shape_dim); ++i)
525 return this->_perms.at(std::size_t(dim));
540 return this->_inv_perms.at(std::size_t(dim));
584 template<
int num_coords_,
typename Coord_>
593 XABORTM(
"use the MeshPermutation::create_other() function");
678 NumEntitiesExtractor<shape_dim>::set_num_entities_with_numverts(ish, num_entities);
679 for(std::size_t dim(0); dim <= std::size_t(
shape_dim); ++dim)
699 template<
int num_coords_,
typename Coord_>
705 Intern::LexiPermuter<ShapeType>::compute(this->_perms, ish, vtx);
708 for(std::size_t dim(0); dim <= std::size_t(
shape_dim); ++dim)
734 const auto& verts_at_elem = ish.template get_index_set<shape_dim, 0>();
745 const Index num_elems = elems_at_elem.get_num_nodes_domain();
746 const Index num_colors = cparti.get_num_nodes_domain();
756 this->_element_coloring.assign(dom_ptr, &dom_ptr[num_colors]);
778 void create_cmk(
const IndexSetHolder<Shape_>& ish,
bool reverse)
782 const auto& verts_at_elem = ish.template get_index_set<shape_dim, 0>();
818 template<
int num_coords_,
typename Coord_>
822 std::array<Adjacency::Graph, shape_dim> idx_set;
823 Intern::ISWRenderer<Shape_>::render(idx_set, ish.template get_index_set_wrapper<shape_dim>());
831 NumEntitiesExtractor<shape_dim>::set_num_entities_with_numverts(ish, num_entities);
834 const Index num_verts = num_entities[0];
838 std::array<std::vector<Index>,
shape_dim+1> perms;
839 for(std::size_t i(0); i <= std::size_t(
shape_dim); ++i)
840 perms.at(i).reserve(num_entities[i]);
844 std::array<std::vector<int>,
shape_dim+1> masks;
845 for(std::size_t i(0); i <= std::size_t(
shape_dim); ++i)
846 masks.at(i).resize(num_entities[i]);
849 std::vector<Index> layer_cur, layer_vert, layer_next;
850 layer_cur.reserve(num_elems);
851 layer_next.reserve(num_elems);
852 layer_vert.reserve(num_verts);
855 this->_element_layering.clear();
856 this->_element_layering.push_back(
Index(0));
862 while(
Index(perms.back().size()) < num_elems)
869 layer_cur.push_back(idx);
870 masks.back()[idx] = 1;
873 while(!layer_cur.empty())
877 for(
auto it = layer_cur.begin(); it != layer_cur.end(); ++it)
880 const Index cur_elem = *it;
881 perms.back().push_back(cur_elem);
885 for(
auto kt = verts_at_elem.
image_begin(cur_elem); kt != verts_at_elem.
image_end(cur_elem); ++kt)
887 const Index cur_vert = *kt;
889 if(masks.front()[cur_vert] != 0)
892 layer_vert.push_back(cur_vert);
893 perms.front().push_back(cur_vert);
894 masks.front()[cur_vert] = 1;
898 for(std::size_t k(1); k < std::size_t(
shape_dim); ++k)
900 for(
auto kt = idx_set.at(k).image_begin(cur_elem); kt != idx_set.at(k).image_end(cur_elem); ++kt)
902 const Index cur_face = *kt;
903 if(masks.at(k)[cur_face] != 0)
905 perms.at(k).push_back(cur_face);
906 masks.at(k)[cur_face] = 1;
911 for(
auto jt = layer_vert.begin(); jt != layer_vert.end(); ++jt)
913 const Index cur_vert = *jt;
914 for(
auto kt = elems_at_vert.
image_begin(cur_vert); kt != elems_at_vert.
image_end(cur_vert); ++kt)
916 const Index next_elem = *kt;
917 if(masks.back()[next_elem] != 0)
919 layer_next.push_back(next_elem);
920 masks.back()[next_elem] = 1;
926 layer_cur.swap(layer_next);
929 this->_element_layering.push_back(
Index(perms.back().size()));
938 for(std::size_t dim(0); dim <= std::size_t(
shape_dim); ++dim)
940 for(std::size_t i(0), j(perms[dim].size()-1); i < j; ++i, --j)
941 std::swap(perms[dim][i], perms[dim][j]);
945 const Index lay_back =
Index(this->_element_layering.size()) - 1u;
946 for(
Index k(lay_back); k > 0u; --k)
949 this->_element_layering.at(k) -= this->_element_layering.at(k-1u);
951 for(
Index k(1u), l(lay_back); k < l; ++k, --l)
954 std::swap(this->_element_layering.at(k), this->_element_layering.at(l));
956 for(
Index k(1u); k <= lay_back; ++k)
959 this->_element_layering.at(k) += this->_element_layering.at(k-1u);
964 for(std::size_t dim(0); dim <= std::size_t(
shape_dim); ++dim)
967 XASSERT(
Index(perms.at(dim).size()) == num_entities[dim]);
984 for(std::size_t dim(0); dim <= std::size_t(
shape_dim); ++dim)
986 if(
_perms.at(dim).empty())
1005 XASSERT(num_entities !=
nullptr);
1008 for(std::size_t i(0); i <= std::size_t(
shape_dim); ++i)
1013 if(!perm.
empty() && (perm.
size() != num_entities[i]))
1015 if(!iperm.
empty() && (iperm.
size() != num_entities[i]))
1028 const std::vector<int>& mask)
1030 std::set<Index> iset;
1033 Index deg = v_at_e.get_num_nodes_domain() + e_at_v.get_num_nodes_domain();
1035 for(
Index i(0); i < v_at_e.get_num_nodes_domain(); ++i)
#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.
Coloring object implementation.
Graph create_partition_graph() const
Creates a color partition graph.
@ minimum_degree
Minimum-degree root.
static Permutation compute(std::vector< Index > &layers, const Graph &graph, bool reverse=false, CuthillMcKee::RootType r_type=RootType::standard, CuthillMcKee::SortType t_type=SortType::standard)
Cuthill-McKee permutation computation function.
Adjacency Graph implementation.
ImageIterator image_begin(Index domain_node) const
Returns an iterator for the first adjacent image node.
Index * get_domain_ptr()
Returns the domain pointer array.
ImageIterator image_end(Index domain_node) const
Returns an iterator for the first position past the last adjacent image node.
Index * get_image_idx()
Returns the image node index array.
Index get_num_indices() const
Returns the total number indices.
Index size() const
returns the size of the permutation
bool empty() const
Checks whether the permutation is empty.
@ perm
create from permutation array
Mesh permutation class template.
void clone(const MeshPermutation &other)
Clones another mesh permutation object into this object.
std::size_t bytes() const
const std::vector< Index > & get_element_layering() const
Returns a const reference to the element layering vector.
void create_random(const IndexSetHolder< Shape_ > &ish, Random &rng)
Creates random mesh permutation for a conformal mesh.
void create_cmk(const IndexSetHolder< Shape_ > &ish, bool reverse)
Creates a (reversed) algebraic Cuthill-McKee mesh permutation for a conformal mesh.
void create_gcmk(const IndexSetHolder< Shape_ > &ish, const VertexSet< num_coords_, Coord_ > &vtx, bool reverse)
Creates a (reversed) geometric Cuthill-McKee mesh permutation for a conformal mesh.
PermArray _inv_perms
the inverse permutations
MeshPermutation & operator=(const MeshPermutation &)=delete
delete copy-assign operator
int validate_sizes(const Index *num_entities) const
Validates the permutation sizes.
std::vector< Index > _element_coloring
const PermArray & get_perms() const
const Adjacency::Permutation & get_inv_perm(int dim=shape_dim) const
Returns a const reference to an inverse permutation.
std::vector< Index > _element_layering
void create_lexicographic(const IndexSetHolder< Shape_ > &ish, const VertexSet< num_coords_, Coord_ > &vtx)
Creates a lexicographic mesh permutation for a conformal mesh.
void create_colored(const IndexSetHolder< Shape_ > &ish)
Creates a colored mesh permutation for a conformal mesh.
void create_inverse_permutations()
(Re)Creates the inverse permutations from the forward ones.
static Index _pick_gcmk_root(const Adjacency::Graph &v_at_e, const Adjacency::Graph &e_at_v, const std::vector< int > &mask)
Auxiliary helper function: pick an unmasked root element for GCMK.
PermArray & create_other()
Initializes a custom permutation.
PermutationStrategy _strategy
the permutation strategy
MeshPermutation(MeshPermutation &&other)
move constructor
Shape_ ShapeType
the underlying shape type
PermutationStrategy get_strategy() const
bool empty() const
Checks whether this permutation is empty.
PermArray _perms
the actual permutations
std::array< Adjacency::Permutation, shape_dim+1 > PermArray
permutation array typedef
MeshPermutation clone() const
MeshPermutation(PermutationStrategy strategy, const IndexSetHolder< Shape_ > &ish, const VertexSet< num_coords_, Coord_ > &vtx)
Creates a mesh permutation for a conformal mesh.
const PermArray & get_inv_perms() const
MeshPermutation & operator=(MeshPermutation &&other)
move-assignment operator
MeshPermutation()
standard constructor
static constexpr int shape_dim
the shape dimension
const std::vector< Index > & get_element_coloring() const
Returns a const reference to the element coloring vector.
void create_random(const IndexSetHolder< Shape_ > &ish)
Creates random mesh permutation for a conformal mesh.
virtual ~MeshPermutation()
virtual destructor
void create(PermutationStrategy strategy, const IndexSetHolder< Shape_ > &ish, const VertexSet< num_coords_, Coord_ > &vtx)
Creates a mesh permutation for a conformal mesh.
const Adjacency::Permutation & get_perm(int dim=shape_dim) const
Returns a const reference to a (forward) permutation.
MeshPermutation(const MeshPermutation &)=delete
delete copy constructor
Pseudo-Random Number Generator.
@ transpose
Render-Transpose mode.
@ injectify
Render-Injectified mode.
PermutationStrategy
Mesh permutation strategy enumeration.
@ colored
colored permutation strategy a.k.a. "red-black" strategy
@ none
no permutation strategy
@ cuthill_mckee_reversed
reversed (algebraic) Cuthill-McKee permutation strategy
@ other
generic/other permutation strategy
@ cuthill_mckee
(algebraic) Cuthill-McKee permutation strategy
@ random
random permutation strategy
@ geometric_cuthill_mckee_reversed
reversed geometric Cuthill-McKee permutation strategy
@ lexicographic
lexicographic permutation strategy
@ geometric_cuthill_mckee
geometric Cuthill-McKee permutation strategy
std::uint64_t Index
Index data type.
Fixed-Sized Vertex Set class template.