8 #ifndef CARTDECOMPOSITION_HPP
9 #define CARTDECOMPOSITION_HPP
13 #include "VCluster/VCluster.hpp"
14 #include "Graph/CartesianGraphFactory.hpp"
15 #include "Decomposition.hpp"
16 #include "Vector/map_vector.hpp"
18 #include <initializer_list>
19 #include "SubdomainGraphNodes.hpp"
20 #include "dec_optimizer.hpp"
21 #include "Space/Shape/Box.hpp"
22 #include "Space/Shape/Point.hpp"
23 #include "NN/CellList/CellDecomposer.hpp"
24 #include <unordered_map>
25 #include "NN/CellList/CellList.hpp"
26 #include "Space/Ghost.hpp"
28 #include "ie_loc_ghost.hpp"
29 #include "ie_ghost.hpp"
30 #include "nn_processor.hpp"
31 #include "GraphMLWriter/GraphMLWriter.hpp"
32 #include "Distribution/ParMetisDistribution.hpp"
33 #include "Distribution/DistParMetisDistribution.hpp"
34 #include "Distribution/MetisDistribution.hpp"
35 #include "DLB/DLB.hpp"
36 #include "util/se_util.hpp"
37 #include "util/mathutil.hpp"
38 #include "CartDecomposition_ext.hpp"
39 #include "data_type/aggregate.hpp"
40 #include "Domain_NN_calculator_cart.hpp"
42 #define CARTDEC_ERROR 2000lu
55 template<
unsigned int dim>
static void nsub_to_div2(
size_t (& div)[dim],
size_t n_sub,
size_t dim_r)
57 for (
size_t i = 0; i < dim; i++)
60 {div[i] = openfpm::math::round_big_2(pow(n_sub, 1.0 / dim_r));}
77 template<
unsigned int dim>
static void nsub_to_div(
size_t (& div)[dim],
size_t n_sub,
size_t dim_r)
79 for (
size_t i = 0; i < dim; i++)
82 {div[i] = std::floor(pow(n_sub, 1.0 / dim_r));}
88 #define COMPUTE_SKIN_SUB 1
131 template<
unsigned int dim,
typename T,
typename Memory,
typename Distribution>
184 CellDecomposer_sm<dim, T, shift<dim,T>>
cd;
235 for (
size_t i = 0 ; i < dim ; i++) {one[i] = 1;}
243 for (
size_t i = 0 ; i < dim ; i++)
260 for (
size_t i = 0; i < dim; i++)
265 if (sub_dc.
getLow(i) == 0)
291 for (
unsigned int i = 0; i < dim; i++)
308 for (
size_t i = 0 ; i < dim ; i++)
310 ghe.setLow(i,static_cast<long int>(
ghost.getLow(i)/
spacing[i]) - 1);
311 ghe.setHigh(i,static_cast<long int>(
ghost.getHigh(i)/
spacing[i]) + 1);
318 if (loc_box.size() > 0)
327 for (
size_t i = 0 ; i < dim ; i++)
338 for (
size_t s = 1; s < loc_box.size(); s++)
366 for (
size_t i = 0 ; i < dim ; i++)
372 fine_s.get(lin2) =
dist.getGraph().template vertex_p<nm_v::proc_id>(lin);
398 for (
size_t i = 0; i < dim; i++)
399 {div[i] = (size_t) ((bound.
getHigh(i) - bound.
getLow(i)) /
cd.getCellBox().getP2()[i]);}
418 float b_s =
static_cast<float>(cellBox.
getHigh(0));
419 float gh_s =
static_cast<float>(
ghost.getHigh(0));
422 float gh_v = (gh_s * b_s);
425 for (
size_t i = 2; i < dim; i++)
431 size_t norm = (size_t) (1.0 / gh_v);
433 migration = pow(b_s, dim);
437 for (
size_t i = 0; i <
dist.getNSubSubDomains(); i++)
439 dist.setMigrationCost(i, norm * migration );
441 for (
size_t s = 0; s <
dist.getNSubSubDomainNeighbors(i); s++)
445 dist.setCommunicationCost(i, s, 1 * ts);
447 prev +=
dist.getNSubSubDomainNeighbors(i);
474 for (
int i = 0; i < dim; i++)
596 static constexpr
int dims = dim;
745 for (
size_t i = 0 ; i < dim ; i++)
747 if (
bc[i] == PERIODIC)
748 pt[i] = openfpm::math::periodic_l(pt[i],
domain.getHigh(i),
domain.getLow(i));
763 for (
size_t i = 0 ; i < dim ; i++)
765 if (
bc[i] == PERIODIC)
781 for (
size_t i = 0 ; i < dim ; i++)
783 if (
bc[i] == PERIODIC)
784 pt.template get<0>()[i] = openfpm::math::periodic_l(pt.template get<0>()[i],
domain.getHigh(i),
domain.getLow(i));
806 for (
size_t i = 0 ; i < dim ; i++)
814 for (
size_t i = 0 ; i < dim ; i++)
848 for (
size_t i = 0 ; i < dim ; i++)
855 for (
size_t i = 0 ; i < dim ; i++)
856 cart.
bc[i] = this->bc[i];
884 for (
size_t i = 0 ; i < dim ; i++)
894 for (
size_t i = 0 ; i < dim ; i++)
922 for (
size_t i = 0 ; i < dim ; i++)
925 magn[i] = cart.magn[i];
932 for (
size_t i = 0 ; i < dim ; i++)
953 return openfpm::math::round_big_2(pow(n_sub, 1.0 / dim));
965 return fine_s.get(
cd.template getCell(p));
1075 for (
size_t i = 0 ; i < dim ; i++)
1080 for (
size_t i = 0 ; i < dim ; i++)
1083 std::cerr << __FILE__ <<
":" << __LINE__ <<
".Error the decomposition grid specified as gr.size(" << i <<
")=" <<
gr.
size(i) <<
" is not multiple of the distribution grid gm.size(" << i <<
")=" << gm.
size(i) << std::endl;
1105 const size_t (&
bc)[dim],
1116 size_t n_sub = n_proc * dec_gran;
1121 nsub_to_div2(div,n_sub,dim);
1130 long int dim_r = dim-1;
1134 size_t tot_size = 1;
1135 for (
size_t i = 0 ; i < dim ; i++)
1136 {tot_size *= div[i];}
1139 if (tot_size / n_proc > 0.75*dec_gran )
1142 nsub_to_div(div,n_sub,dim_r);
1158 for (
size_t i = 0 ; i < dim ; i++)
1159 {div_[i] = this->
gr.
size(i);}
1175 const size_t (&
bc)[dim],
1180 for (
size_t i = 0 ; i < dim ; i++)
1181 this->
bc[i] =
bc[i];
1184 this->ghost =
ghost;
1192 if (sec_dist.size(0) != 0)
1296 if (dlb.
getHeurisitc() == DLB::Heuristic::UNBALANCE_THRLD)
1298 float unbalance =
dist.getUnbalance();
1302 std::cout << std::setprecision(3) << unbalance <<
"\n";
1323 return dist.getUnbalance();
1332 return dist.getProcessorLoad();
1343 dist.getSubSubDomainPosition(
id, pos);
1353 return dist.getNSubSubDomains();
1364 dist.setComputationCost(
id, weight);
1376 return dist.getSubSubDomainComputationCost(
id);
1385 return dist.subSize();
1412 for (
size_t k = 0; k < dim; k++)
1518 for (
size_t i = 0 ; i < dim ; i++)
1520 if (
bc[i] == PERIODIC)
1521 pt.
get(i) = openfpm::math::periodic_l(p.template get<0>()[i],
domain.getHigh(i),
domain.getLow(i));
1605 for (
size_t i = 0 ; i < dim ; i++)
1607 if (
bc[i] == PERIODIC)
1608 pt.
get(i) = openfpm::math::periodic_l(p[i],
domain.getHigh(i),
domain.getLow(i));
1680 vtk_box1.write(output + std::string(
"subdomains_") + std::to_string(v_cl.
getProcessUnitID()) + std::string(
".vtk"));
1720 std::cout <<
"Subdomains\n";
1723 std::cout << ::SpaceBox<dim, T>(
sub_domains.get(p)).toString() <<
"\n";
1726 std::cout <<
"External ghost box\n";
1728 for (
size_t p = 0; p<nn_prcs < dim, T>::getNNProcessors(); p++)
1730 for (
size_t i = 0; i<ie_ghost < dim, T>::getProcessorNEGhost(p); i++)
1736 std::cout <<
"Internal ghost box\n";
1738 for (
size_t p = 0; p<nn_prcs < dim, T>::getNNProcessors(); p++)
1740 for (
size_t i = 0; i<ie_ghost < dim, T>::getProcessorNIGhost(p); i++)
1786 if (ghost != cart.
ghost)
1853 size_t c =
dist.getSubSubDomainComputationCost(gid);
1855 dist.setComputationCost(gid, c + i);
1865 return dist.get_ndec();
openfpm::vector< size_t > fine_s
size_t getProcessorLoad()
Compute the processor load counting the total weights of its vertices.
void setGoodParameters(::Box< dim, T > domain_, const size_t(&bc)[dim], const Ghost< dim, T > &ghost, size_t dec_gran, const grid_sm< dim, void > &sec_dist=grid_sm< dim, void >())
Set the best parameters for the decomposition.
openfpm::vector< openfpm::vector< SpaceBox< dim, T > > > sub_domains_global
the global set of all sub-domains as vector of 'sub_domains' vectors
void redecompose(size_t ts)
Refine the decomposition, available only for ParMetis distribution, for Metis it is a null call...
This class represent an N-dimensional box.
CellDecomposer_sm< dim, T, shift< dim, T > > cd
bool is_equal(CartDecomposition< dim, T, Memory > &cart)
Check if the CartDecomposition contain the same information.
size_t IDtoProc(size_t id) const
Return the processor id of the near processor list at place id.
mem_id LinId(const grid_key_dx< N > &gk, const char sum_id[N]) const
Linearization of the grid_key_dx with a specified shift.
void applyPointBC(encapc< 1, Point< dim, T >, Mem > &&pt) const
Apply boundary condition to the point.
void getParameters(size_t(&div_)[dim])
return the parameters of the decomposition
void debugPrint()
Print subdomains, external and internal ghost boxes.
CartDecomposition(const CartDecomposition< dim, T, Memory, Distribution > &cart)
Cartesian decomposition copy constructor.
size_t processorIDBC(const T(&p)[dim]) const
Given a point return in which processor the particle should go.
Vcluster & v_cl
Runtime virtual cluster machine.
Transform the boost::fusion::vector into memory specification (memory_traits)
const grid_sm< dim, void > getGrid()
Decomposition grid.
Heuristic getHeurisitc()
Get the heuristic.
bool write(std::string output, size_t p_id) const
write the information about the ghost in vtk format
void incRef()
Increment the reference counter.
This class decompose a space into sub-sub-domains and distribute them across processors.
openfpm::vector< subsub_lin< dim > > & getCRSAnomDomainCells()
Get the domain anomalous cells.
void setParameters(const Box< dim, long int > &proc_box)
Set parameters to calculate the cell neighborhood.
const size_t(& periodicity() const)[dim]
Get the periodicity.
T getLow(int i) const
get the i-coordinate of the low bound interval of the box
SpaceBox< dim, T > convertDecBoxIntoSubDomain(encapc< 1,::Box< dim, size_t >, Memory_bx > loc_box)
It convert the box from the domain decomposition into sub-domain.
const CellDecomposer_sm< dim, T, shift< dim, T > > & getCellDecomposer()
Get the cell decomposer of the decomposition.
grid_key_dx is the key to access any element in the grid
size_t processorIDBC(const Point< dim, T > &p) const
Given a point return in which processor the particle should go.
const ::Box< dim, T > & getDomain() const
Return the box of the physical domain.
size_t getProcessUnitID()
Get the process unit id.
void generateShiftVectors(const Box< dim, T > &domain, size_t(&bc)[dim])
Here we generare the shift vectors.
static size_t getDefaultGrid(size_t n_sub)
The default grid size.
CartDecomposition< dim, T, Memory, Distribution > & operator=(const CartDecomposition &cart)
Copy the element.
void setNNParameters(openfpm::vector<::Box< dim, size_t >> &loc_box, const grid_key_dx< dim > &shift, const grid_sm< dim, void > &gs)
Set parameters to calculate the cell neighborhood.
::Box< dim, T > bbox
Processor bounding box.
void applyPointBC(float(&pt)[dim]) const
Apply boundary condition to the point.
bool commCostSet
Indicate the communication weight has been set.
void decompose()
Start decomposition.
void setParameters(const size_t(&div_)[dim],::Box< dim, T > domain_, const size_t(&bc)[dim], const Ghost< dim, T > &ghost, const grid_sm< dim, void > &sec_dist=grid_sm< dim, void >())
Set the parameter of the decomposition.
void mul(T(&sp)[dim])
multiply the space box with the coefficient defined in sp
size_t subSize()
Operator to access the size of the sub-graph.
size_t getNSubSubDomains()
Get the number of sub-sub-domains in this sub-graph.
size_t size() const
Return the size of the grid.
void calculate_magn(const grid_sm< dim, void > &gm)
Calculate magnification.
bool check_consistency()
function to check the consistency of the information of the decomposition
T spacing[dim]
Box Spacing.
void create_box_nn_processor_ext(Vcluster &v_cl, Ghost< dim, T > &ghost, openfpm::vector< SpaceBox< dim, T >> &sub_domains, const openfpm::vector< openfpm::vector< long unsigned int > > &box_nn_processor, const nn_prcs< dim, T > &nn_p)
Create the box_nn_processor_int (bx part) structure.
void addComputationCost(size_t gid, size_t i)
Add computation cost i to the subsubdomain with global id gid.
T getHigh(int i) const
get the high interval of the box
CartDecomposition_ext< dim, T, Memory, Distribution > extended_type
This class admit a class defined on an extended domain.
size_t processorID(const Point< dim, T > &p) const
Given a point return in which processor the particle should go.
SpaceBox< dim, T > getSubDomainWithGhost(size_t lc)
Get the local sub-domain enlarged with ghost extension.
grid_key_dx< dim > one
key with all coordinates set to one
SpaceBox< dim, T > Box
It simplify to access the SpaceBox element.
void setHigh(int i, T val)
set the high interval of the box
void refine(size_t ts)
Refine the decomposition, available only for ParMetis distribution, for Metis it is a null call...
grid_sm< dim, void > gr_dist
Structure that store the cartesian grid information.
This class implement the point shape in an N-dimensional space.
static bool check_valid(comb< dim > cmb, const size_t(&bc)[dim])
grow_policy_double vector_grow_policy_default
default grow policy
bool rebalanceNeeded()
check if a re-balance is needed using the selected heuristic
bool isLocalBC(const encapc< 1, Point< dim, T >, Mem > p, const size_t(&bc)[dim]) const
Check if the particle is local considering boundary conditions.
bool write(std::string output) const
Write the decomposition as VTK file.
void getSubSubDomainPosition(size_t id, T(&pos)[dim])
function that return the position of the cell in the space
openfpm::vector< SpaceBox< dim, T >, Memory, typename memory_traits_lin< SpaceBox< dim, T > >::type, memory_traits_lin, openfpm::vector_grow_policy_default, openfpm::vect_isel< SpaceBox< dim, T > >::value >::access_key acc_key
void reset()
Reset the nn_prcs structure.
void expand(T(&exp)[dim])
expand the box by a vector
Distribution & getDistribution()
Return the distribution object.
void computeCommunicationAndMigrationCosts(size_t ts)
Calculate communication and migration costs.
class to select the returned id by ghost_processorID
void applyPointBC(Point< dim, T > &pt) const
Apply boundary condition to the point.
void reset()
Delete the decomposition and reset the data-structure.
Distribution dist
Create distribution.
openfpm::vector< size_t > & getCRSDomainCells()
Get the CRS domain Cells with normal neighborhood.
grid_sm< dim, void > gr
Structure that store the cartesian grid information.
mem_id get(size_t i) const
Get the i index.
bool isLocal(const encapc< 1, Point< dim, T >, Mem > p) const
Check if the particle is local.
Implementation of VCluster class.
const grid_sm< dim, void > getDistGrid()
Distribution grid.
static size_t id(p_box< dim, T > &p, size_t b_id)
Return the shift id.
void reset()
Reset the ie_loc_ghost.
static size_t id(p_box< dim, T > &p, size_t b_id)
Return the near processor id.
size_t lc_proc
local processor id
openfpm::vector< size_t > & getCRSDomainCells()
Get the domain Cells.
bool isLocal(const T(&pos)[dim]) const
Check if the particle is local.
size_t getNTimeStepSinceDLB()
Get how many time-steps have passed since the last re-balancing.
grid_sm< dim, void > gs
Processor cells-grid.
long int ref()
Return the reference counter.
This class decompose a space into sub-sub-domains and distribute them across processors.
openfpm::vector< subsub_lin< dim > > & getCRSAnomDomainCells()
Get the CRS anomalous cells.
void enclose(const Box< dim, T > &en)
Refine the box to enclose the given box and itself.
::Box< dim, T > & getProcessorBounds()
Return the bounding box containing union of all the sub-domains for the local processor.
size_t getNSubDomain()
Get the number of local sub-domains.
CartDecomposition(Vcluster &v_cl)
Cartesian decomposition constructor.
bool refine(DLB &dlb)
Refine the decomposition, available only for ParMetis distribution, for Metis it is a null call...
SpaceBox< dim, T > getSubDomain(size_t lc)
Get the local sub-domain.
It analyze the type given and it select correctly the implementation for vector.
structure that store and compute the internal and external local ghost box
CartDecomposition< dim, T, Memory, Distribution > duplicate() const
It create another object that contain the same information and act in the same way.
void Initialize_geo_cell_lists()
Initialize geo_cell lists.
void enlarge(const Box< dim, T > &gh)
Enlarge the box with ghost margin.
const size_t(& getSize() const)[N]
Return the size of the grid as an array.
size_t shift_id
shift vector id
void reset()
In case you have to recompute the indexes.
void create_box_nn_processor_int(Vcluster &v_cl, Ghost< dim, T > &ghost, openfpm::vector< SpaceBox< dim, T >> &sub_domains, const openfpm::vector< openfpm::vector< long unsigned int > > &box_nn_processor, const nn_prcs< dim, T > &nn_p)
Create the box_nn_processor_int (nbx part) structure, the geo_cell list and proc_int_box.
class to select the returned id by ghost_processorID
void create(openfpm::vector< SpaceBox< dim, T >> &sub_domains, Box< dim, T > &domain, Ghost< dim, T > &ghost, const size_t(&bc)[dim])
Create external and internal local ghosts.
const grid_key_dx< dim > & get() const
Get the actual key.
Ghost< dim, T > ghost
ghost info
CartDecomposition< dim, T, Memory, Distribution > duplicate(const Ghost< dim, T > &g) const
It create another object that contain the same decomposition information but with different ghost box...
size_t bc[dim]
Boundary condition info.
::Box< dim, size_t > proc_box
Processor domain bounding box.
bool isValidN() const
Check if the Box is a valid box P2 > P1.
CartDecomposition< dim, T, Memory, Distribution > base_type
This class is base of itself.
const T & get(size_t i) const
Get coordinate.
openfpm::vector< size_t > & getDomainCells()
Get the domain Cells.
size_t proc
processor rank
void setLow(int i, T val)
set the low interval of the box
static size_t id(p_box< dim, T > &p, size_t b_id)
Return the processor id.
bool isNext()
Check if there is the next element.
size_t periodicity(size_t i) const
Get the periodicity on i dimension.
This class is a trick to indicate the compiler a specific specialization pattern. ...
bool write(std::string output, size_t p_id) const
Write the decomposition as VTK file.
void Initialize_geo_cell(const Box< dim, T > &domain, const size_t(&div)[dim])
Initialize the geo cell list structure.
bool write(std::string output) const
Write the decomposition as VTK file.
void decRef()
Decrement the reference counter.
This class take a graph representing the space decomposition and produce a simplified version...
T domain_type
Type of the domain we are going to decompose.
const Ghost< dim, T > & getGhost() const
Return the ghost.
structure that store and compute the internal and external local ghost box
size_t getProcessorEGhostId(size_t id, size_t j) const
Get the j External ghost box id.
size_t processorID(const T(&p)[dim]) const
Given a point return in which processor the particle should go.
size_t getSubSubDomainComputationCost(size_t id)
function that return the computation cost of the sub-sub-domain id
bool isLocal(const Point< dim, T > &pos) const
Check if the particle is local.
static size_t id(p_box< dim, T > &p, size_t b_id)
Return the box id.
class to select the returned id by ghost_processorID
size_t getProcessorIGhostId(size_t id, size_t j) const
Get the j Internal ghost box id.
void calculateGhostBoxes()
It calculate the internal ghost boxes.
size_t get_ndec()
Get the decomposition counter.
This class calculate processor domains and neighborhood of each processor domain. ...
bool is_equal_ng(CartDecomposition< dim, T, Memory > &cart)
Check if the CartDecomposition contain the same information with the exception of the ghost part It i...
class to select the returned id by ghost_processorID
void set_d(size_t i, mem_id id)
Set the i index.
CartDecomposition< dim, T, Memory, Distribution > & operator=(CartDecomposition &&cart)
Copy the element, move semantic.
::Box< dim, T > domain
rectangular domain to decompose
Vcluster & getVC() const
Get the Virtual Cluster machine.
size_t processorID(const encapc< 1, Point< dim, T >, Mem > &p) const
Given a point return in which processor the particle should go.
It store all the boxes of the near processors in a linear array.
void setSubSubDomainComputationCost(size_t id, size_t weight)
Function that set the computational cost for a of a sub-sub domain.
openfpm::vector< SpaceBox< dim, T > > sub_domains
the set of all local sub-domain as vector
void applyBC(const Box< dim, T > &domain, const Ghost< dim, T > &ghost, const size_t(&bc)[dim])
Apply boundary conditions.
Implementation of 1-D std::vector like structure.
CartDecomposition(CartDecomposition< dim, T, Memory, Distribution > &&cart)
Cartesian decomposition copy constructor.
bool isLocalBC(const T(&p)[dim], const size_t(&bc)[dim]) const
Check if the particle is local considering boundary conditions.
void createSubdomains(Vcluster &v_cl, const size_t(&bc)[dim], size_t opt=0)
Constructor, it decompose and distribute the sub-domains across the processors.
size_t processorIDBC(encapc< 1, Point< dim, T >, Mem > p)
Given a point return in which processor the point/particle should go.
long int ref_cnt
reference counter of the object in case is shared between object
size_t getProcessingUnits()
Get the total number of processors.
openfpm::vector< openfpm::vector< long unsigned int > > box_nn_processor
for each sub-domain, contain the list of the neighborhood processors
openfpm::vector<::Box< dim, size_t > > loc_box
set of Boxes produced by the decomposition optimizer
void setDimensions(const size_t(&dims)[N])
Reset the dimension of the grid.
void setNNParameters(grid_key_dx< dim > &shift, grid_sm< dim, void > &gs)
set NN parameters to calculate cell-list neighborhood
void reset()
Reset the nn_prcs structure.
openfpm::vector< size_t > & getDomainCells()
Get the domain Cells.
friend extended_type
friend classes
static constexpr int dims
Space dimensions.
void setUnbalance(float u)
Set un-balance value.
void CreateSubspaces()
Create the sub-domain that decompose your domain.
~CartDecomposition()
Cartesian decomposition destructor.
float getUnbalance()
Get the current un-balance value.
void create(const openfpm::vector< openfpm::vector< long unsigned int > > &box_nn_processor, const openfpm::vector< SpaceBox< dim, T >> &sub_domains)
Create the list of adjacent processors and the list of adjacent sub-domains.
This class store the adjacent processors and the adjacent sub_domains.