/* * CartDecomposition_ext.hpp * * Created on: Mar 6, 2016 * Author: i-bird */ #ifndef SRC_DECOMPOSITION_CARTDECOMPOSITION_EXT_HPP_ #define SRC_DECOMPOSITION_CARTDECOMPOSITION_EXT_HPP_ #include "memory/HeapMemory.hpp" #include "Decomposition/Distribution/ParMetisDistribution.hpp" #include "Space/Ghost.hpp" #include "Decomposition/nn_processor.hpp" template<unsigned int dim, typename T, typename Memory = HeapMemory, template<typename> class layout_base = memory_traits_lin, typename Distribution = ParMetisDistribution<dim, T>> class CartDecomposition; /** * \brief This class decompose a space into sub-sub-domains and distribute them across processors * * \tparam dim is the dimensionality of the physical domain we are going to decompose. * \tparam T type of the space we decompose, Real, Integer, Complex ... * \tparam Memory Memory factory used to allocate memory * \tparam Distribution type of distribution, can be ParMetisDistribution or MetisDistribution * * Most of the functionality is the same as CartDecomposition so refer to that class for more information * * The additional functionality is the possibility to produce an extended decomposition, in figure is * show what we mean with extended * * \see CartDecomposition * * * * ### Create a Cartesian decomposition object on a Box space, distribute, calculate internal and external ghost boxes * \snippet CartDecomposition_unit_test.hpp Create CartDecomposition * */ template<unsigned int dim, typename T, typename Memory = HeapMemory, template<typename> class layout_base = memory_traits_lin, typename Distribution = ParMetisDistribution<dim, T>> class CartDecomposition_ext: public CartDecomposition<dim,T,Memory,layout_base,Distribution> { private: /*! \brief It copy the sub-domains into another CartesianDecomposition object extending them * * \see duplicate (in case of extended domain) * * \param dec Cartesian decomposition object * \param ext_dom Extended domain * */ void extend_subdomains(const CartDecomposition<dim,T,Memory,layout_base,Distribution> & dec, const ::Box<dim,T> & ext_dom) { // Box typedef ::Box<dim,T> b; this->bbox.zero(); // Extend sub-domains for (size_t i = 0 ; i < dec.sub_domains.size() ; i++) { ::Box<dim,T> box; // Calculate the extended box for (size_t j = 0 ; j < dim ; j++) { if (dec.sub_domains.template get<b::p1>(i)[j] == dec.domain.getLow(j)) box.setLow(j,ext_dom.getLow(j)); else box.setLow(j,dec.sub_domains.template get<b::p1>(i)[j]); if (dec.sub_domains.template get<b::p2>(i)[j] == dec.domain.getHigh(j)) box.setHigh(j,ext_dom.getHigh(j)); else box.setHigh(j,dec.sub_domains.template get<b::p2>(i)[j]); } // add the subdomain this->sub_domains.add(box); // Calculate the bound box this->bbox.enclose(box); } } /*! \brief Extend the fines for the new Cartesian decomposition * * \param dec Non-extended decomposition * */ /* void extend_fines(const CartDecomposition<dim,T,Memory,Distribution> & dec) { // Extension, first we calculate the extensions of the new domain compared // to the old one in cell units (each cell unit is a sub-sub-domain) ::Box<dim,size_t> ext; // Extension of the new fines structure ::Box<dim,size_t> n_fines_ext; // Extension of the old fines structure ::Box<dim,size_t> o_fines_ext; size_t sz_new[dim]; size_t sz_old[dim]; for (size_t i = 0; i < dim ; i++) { size_t p1 = (dec.domain.getLow(i) - dec.domain.getLow(i)) / dec.cd.getCellBox().getHigh(i) + 1; size_t p2 = (dec.domain.getLow(i) - dec.domain.getLow(i)) / dec.cd.getCellBox().getHigh(i) + 1; ext.setLow(i,p1); ext.setHigh(i,p2); sz_new[i] = p1+p2+dec.cd.getGrid().size(i); sz_old[i] = dec.cd.getGrid().size(i); } grid_sm<dim,void> info_new(sz_new); grid_sm<dim,void> info_old(sz_old); // resize the new fines this->fine_s.resize(info_new.size()); // we create an iterator that iterate across the full new fines grid_key_dx_iterator<dim> fines_t(info_new); while (fines_t.isNext()) { auto key = fines_t.get(); // new_fines is bigger than old_fines structure // out of bound key must be adjusted // The adjustment produce a natural extension // a representation can be seen in the figure of // CartDecomposition duplicate function with extended domains grid_key_dx<dim> key_old; for (size_t i = 0 ; i < dim ; i++) { key_old.set_d(i,(long int)key.get(i) - ext.getLow(i)); if (key_old.get(i) < 0) key_old.set_d(i,0); else if(key_old.get(i) >= (long int)info_old.size(i) ) key_old.set_d(i,info_old.size(i)-1); } this->fine_s.get(info_new.LinId(key)) = dec.fine_s.get(info_old.LinId(key_old)); ++fines_t; } this->gr.setDimensions(sz_new); // the new extended CellDecomposer must be consistent with the old cellDecomposer. this->cd.setDimensions(dec.cd,ext); }*/ void reconstruct_fine_s_from_extended_domain(const ::Box<dim,T> & ext_domain) { this->initialize_fine_s(ext_domain); this->construct_fine_s(); } public: /*! \brief Cartesian decomposition constructor * * \param v_cl VCluster * */ CartDecomposition_ext(Vcluster<> & v_cl) :CartDecomposition<dim,T,Memory,layout_base,Distribution>(v_cl) { } //! The non-extended decomposition base class typedef CartDecomposition<dim,T,Memory,layout_base,Distribution> base_type; /*! \brief It create another object that contain the same decomposition information but with different ghost boxes and an extended domain * * The domain extension is produced extending the boxes at the border like in figure * * \verbatim * +--------------^--------^----------^----------+ | | | | | | A | E | F | N | | +-----------------------------------+----> | | | | | | | | A | A | | F | | | | | | | | | | | | | E +----------+ N | N | <--------------+ | | | | | | | | | | | | | | | G | | | | | | | +----------> | B | B | +----------+ | | | | +--------+ | M | M | | | | | H | | | | | | +-----+----+----------> <--------------+ D | | | | | | | | I | L | L | | C | C | | | | | | | | | | | | | +-----------------------------------+ | | | | | | | C | D | I | L | +--------------v--------v-----v---------------+ * * \endverbatim * * \param dec Decomposition * \param g ghost * \param ext_domain extended domain (MUST be extended) * * \return a duplicated decomposition with different ghost boxes and an extended domain * */ void setParameters(const CartDecomposition<dim,T,Memory,layout_base,Distribution> & dec, const Ghost<dim,T> & g, const ::Box<dim,T> & ext_domain) { // Set the decomposition parameters this->gr.setDimensions(dec.gr.getSize()); this->cd.setDimensions(ext_domain, dec.gr.getSize(), 0); this->box_nn_processor = dec.box_nn_processor; // Calculate new sub-domains for extended domain extend_subdomains(dec,ext_domain); // Calculate fine_s structure for the extended domain // update the cell decomposer and gr reconstruct_fine_s_from_extended_domain(ext_domain); // Get the old sub-sub-domain grid extension this->domain = ext_domain; // spacing does not change for (size_t i = 0 ; i < dim ; i++) {this->spacing[i] = dec.spacing[i];}; this->ghost = g; this->dist = dec.dist; for (size_t i = 0 ; i < dim ; i++) this->bc[i] = dec.bc[i]; (static_cast<nn_prcs<dim,T,layout_base,Memory> &>(*this)).create(this->box_nn_processor, this->sub_domains); (static_cast<nn_prcs<dim,T, layout_base,Memory> &>(*this)).applyBC(ext_domain,g,this->bc); this->Initialize_geo_cell_lists(); this->calculateGhostBoxes(); } }; #endif /* SRC_DECOMPOSITION_CARTDECOMPOSITION_EXT_HPP_ */