9#include <kernel/adjacency/graph.hpp>
10#include <kernel/geometry/conformal_mesh.hpp>
12#include <kernel/util/random.hpp>
13#include <kernel/util/dist.hpp>
14#include <kernel/util/mutable_priority_queue.hpp>
15#include <kernel/util/time_stamp.hpp>
33 distance(std::numeric_limits<Index>::max())
38 template<
typename Shape_,
int num_coords_,
typename Coord_>
42 static constexpr int facet_dim = MeshType::shape_dim-1;
43 const auto& facet_idx = mesh.template get_index_set<MeshType::shape_dim, facet_dim>();
50 std::vector<Index> distances(num_elems, std::numeric_limits<Index>::max());
51 distances.at(start) =
Index(0);
55 for (
Index i(0) ; i < num_elems ; ++i)
57 pending_nodes.insert(i, 0);
59 pending_nodes.update(start, std::numeric_limits<Index>::max());
62 Index(
Math::pow(
double(num_elems),
double(1) /
double(MeshType::shape_dim)) + 1),
63 num_elems / num_patches);
64 exploration_threshold =
Math::max(exploration_threshold,
Index(2));
67 while (pending_nodes.size() > 0)
69 Index next_node = pending_nodes.front_value();
70 Index next_distance = std::numeric_limits<Index>::max() - pending_nodes.front_key();
74 if (next_distance != std::numeric_limits<Index>::max() && next_distance > exploration_threshold)
80 for (
int j(0) ; j < facet_idx.get_num_indices() ; ++j)
82 Index other_cell(neighbors[next_node][j]);
84 if (other_cell != ~
Index(0) && pending_nodes.count(other_cell) > 0)
86 Index new_distance = distances.at(next_node) + 1;
87 if (distances.at(other_cell) > new_distance)
89 distances.at(other_cell) = new_distance;
90 pending_nodes.update(other_cell, std::numeric_limits<Index>::max() - new_distance);
98 template<
typename Shape_,
int num_coords_,
typename Coord_>
145 std::vector<Intern::PartiIterativeItem> items;
147 bool bad_centers(
true);
164 auto center_iterator =
_centers.begin();
167 auto distance_list = Intern::parti_iterative_distance(*center_iterator, mesh,
_num_patches);
170 if(distance_list.at(node) < items.at(node).distance)
172 items.at(node).distance = distance_list.at(node);
173 items.at(node).patch = patch;
181 bad_centers &= (items.at(node).distance == std::numeric_limits<Index>::max());
201 const auto& facet_idx = mesh.template get_index_set<MeshType::shape_dim, facet_dim>();
210 for (
int j(0) ; j < facet_idx.get_num_indices() ; ++j)
212 Index other_cell(neighbors[cell][j]);
231 const auto& facet_idx = mesh.template get_index_set<MeshType::shape_dim, facet_dim>();
235 Index mutation_count(0);
238 while (tries < 10*mutation_max && mutation_count < mutation_max)
253 for (
auto it(
_boundary_cells.at(patch).begin()) ; counter != rng_cell_idx ; ++counter, ++it)
259 std::list<Index> trans_patch_neighbors;
260 for (
int j(0) ; j < facet_idx.get_num_indices() ; ++j)
262 Index other_cell(neighbors[cell][j]);
266 trans_patch_neighbors.push_back(other_cell);
271 Index smallest_patch(patch);
273 for (
auto neighbor : trans_patch_neighbors)
282 if (smallest_patch == patch)
286 std::list<Index> in_patch_neighbors;
287 for (
int j(0) ; j < facet_idx.get_num_indices() ; ++j)
289 Index other_cell(neighbors[cell][j]);
293 in_patch_neighbors.push_back(other_cell);
298 bool neighbor_missing =
false;
299 for (
auto neighbor : in_patch_neighbors)
301 bool other_neighbor =
false;
302 for (
int j(0) ; j < facet_idx.get_num_indices() ; ++j)
304 Index other_cell(neighbors[neighbor][j]);
307 other_neighbor =
true;
311 if (other_neighbor ==
false)
312 neighbor_missing =
true;
314 if (neighbor_missing)
327 for (
auto neighbor : trans_patch_neighbors)
333 bool boundary(
false);
334 for (
int j(0) ; j < facet_idx.get_num_indices() ; ++j)
336 Index other_cell(neighbors[neighbor][j]);
349 for (
auto neighbor : in_patch_neighbors)
364 const auto& facet_idx =
_mesh.template get_index_set<MeshType::shape_dim, facet_dim>();
372 for (
int j(0) ; j < facet_idx.get_num_indices() ; ++j)
374 Index other_cell(neighbors[cell][j]);
385 Index get_boundary_size()
const
390 sum += get_boundary_size(patch);
400 Index get_boundary_deviation()
const
402 Index min(std::numeric_limits<Index>::max());
406 Index patches_boundary_size(get_boundary_size(patch));
407 min =
Math::min(patches_boundary_size, min);
408 max =
Math::max(patches_boundary_size, max);
413 Index get_cell_deviation()
const
415 Index min(std::numeric_limits<Index>::max());
426 template<
typename T_>
427 bool parti_iterative_compare_cell_deviation_simple(
const T_ & first,
const T_ & second)
429 if (first.get_cell_deviation() != second.get_cell_deviation())
430 return first.get_cell_deviation() < second.get_cell_deviation();
431 else if (first.get_boundary_deviation() != second.get_boundary_deviation() )
432 return first.get_boundary_deviation() < second.get_boundary_deviation();
434 return first.get_boundary_size() < second.get_boundary_size();
437 template<
typename T_>
438 bool parti_iterative_compare_cell_deviation(
const T_ & first,
const T_ & second)
440 if (first.get_cell_deviation() != second.get_cell_deviation())
441 return first.get_cell_deviation() < second.get_cell_deviation() && first.get_boundary_size() <= second.get_boundary_size() + 1;
442 else if (first.get_boundary_deviation() != second.get_boundary_deviation() )
443 return first.get_boundary_deviation() < second.get_boundary_deviation() && first.get_boundary_size() <= second.get_boundary_size() + 1;
445 return first.get_boundary_size() < second.get_boundary_size();
449 template<
typename Mesh_>
463 template<
typename Shape_,
int num_coords_,
typename Coord_>
474 std::list<Geometry::Intern::PartiIterativeIndividual<Shape_, num_coords_, Coord_>>
_population;
498 _num_elems(mesh.get_num_elements()),
499 _num_ranks(
Index(comm.size())),
501 _num_patches(num_patches)
509 _population.push_back(indi);
515 for (
Index i(0) ; i < 10 ; ++i)
518 _population.push_back(indi);
520 _population.sort(Geometry::Intern::parti_iterative_compare_cell_deviation_simple<
typename decltype(_population)::value_type>);
521 while (_population.size() > 10)
522 _population.pop_back();
531 std::list<
typename decltype(_population)::value_type> mutations;
532 for (
auto it(_population.begin()) ; it != _population.end() ; ++it)
535 indi.mutate(mesh, rng, 5);
536 mutations.push_back(indi);
538 mutations.sort(Geometry::Intern::parti_iterative_compare_cell_deviation<
typename decltype(_population)::value_type>);
539 _population.merge(mutations, Geometry::Intern::parti_iterative_compare_cell_deviation<
typename decltype(_population)::value_type>);
540 while (_population.size() > 20)
541 _population.pop_back();
544 _population.sort(Geometry::Intern::parti_iterative_compare_cell_deviation<
typename decltype(_population)::value_type>);
545 while (_population.size() > 1)
546 _population.pop_back();
559 auto& indi = _population.front();
561 Index own_cell_deviation = indi.get_cell_deviation();
562 Index lowest_cell_deviation(std::numeric_limits<Index>::max());
563 Index own_boundary_deviation = indi.get_boundary_deviation();
564 Index lowest_boundary_deviation(std::numeric_limits<Index>::max());
565 Index own_boundary_size = indi.get_boundary_size();
566 Index lowest_boundary_size(std::numeric_limits<Index>::max());
567 Index lowest_rank(0);
569 Index * all_cell_deviation =
new Index[_num_ranks];
570 Index * all_boundary_deviation =
new Index[_num_ranks];
571 Index * all_boundary_size =
new Index[_num_ranks];
572 _comm.
allgather(&own_cell_deviation, 1, all_cell_deviation, 1);
573 _comm.
allgather(&own_boundary_deviation, 1, all_boundary_deviation, 1);
574 _comm.
allgather(&own_boundary_size, 1, all_boundary_size, 1);
575 for (
Index i(0) ; i < _num_ranks ; ++i)
577 if (all_cell_deviation[i] < lowest_cell_deviation)
579 lowest_cell_deviation = all_cell_deviation[i];
580 lowest_boundary_deviation = all_boundary_deviation[i];
581 lowest_boundary_size = all_boundary_size[i];
584 else if (all_cell_deviation[i] == lowest_cell_deviation && all_boundary_deviation[i] < lowest_boundary_deviation)
586 lowest_cell_deviation = all_cell_deviation[i];
587 lowest_boundary_deviation = all_boundary_deviation[i];
588 lowest_boundary_size = all_boundary_size[i];
591 else if (all_cell_deviation[i] == lowest_cell_deviation && all_boundary_deviation[i] == lowest_boundary_deviation && all_boundary_size[i] < lowest_boundary_size)
593 lowest_cell_deviation = all_cell_deviation[i];
594 lowest_boundary_deviation = all_boundary_deviation[i];
595 lowest_boundary_size = all_boundary_size[i];
599 delete[] all_cell_deviation;
600 delete[] all_boundary_deviation;
601 delete[] all_boundary_size;
603 int _rank = _comm.
rank();
604 if (_rank == (
int)lowest_rank)
613 for(
Index i(0); i < _num_patches; ++i)
615 ptr[i+1] =
Index(indi._cells_per_patch.at(i).size()) + ptr[i];
620 for (
Index rank(0) ; rank < _num_patches ; ++rank)
622 for (
auto cell : indi._cells_per_patch.at(rank))
634 Index * domain_ptr =
new Index[_num_patches + 1];
635 _comm.
bcast(domain_ptr, _num_patches + 1, (
int)lowest_rank);
637 _comm.
bcast(image_idx, _num_elems, (
int)lowest_rank);
638 Adjacency::Graph graph(_num_patches, _num_elems, _num_elems, domain_ptr, image_idx);
#define XASSERT(expr)
Assertion macro definition.
Adjacency Graph implementation.
Index * get_domain_ptr()
Returns the domain pointer array.
Index * get_image_idx()
Returns the image node index array.
void bcast(void *buffer, std::size_t count, const Datatype &datatype, int root) const
Blocking broadcast.
int rank() const
Returns the rank of this process in this communicator.
void allgather(const void *sendbuf, std::size_t sendcount, const Datatype &sendtype, void *recvbuf, std::size_t recvcount, const Datatype &recvtype) const
Blocking gather-to-all.
std::vector< std::set< Index > > _boundary_cells
List of boundary cells per patch.
std::vector< Index > _patch_per_cell
mapping of cell to patch number
std::vector< std::set< Index > > _cells_per_patch
Mapping of patches to cells assigned to each patch.
void mutate(MeshType &mesh, Random &rng, Index mutation_max)
mutate individuum - let cells switch to smaller patches
PartiIterativeIndividual(MeshType &mesh, Random &rng, Index num_patches)
Constructor.
std::set< Index > _centers
List of cluster centers: cell id for each patch.
void update_boundary_size()
update boundary size per patch from _boundary_cells structure
const Index _num_elems
number of elements in input mesh
std::vector< Index > _boundary_size_per_patch
boundary size per patch, must be updated via update_boundary_size method
const Index _num_patches
number of desired patches
ConformalMesh< Shape_, num_coords_, Coord_ > MeshType
our mesh type
Iterative-Partitioner class template declaration.
Pseudo-Random Number Generator.
TimeStamp & stamp()
Stamps the current time-stamp.
double elapsed_now() const
Calculates the time elapsed between the time stamp and now.
T_ pow(T_ x, T_ y)
Returns x raised to the power of y.
T_ min(T_ a, T_ b)
Returns the minimum of two values.
T_ max(T_ a, T_ b)
Returns the maximum of two values.
std::uint64_t Index
Index data type.