Commit 7f66938e authored by Pietro Incardona's avatar Pietro Incardona

Adding peridioc boundary

parent 9b5483e7
openfpm_data @ fb93d170
Subproject commit 035b35bad815ff563b1f51b8192bc8abddee3a4c
Subproject commit fb93d17019fdfb1f7c65c463143f5100d506d6d2
openfpm_io @ c54eca6e
Subproject commit 9154ba930b68bd58a065f1809b037e0a2320c2c8
Subproject commit c54eca6ee2e0bbfefda778df50b369ce9a90323f
openfpm_numerics @ 7be65314
Subproject commit 3385f02c21b9eca9daa9ab8373ede437f7fb4b6b
Subproject commit 7be6531420de26986cd584e3bec0f5ee51afdef1
......@@ -1407,7 +1407,7 @@ FORMULA_TRANSPARENT = YES
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = NO
USE_MATHJAX = YES
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:
......
openfpm_vcluster @ d052b0d7
Subproject commit 10e84f95e72148824815cbb50040b10b3ee61ecf
Subproject commit d052b0d75a49835b24419cc4938485d6dc514393
......@@ -133,15 +133,18 @@ private:
// reference counter of the object in case is shared between object
long int ref_cnt;
// Save the ghost boundaries
// ghost info
Ghost<dim,T> ghost;
// Boundary condition info
size_t bc[dim];
/*! \brief Constructor, it decompose and distribute the sub-domains across the processors
*
* \param v_cl Virtual cluster, used internally for communications
*
*/
void CreateDecomposition(Vcluster & v_cl)
void CreateDecomposition(Vcluster & v_cl, const size_t (& bc)[dim])
{
#ifdef SE_CLASS1
if (&v_cl == NULL)
......@@ -165,8 +168,13 @@ private:
// Create a cartesian grid graph
CartesianGraphFactory<dim,Graph_CSR<nm_part_v,nm_part_e>> g_factory_part;
// the graph has only non perdiodic boundary conditions
size_t bc_o[dim];
for (size_t i = 0 ; i < dim ; i++)
bc_o[i] = NON_PERIODIC;
// sub-sub-domain graph
Graph_CSR<nm_part_v,nm_part_e> gp = g_factory_part.template construct<NO_EDGE,T,dim-1>(gr.getSize(),domain);
Graph_CSR<nm_part_v,nm_part_e> gp = g_factory_part.template construct<NO_EDGE,T,dim-1>(gr.getSize(),domain,bc_o);
// Get the number of processing units
size_t Np = v_cl.getProcessingUnits();
......@@ -191,7 +199,7 @@ private:
openfpm::vector<::Box<dim,size_t>> loc_box;
// optimize the decomposition
d_o.template optimize<nm_part_v::sub_id,nm_part_v::id>(gp,p_id,loc_box,box_nn_processor);
d_o.template optimize<nm_part_v::sub_id,nm_part_v::id>(gp,p_id,loc_box,box_nn_processor,bc);
// Initialize ss_box and bbox
if (loc_box.size() >= 0)
......@@ -257,6 +265,7 @@ private:
nn_prcs<dim,T>::create(box_nn_processor, sub_domains);
nn_prcs<dim,T>::refine_ss_box(ss_box);
nn_prcs<dim,T>::applyBC(domain,ghost,bc);
// fill fine_s structure
// fine_s structure contain the processor id for each sub-sub-domain
......@@ -614,6 +623,7 @@ p1[0]<-----+ +----> p2[0]
cart.ghost = g;
nn_prcs<dim,T>::create(box_nn_processor, sub_domains);
nn_prcs<dim,T>::applyBC(domain,ghost,bc);
calculateGhostBoxes();
Initialize_geo_cell_lists();
......@@ -764,8 +774,12 @@ p1[0]<-----+ +----> p2[0]
* \param domain_ domain to decompose
*
*/
void setParameters(const size_t (& div_)[dim], Domain<dim,T> domain_, Ghost<dim,T> ghost = Ghost<dim,T>())
void setParameters(const size_t (& div_)[dim], Domain<dim,T> domain_, const size_t (& bc)[dim] ,Ghost<dim,T> ghost = Ghost<dim,T>())
{
// set the boundary conditions
for (size_t i = 0 ; i < dim ; i++)
this->bc[i] = bc[i];
// set the ghost
this->ghost = ghost;
// Set the decomposition parameters
......@@ -776,7 +790,7 @@ p1[0]<-----+ +----> p2[0]
//! Create the decomposition
CreateDecomposition(v_cl);
CreateDecomposition(v_cl,bc);
}
/*! \brief Get the number of local sub-domains
......
......@@ -8,7 +8,7 @@ BOOST_AUTO_TEST_SUITE( CartDecomposition_test )
#define SUB_UNIT_FACTOR 64
BOOST_AUTO_TEST_CASE( CartDecomposition_test_use)
BOOST_AUTO_TEST_CASE( CartDecomposition_non_periodic_test)
{
// Vcluster
Vcluster & vcl = *global_v_cluster;
......@@ -35,8 +35,111 @@ BOOST_AUTO_TEST_CASE( CartDecomposition_test_use)
// Define ghost
Ghost<3,float> g(0.01);
// Boundary conditions
size_t bc[] = {NON_PERIODIC,NON_PERIODIC,NON_PERIODIC};
// Decompose
dec.setParameters(div,box,bc,g);
// create a ghost border
dec.calculateGhostBoxes();
//! [Create CartDecomposition]
// For each calculated ghost box
for (size_t i = 0 ; i < dec.getNIGhostBox() ; i++)
{
SpaceBox<3,float> b = dec.getIGhostBox(i);
size_t proc = dec.getIGhostBoxProcessor(i);
// sample one point inside the box
Point<3,float> p = b.rnd();
// Check that ghost_processorsID return that processor number
const openfpm::vector<size_t> & pr = dec.template ghost_processorID<CartDecomposition<3,float>::processor_id>(p);
bool found = false;
for (size_t j = 0; j < pr.size() ; j++)
{
if (pr.get(j) == proc)
{found = true; break;}
}
if (found == false)
{
const openfpm::vector<size_t> pr2 = dec.template ghost_processorID<CartDecomposition<3,float>::processor_id>(p);
}
BOOST_REQUIRE_EQUAL(found,true);
}
// Check the consistency
bool val = dec.check_consistency();
BOOST_REQUIRE_EQUAL(val,true);
// We duplicate the decomposition
CartDecomposition<3,float> dec2 = dec.duplicate();
dec2.check_consistency();
bool ret = dec.is_equal(dec2);
// We check if the two decomposition are equal
BOOST_REQUIRE_EQUAL(ret,true);
// check that dec and dec2 contain the same information
// We duplicate the decomposition redefining the ghost
// Define ghost
Ghost<3,float> g3(0.005);
// We duplicate the decomposition refefining the ghost
CartDecomposition<3,float> dec3 = dec.duplicate(g3);
ret = dec3.check_consistency();
BOOST_REQUIRE_EQUAL(ret,true);
// Check that g3 is equal to dec2 with the exception of the ghost part
ret = dec3.is_equal_ng(dec2);
BOOST_REQUIRE_EQUAL(ret,true);
}
BOOST_AUTO_TEST_CASE( CartDecomposition_periodic_test)
{
// Vcluster
Vcluster & vcl = *global_v_cluster;
// Initialize the global VCluster
init_global_v_cluster(&boost::unit_test::framework::master_test_suite().argc,&boost::unit_test::framework::master_test_suite().argv);
//! [Create CartDecomposition]
CartDecomposition<3,float> dec(vcl);
// Physical domain
Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0});
size_t div[3];
// Get the number of processor and calculate the number of sub-domain
// for each processor (SUB_UNIT_FACTOR=64)
size_t n_proc = vcl.getProcessingUnits();
size_t n_sub = n_proc * SUB_UNIT_FACTOR;
// Set the number of sub-domains on each dimension (in a scalable way)
for (int i = 0 ; i < 3 ; i++)
{div[i] = openfpm::math::round_big_2(pow(n_sub,1.0/3));}
// Define ghost
Ghost<3,float> g(0.01);
// Boundary conditions
size_t bc[] = {PERIODIC,PERIODIC,PERIODIC};
// Decompose
dec.setParameters(div,box,g);
dec.setParameters(div,box,bc,g);
// create a ghost border
dec.calculateGhostBoxes();
......
......@@ -129,7 +129,7 @@ struct N_box
// id of the processor in the nn_processor list (local processor id)
size_t id;
// Near processor sub-domains
// adjacent processor sub-domains
typename openfpm::vector<::Box<dim,T>> bx;
//! Default constructor
......
......@@ -57,8 +57,8 @@ protected:
/*! \brief Create the box_nn_processor_int (bx part) structure
*
* This structure store for each sub-domain of this processors enlarged by the ghost size the boxes that
* come from the intersection with the near processors sub-domains (External ghost box)
* For each sub-domain of the local processor it store the intersection between the enlarged
* sub-domain of the calling processor with the adjacent processors sub-domains (External ghost box)
*
* \param ghost margins
*
......@@ -85,19 +85,19 @@ protected:
// For each processor adjacent to this sub-domain
for (size_t j = 0 ; j < box_nn_processor.get(i).size() ; j++)
{
// Contiguous processor
// adjacent processor
size_t p_id = box_nn_processor.get(i).get(j);
// store the box in proc_int_box storing from which sub-domain they come from
// used later
Box_dom<dim,T> & proc_int_box_g = proc_int_box.get(nn_p.ProctoID(p_id));
// get the set of sub-domains of the adjacent processor p_id
const openfpm::vector< ::Box<dim,T> > & nn_processor_subdomains_g = nn_p.getExternalAdjSubdomain(p_id).bx;
// near processor sub-domain intersections
// used later
openfpm::vector< ::Box<dim,T> > & box_nn_processor_int_gg = box_nn_processor_int.get(i).get(j).bx;
// for each near processor sub-domain intersect with the enlarged local sub-domain and store it
// for each adjacent processor sub-domain intersect with the enlarged local sub-domain and store it
for (size_t b = 0 ; b < nn_processor_subdomains_g.size() ; b++)
{
::Box<dim,T> bi;
......@@ -626,6 +626,8 @@ public:
return false;
}
}
return true;
}
/*! \brief Check if the ie_loc_ghosts contain the same information with the exception of the ghost part
......
......@@ -9,6 +9,7 @@
#define SRC_DECOMPOSITION_NN_PROCESSOR_HPP_
#include "common.hpp"
#include <unordered_map>
/*! \brief This class store the adjacent processors and the adjacent sub_domains
*
......@@ -27,10 +28,14 @@ class nn_prcs
//! List of adjacent processors
openfpm::vector<size_t> nn_processors;
// for each near-processor store the sub-domain of the near processor
// for each adjacent processor store the sub-domains of the adjacent processor
std::unordered_map<size_t, N_box<dim,T>> nn_processor_subdomains;
// for each processor store the set of the sub-domains sent to the adjacent processors
// when we add new boxes, are added here
std::unordered_map<size_t, N_box<dim,T>> nn_processor_subdomains_tmp;
// for each near processor store the set of the sub-domains sent to the near processors,
// the nested vector contain the id of the local sub-domain
openfpm::vector<openfpm::vector<size_t>> proc_adj_box;
//! contain the internal adjacent sub-domains sent to the other processors
......@@ -39,6 +44,9 @@ class nn_prcs
// Receive counter
size_t recv_cnt;
//! applyBC function is suppose to be called only one time
bool aBC;
/*! \brief Message allocation
*
* \param message size required to receive from i
......@@ -64,21 +72,139 @@ class nn_prcs
return cd->nn_processor_subdomains[i].bx.getPointer();
}
/*! Checl that the compination is valid
*
* \param cmb combination
* \param bc boundary conditions
*
*/
bool inline check_valid(comb<dim> cmb,const size_t (& bc)[dim])
{
for (size_t i = 0 ; i < dim ; i++)
{
if (bc[i] == NON_PERIODIC && cmb.getComb()[i] != 0)
return false;
}
return true;
}
/*! \brief add sub-domain to processor
*
* \param i processor
* \param bx Box to add
*
*/
inline void add_nn_subdomain(size_t i, const Box<dim,T> & bx)
{
nn_processor_subdomains_tmp[i].bx.add(bx);
}
/*! \brief In case of periodic boundary conditions we have to add boxes
* at the borders
*
* \param domain Domain box
* \param boundary boundary conditions
* \param ghost ghost part
*
*/
void add_box_periodic(const Box<dim,T> & domain, const Ghost<dim,T> & ghost, const size_t (&bc)[dim])
{
HyperCube<dim> hyp;
// first we create boxes at the border of the domain used to detect the sub-domain
// that must be adjusted, each of this boxes define a shift in case of periodic boundary condition
for (long int i = dim-1 ; i >= 0 ; i--)
{
std::vector<comb<dim>> cmbs = hyp.getCombinations_R(i);
for (size_t j = 0 ; j < cmbs.size() ; j++)
{
if (check_valid(cmbs[j],bc) == false)
continue;
Box<dim,T> bp;
Point<dim,T> shift;
for (size_t k = 0 ; k < dim ; k++)
{
switch (cmbs[j][k])
{
case 1:
bp.setLow(k,domain.getHigh(k)+ghost.getLow(k));
bp.setHigh(k,domain.getHigh(k));
shift.get(k) = -domain.getHigh(k);
break;
case 0:
bp.setLow(k,domain.getLow(k));
bp.setHigh(k,domain.getHigh(k));
shift.get(k) = 0;
break;
case -1:
bp.setLow(k,domain.getLow(k));
bp.setHigh(k,ghost.getHigh(k));
shift.get(k) = domain.getHigh(k);
break;
}
}
// Detect all the sub-domain involved, shift them and add to the list
// Detection is performed intersecting the sub-domains with the ghost
// parts near the domain borders
for (size_t k = 0 ; k < getNNProcessors() ; k++)
{
// sub-domains of the near processor
const openfpm::vector< ::Box<dim,T> > & nn_sub = getAdjacentSubdomains(IDtoProc(k));
for (size_t l = 0 ; l < nn_sub.size(); l++)
{
Box<dim,T> sub = nn_sub.get(l);
Box<dim,T> b_int;
if (sub.Intersect(bp,b_int) == true)
{
sub += shift;
add_nn_subdomain(IDtoProc(k),sub);
}
}
}
}
}
flush();
}
/*! \brief Flush the temporal added sub-domain to the processor sub-domain
*
*
*/
void flush()
{
for ( auto it = nn_processor_subdomains_tmp.begin(); it != nn_processor_subdomains_tmp.end(); ++it )
{
const N_box<dim,T> & nnp_bx = it->second;
for (size_t i = 0 ; i < nnp_bx.bx.size() ; i++)
{
nn_processor_subdomains[it->first].bx.add(nn_processor_subdomains_tmp[it->first].bx.get(i));
}
}
}
public:
nn_prcs(Vcluster & v_cl)
:v_cl(v_cl){}
:v_cl(v_cl),aBC(false){}
//! Constructor from another ie_loc_ghost
//! Constructor from another nn_prcs
nn_prcs(const nn_prcs<dim,T> & ilg)
:v_cl(ilg.v_cl)
:v_cl(ilg.v_cl),aBC(false)
{
this->operator=(ilg);
};
//! Constructor from temporal ie_loc_ghost
nn_prcs(nn_prcs<dim,T> && ilg)
:v_cl(ilg.v_cl)
:v_cl(ilg.v_cl),aBC(false)
{
this->operator=(ilg);
}
......@@ -139,8 +265,7 @@ public:
*/
void create(const openfpm::vector<openfpm::vector<long unsigned int> > & box_nn_processor, const openfpm::vector<SpaceBox<dim,T>> & sub_domains)
{
// produce the list of the contiguous processor (nn_processors) and link nn_processor_subdomains to the
// processor list
// produce the list of the adjacent processor (nn_processors) list
for (size_t i = 0 ; i < box_nn_processor.size() ; i++)
{
for (size_t j = 0 ; j < box_nn_processor.get(i).size() ; j++)
......@@ -154,13 +279,12 @@ public:
auto last = std::unique(nn_processors.begin(), nn_processors.end());
nn_processors.erase(last, nn_processors.end());
// produce the list of the contiguous processor (nn_processors) and link nn_processor_subdomains to the
// processor list (nn_processors)
// construct nn_processor_subdomains
for (size_t i = 0 ; i < box_nn_processor.size() ; i++)
{
for (size_t j = 0 ; j < box_nn_processor.get(i).size() ; j++)
{
// processor id near to this sub-domain
// processor id adjacent to this sub-domain
size_t proc_id = box_nn_processor.get(i).get(j);
size_t k = 0;
......@@ -173,10 +297,8 @@ public:
}
// create a buffer with the sub-domains of this processor, the informations ( the boxes )
// of the sub-domains contiguous to the processor A are sent to the processor A and
// the information of the contiguous sub-domains in the near processors are received
//
// create a buffer with the sub-domains of this processor, send them to the adjacent
// processor
proc_adj_box.resize(getNNProcessors());
boxes.resize(nn_processors.size());
......@@ -195,12 +317,8 @@ public:
}
}
// Intersect all the local sub-domains with the sub-domains of the contiguous processors
// Get the sub-domains of the near processors
v_cl.sendrecvMultipleMessagesNBX(nn_processors,boxes,nn_prcs<dim,T>::message_alloc, this ,NEED_ALL_SIZE);
}
/*! \brief Get the number of Near processors
......@@ -227,12 +345,12 @@ public:
/*! \brief Get the sub-domain pf an adjacent processor
*
* \param p_id adjacent processor (id from 0 to getNNProcessors())
* \param p_id adjacent processor rank
*
* \return the sub-domains
*
*/
inline const openfpm::vector< ::Box<dim,T> > & getAdjacentSubdomain(size_t p_id) const
inline const openfpm::vector< ::Box<dim,T> > & getAdjacentSubdomains(size_t p_id) const
{
auto key = nn_processor_subdomains.find(p_id);
#ifdef SE_CLASS1
......@@ -246,7 +364,7 @@ public:
/*! \brief Get the adjacent processor id
*
* \param p_id adjacent processor (id from 0 to getNNProcessors())
* \param p_id adjacent processor rank
*
* \return the processor rank
*
......@@ -342,6 +460,26 @@ public:
return true;
}
/*! \brief Apply boundary conditions
*
* \param domain The simulation domain
* \param ghost ghost part
* \param bc Boundary conditions
*
*/
void applyBC(const Box<dim,T> & domain, const Ghost<dim,T> & ghost, const size_t (&bc)[dim])
{
if (aBC == true)
{
std::cerr << "Warning " << __FILE__ << ":" << __LINE__ << "Apply BC is suppose to be called only one time\n";
return;
}
aBC=true;
return add_box_periodic(domain,ghost,bc);
}
/*! \brief Check if the nn_prcs contain the same information
*
* \param ele Element to check
......@@ -354,7 +492,7 @@ public:
for (size_t p = 0 ; p < getNNProcessors() ; p++)
{
if (getAdjacentSubdomain(IDtoProc(p)) != np.getAdjacentSubdomain(IDtoProc(p)))
if (getAdjacentSubdomains(IDtoProc(p)) != np.getAdjacentSubdomains(IDtoProc(p)))
return false;
if (getAdjacentProcessor(IDtoProc(p)) != np.getAdjacentProcessor(IDtoProc(p)))
return false;
......@@ -366,6 +504,18 @@ public:
return true;
}
//! Used for testing porpose do not use
std::unordered_map<size_t, N_box<dim,T>> & get_nn_processor_subdomains()
{
return nn_processor_subdomains;
}
//! Used for testing porpose do not use
openfpm::vector<size_t> & get_nn_processors()
{
return nn_processors;
}
};
......
......@@ -14,6 +14,7 @@
#include "Space/Shape/Box.hpp"
#include "Space/Shape/HyperCube.hpp"
/*! \brief This class work as a functor
*
* For each number in the boost::mpl::vector (for example 3 6) set the properties of the vertex at the
......@@ -84,7 +85,7 @@ class Graph_constructor_impl
{
public:
//! Construct cartesian graph
static Graph construct(const size_t (& sz)[dim], Box<dim,T> dom)
static Graph construct(const size_t (& sz)[dim], Box<dim,T> dom, const size_t(& bc)[dim])
{
// Calculate the size of the hyper-cubes on each dimension
......@@ -162,7 +163,7 @@ public:
// Calculate the start point id
size_t start_v = g.LinId(key);
size_t end_v = g.template LinId<CheckExistence>(key,c[j].getComb());
size_t end_v = g.template LinId<CheckExistence>(key,c[j].getComb(),bc);
// Add an edge and set the the edge property to the size of the face (communication weight)
gp.template addEdge<CheckExistence>(start_v,end_v).template get<se>() = ele_sz;
......@@ -171,8 +172,6 @@ public:
// Fill vertex properties
++k_it;
}
......@@ -194,7 +193,7 @@ class Graph_constructor_impl<dim,Graph,NO_EDGE,T,dim_c,pos...>
{
public:
//! Construct cartesian graph
static Graph construct(const size_t ( & sz)[dim], Box<dim,T> dom)
static Graph construct(const size_t ( & sz)[dim], Box<dim,T> dom, const size_t(& bc)[dim])
{
// Calculate the size of the hyper-cubes on each dimension
......@@ -259,20 +258,20 @@ public:
{
// Calculate the element size
T ele_sz = 0;
// T ele_sz = 0;
// for each dimension multiply and reduce
for