-
Pietro Incardona authoredPietro Incardona authored
grid_dist_util.hpp 15.82 KiB
/*
* grid_dist_util.hpp
*
* Created on: Jan 28, 2016
* Author: i-bird
*/
#ifndef SRC_GRID_GRID_DIST_UTIL_HPP_
#define SRC_GRID_GRID_DIST_UTIL_HPP_
#include "NN/CellList/CellDecomposer.hpp"
#include "Decomposition/common.hpp"
/*! \brief get cellDecomposer parameters
*
* \tparam dim dimensionality
*
* \param c_g get the parameters of the cell decomposer
* \param g_sz global grid parameters
*
*/
template<unsigned int dim> void getCellDecomposerPar(size_t (& c_g)[dim], const size_t (& g_sz)[dim], const size_t (& bc)[dim])
{
for (size_t i = 0 ; i < dim ; i++)
{
if (bc[i] == NON_PERIODIC)
c_g[i] = (g_sz[i]-1 > 0)?(g_sz[i]-1):1;
else
c_g[i] = g_sz[i];
}
}
/*! \brief Create NON_PERIODIC data structure
*
* \tparam dim Dimensionality
*
* \return structure that define the non periodicity of the grid
*
*/
template<unsigned int dim> periodicity<dim> create_non_periodic()
{
periodicity<dim> p;
for(size_t i = 0 ; i < dim ; i++)
p.bc[i] = NON_PERIODIC;
return p;
}
template<unsigned int dim>
size_t get_gdb_ext(const openfpm::vector<GBoxes<dim>> & gdb_ext, size_t start , size_t stop, size_t k)
{
for (size_t i = start ; i < stop ; i++)
{
if (gdb_ext.get(i).k == k)
{return i;}
}
// not found
return (size_t)-1;
}
/*! \brief Add a box to gdb_ext
*
* \param on which gdb_ext array add the box
* \param k from which definition box it come from
* This parameter make sense only when the grid is not defined everywhere
* \param grid of the sub-domain
* \param grid of the sub-domain inclusive of ghost
*
*/
template<unsigned int dim>
void add_to_gdb_ext(openfpm::vector<GBoxes<dim>> & gdb_ext, size_t k, Box<dim,long int> & sp_t, Box<dim,long int> & sp_tg)
{
// Add gdb_ext
gdb_ext.add();
//! Save the origin of the sub-domain of the local grid
gdb_ext.last().origin = sp_tg.getP1();
// save information about the local grid: domain box seen inside the domain + ghost box (see GDBoxes for a visual meaning)
// and where the GDBox start, or the origin of the local grid (+ghost) in global coordinate
gdb_ext.last().Dbox = sp_t;
gdb_ext.last().Dbox -= sp_tg.getP1();
gdb_ext.last().GDbox = sp_tg;
gdb_ext.last().GDbox -= sp_tg.getP1();
gdb_ext.last().k = k;
}
/*! \brief Create the gdb_ext
*
* It is a fundamental function, because it create the structure that store the information of the local grids. In
* particular from the continuous decomposed domain it calculate the grid that each sub-domain store
*
* \param gdb_ext output Vector of Boxes that define the local grids extension
* \param dec Decomposition
* \param cd_sm CellDecomposer the size of cell is equal to the distance between grid points
*
*/
template<int dim, typename Decomposition>
inline void create_gdb_ext(openfpm::vector<GBoxes<Decomposition::dims>> & gdb_ext,
openfpm::vector<size_t> & gdb_ext_markers,
Decomposition & dec,
CellDecomposer_sm<Decomposition::dims,typename Decomposition::stype,shift<dim,typename Decomposition::stype>> & cd_sm,
openfpm::vector<Box<Decomposition::dims,long int>> & bx_create,
const Ghost<Decomposition::dims,long int> & exp,
bool use_bx_def)
{
gdb_ext.clear();
gdb_ext_markers.clear();
// Get the number of local grid needed
size_t n_grid = dec.getNSubDomain();
// Allocate the grids
for (size_t i = 0 ; i < n_grid ; i++)
{
gdb_ext_markers.add(gdb_ext.size());
// Get the local sub-domain (Grid conversion must be done with the domain P1 equivalent to 0.0)
// consider that the sub-domain with point P1 equivalent to the domain P1 is a (0,0,0) in grid unit
SpaceBox<Decomposition::dims, typename Decomposition::stype> sp = dec.getSubDomain(i);
SpaceBox<Decomposition::dims, typename Decomposition::stype> sp_g = dec.getSubDomainWithGhost(i);
// Because of round off we expand for safety the ghost area
// std::nextafter return the next bigger or smaller representable floating
// point number
for (size_t i = 0 ; i < Decomposition::dims ; i++)
{
sp_g.setLow(i,std::nextafter(sp_g.getLow(i),sp_g.getLow(i) - 1.0));
sp_g.setHigh(i,std::nextafter(sp_g.getHigh(i),sp_g.getHigh(i) + 1.0));
}
// Convert from SpaceBox<dim,St> to SpaceBox<dim,long int>
SpaceBox<Decomposition::dims,long int> sp_t = cd_sm.convertDomainSpaceIntoGridUnits(sp,dec.periodicity());
SpaceBox<Decomposition::dims,long int> sp_tg = cd_sm.convertDomainSpaceIntoGridUnits(sp_g,dec.periodicity());
for (size_t i = 0 ; i < Decomposition::dims ; i++)
{
if (sp_t.getLow(i) < sp_tg.getLow(i))
{sp_tg.setLow(i,sp_t.getLow(i));}
if (sp_t.getHigh(i) > sp_tg.getHigh(i))
{sp_tg.setHigh(i,sp_t.getHigh(i));}
}
if (use_bx_def == true)
{
// intersect the sub-domain with all the boxes
for (size_t k = 0 ; k < bx_create.size() ; k++)
{
Box<Decomposition::dims, long int> inte;
if (sp_t.Intersect(bx_create.get(k),inte) == true)
{
// Ok we have a sub-domain now we have to create the ghost part.
// The ghost part is created converting the bx_def into a continuous
// box expanding this box by the ghost and intersecting this box
// with the sub-domain. This is one way to get a ghost area consistent
// with the construction of the external and internal ghost boxes,
// always calculated in continuous from the decomposition.
//
Box<Decomposition::dims,typename Decomposition::stype> output;
Box<Decomposition::dims,typename Decomposition::stype> bx_wg = cd_sm.convertCellUnitsIntoDomainSpaceMiddle(bx_create.get(k));
bx_wg.enlarge(dec.getGhost());
bx_wg.Intersect(sp_g,output);
SpaceBox<Decomposition::dims,long int> sp_t2 = inte;
SpaceBox<Decomposition::dims,long int> sp_tg2 = cd_sm.convertDomainSpaceIntoGridUnits(output,dec.periodicity());
add_to_gdb_ext(gdb_ext,k,sp_t2,sp_tg2);
}
}
}
else
{
add_to_gdb_ext(gdb_ext,0,sp_t,sp_tg);
}
}
gdb_ext_markers.add(gdb_ext.size());
}
/*! \brief Create the gdb_ext
*
* \param gdb_ext Vector of Boxes that define the local grids extension
* \param gdb_ext_markers filled with sub-domain markers
* see gdb_ext_markers in grid_dist_id for an explanation
* \param dec Decomposition
* \param sz Global grid grid size
* \param domain Domain where the grid is defined
* \param spacing Define the spacing of the grid
* \param bc boundary conditions
*
*/
template<int dim, typename Decomposition>
inline void create_gdb_ext(openfpm::vector<GBoxes<dim>> & gdb_ext,
Decomposition & dec,
const size_t (& sz)[dim],
const Box<Decomposition::dims,typename Decomposition::stype> & domain,
typename Decomposition::stype (& spacing)[dim])
{
// Create the cell decomposer
CellDecomposer_sm<Decomposition::dims,typename Decomposition::stype, shift<Decomposition::dims,typename Decomposition::stype>> cd_sm;
size_t cdp[dim];
// Get the parameters to create a Cell-decomposer
getCellDecomposerPar<Decomposition::dims>(cdp,sz,dec.periodicity());
// Careful cd_sm require the number of cell
cd_sm.setDimensions(domain,cdp,0);
// create an empty vector of boxes
openfpm::vector<Box<Decomposition::dims,long int>> empty;
Ghost<Decomposition::dims,long int> zero(0);
//! We are not interested on the markers
openfpm::vector<size_t> unused;
create_gdb_ext<dim,Decomposition>(gdb_ext,unused,dec,cd_sm,empty,zero,false);
// fill the spacing
for (size_t i = 0 ; i < dim ; i++)
{spacing[i] = cd_sm.getCellBox().getP2()[i];}
}
/*! \brief It store the information about the external ghost box
*
*
*/
template <unsigned int dim> struct e_box_id
{
//! Box defining the external ghost box in global coordinates
::Box<dim,long int> g_e_box;
//! Box defining the external ghost box in local coordinates for gdb_ext
::Box<dim,long int> l_e_box;
//! Box defining the external box in local coordinates for received box
::Box<dim,long int> lr_e_box;
//! Sector position of the external ghost
comb<dim> cmb;
//! Id
size_t g_id;
//! sub_id in which sub-domain this box live
size_t sub;
};
/*! \brief flip box just convert and internal ghost box into an external ghost box and the other way around
*
* \param box to convert
* \param cmb sector position of the box
*
* \return the converted box
*
*/
template<unsigned int dim, typename T, typename idT>
Box<dim,long int> flip_box(const Box<dim,idT> & box, const comb<dim> & cmb, const grid_sm<dim,T> & ginfo)
{
Box<dim,long int> flp;
for (size_t i = 0 ; i < dim; i++)
{
if (cmb[i] == 0)
{
flp.setLow(i,box.getLow(i));
flp.setHigh(i,box.getHigh(i));
}
else if (cmb[i] == 1)
{
flp.setLow(i,box.getLow(i) + ginfo.size(i));
flp.setHigh(i,box.getHigh(i) + ginfo.size(i));
}
else if (cmb[i] == -1)
{
flp.setLow(i,box.getLow(i) - ginfo.size(i));
flp.setHigh(i,box.getHigh(i) - ginfo.size(i));
}
}
return flp;
}
/*! \brief convert to sub-domain id
*
* In case the grid is not defined everywhere the ids returned by getProcessorIGhostSub
* or any function that return a sub-domain id does not match the ids in gdb_ext. This
* function convert it to the correct one
*
* \param k sub-domain id to convert
* \param def_id id of the box that define the real allocated grid
* \param gdb_ext_markers markers for sub-domain id gdb_ext
*
*/
template<unsigned int dim>
inline size_t convert_to_gdb_ext(size_t sub_id,
size_t def_id,
openfpm::vector<GBoxes<dim>> & gdb_ext,
openfpm::vector<size_t> & gdb_ext_markers)
{
size_t start = gdb_ext_markers.get(sub_id);
size_t stop = gdb_ext_markers.get(sub_id+1);
return get_gdb_ext(gdb_ext,start,stop,def_id);
}
/*! \brief It store the information about the local external ghost box
*
*
*/
template <unsigned int dim> struct e_lbox_id
{
//! Box defining the external ghost box in local coordinates
::Box<dim,long int> ebox;
//! Has this external ghost box initialized
bool initialized = false;
//! sub-domain id of the non-extended sub-domain
size_t sub;
//! to which gdb_ext this external ghost box is linked with
//! (in case of grid defined everywhere these two number match)
size_t sub_gdb_ext;
//! external ghost box linked to this internal ghost box
size_t k;
//! Sector position of the local external ghost box
comb<dim> cmb;
};
/*! \brief Add a local external ghost box
*
* \param le_sub sub-domain id
* \param s id of the external ghost box
* \param j id of the domain not expanded
* \param k id of the grid (gdb_ext) this external ghost box is linked with
* \param bid where to add the local external ghost box
* \param box the box to add
* \param cmb quadrant in which the external ghost box live
*
*/
template<unsigned int dim> inline void add_loc_eg_box(size_t le_sub,
size_t se,
size_t j,
size_t k,
openfpm::vector<e_lbox_id<dim>> & bid,
const Box<dim,long int> & ebox,
comb<dim> & cmb)
{
bid.add();
bid.last().ebox = ebox;
bid.last().sub = se;
bid.last().sub_gdb_ext = k;
bid.last().cmb = cmb;
bid.last().k = j;
bid.last().initialized = true;
}
/*! Add an entry of for an external ghost box
*
* \param k sub-domain id to which this external ghost box is linked
* \param cmb quadrant where the received linked internal ghost box live
* \param output external ghost box
* \param g_id global id of the external ghost box, in general this id is communicated
* by the processor that has the linked internal ghost-box
* \param origin domain where this external ghost box is linked
* \param p1 origin of the received internal ghost box
*
*/
template<unsigned int dim> inline void add_eg_box(size_t k,
const comb<dim> & cmb,
const Box<dim,long int> & output,
size_t g_id,
const Point<dim,long int> & origin,
const Point<dim,long int> & p1,
openfpm::vector<e_box_id<dim>> & bid)
{
// link
size_t sub_id = k;
e_box_id<dim> bid_t;
bid_t.sub = sub_id;
bid_t.cmb = cmb;
bid_t.cmb.sign_flip();
::Box<dim,long int> ib = output;
bid_t.g_e_box = ib;
bid_t.g_id = g_id;
// Translate in local coordinate for gdb_ext
Box<dim,long int> tb = ib;
tb -= origin;
bid_t.l_e_box = tb;
// Translate in local coordinates for the received box
Box<dim,long int> tbr = ib;
bid_t.lr_e_box = tbr;
bid.add(bid_t);
}
/*! \brief Result of the itersection of a box with an array of boxes
*
*
*/
template<unsigned int dim>
struct result_box
{
//! id of the box in the array that produced an non-empty intersection
size_t id;
//! valid result of the itersection
Box<dim,long int> bx;
};
/*! \brief Intersect a box with an array of boxes
*
* \param bx_def array of boxes
* \param bx box to intersect with
* \param use_bx_def in case of false the box bx is added to the result array
* and nothing is performed
* \param result results of the intersections
*
*/
template<unsigned int dim>
void bx_intersect(openfpm::vector<Box<dim,long int>> & bx_def,
bool use_bx_def,
Box<dim,long int> & bx,
openfpm::vector_std<result_box<dim>> & result)
{
result.clear();
if (use_bx_def == false)
{
result_box<dim> tmp;
tmp.bx = bx;
tmp.id = 0;
result.add(tmp);
return;
}
for (size_t i = 0 ; i < bx_def.size() ; i++)
{
result_box<dim> inte;
if (bx.Intersect(bx_def.get(i),inte.bx))
{
inte.id = i;
result.add(inte);
}
}
}
/*! \brief it store a box, its unique id and the sub-domain from where it come from
*
*/
template<unsigned int dim> struct i_box_id
{
//! Box
::Box<dim,long int> box;
//! id
size_t g_id;
//! r_sub id of the sub-domain in the sent list
size_t r_sub;
//! Sector where it live the linked external ghost box
comb<dim> cmb;
//! sub
size_t sub;
};
/*! \brief set of internal ghost box to send
*
*
*/
template<unsigned int dim>
struct ibox_send
{
//! global id
size_t gid;
//! internal ghost box
Box<dim,long int> ibox;
};
/*! \brief it store an internal ghost box, the linked external ghost box and the sub-domain from where
* it come from as internal ghost box
*
*/
template<unsigned int dim> struct i_lbox_id
{
//! Box
::Box<dim,long int> box;
//! sub-domain id (of the extended sub-domain).
//! sub and sub_gdb_ext match if use_bx_def is not used in the
//! distributed grid
size_t sub;
//! to which gdb_ext this internal ghost box is linked with
size_t sub_gdb_ext;
//! external ghost box linked to this internal ghost box
openfpm::vector<size_t> k;
//! combination
comb<dim> cmb;
};
/*! \brief For each external ghost id, it contain a set of sub-domain at which this
* external box is linked
*
*
*/
template<unsigned int dim>
struct e_box_multi
{
//! set sub-domain at which with external ghost is linked
//! The eb_list are id for the eb_box list
openfpm::vector<size_t> eb_list;
//! This is the id in eb_list that contain an external ghost box
//! able to store the full received box
size_t full_match;
//! It store the id of linked eg_box (eg_box.get(e_id) is valid, this mean that e_id store processor id information)
//! \see ProctoID function
size_t e_id;
};
/*! \brief Per-processor Internal ghost box
*
*/
template <unsigned int dim> struct ip_box_grid
{
// ghost in grid units
openfpm::vector<i_box_id<dim>> bid;
//! processor id
size_t prc;
};
/*! \brief local Internal ghost box
*
*/
template <unsigned int dim> struct i_lbox_grid
{
// ghost in grid units
openfpm::vector<i_lbox_id<dim>> bid;
};
/*! \brief Per-processor external ghost box
*
*/
template <unsigned int dim>struct ep_box_grid
{
// ghost in grid units
openfpm::vector<e_box_id<dim>> bid;
//! processor id
size_t prc;
//! total number of received points
size_t recv_pnt;
//! Number of received boxes
size_t n_r_box;
};
/*! \brief Per-processor external ghost box
*
*/
template <unsigned int dim> struct e_lbox_grid
{
// ghost in grid units
openfpm::vector<e_lbox_id<dim>> bid;
};
#endif /* SRC_GRID_GRID_DIST_UTIL_HPP_ */