From a9c90bb010ea40bccbd07d155ca23ef9a32880a6 Mon Sep 17 00:00:00 2001 From: Pietro Incardona <incardon@mpi-cbg.de> Date: Sun, 9 Aug 2015 19:29:05 +0200 Subject: [PATCH] Adding refactored files --- src/Decomposition/ie_ghost.hpp | 244 +++++++++++++++++++++++++++++ src/Decomposition/nn_processor.hpp | 226 ++++++++++++++++++++++++++ 2 files changed, 470 insertions(+) create mode 100644 src/Decomposition/ie_ghost.hpp create mode 100644 src/Decomposition/nn_processor.hpp diff --git a/src/Decomposition/ie_ghost.hpp b/src/Decomposition/ie_ghost.hpp new file mode 100644 index 00000000..76e9eb50 --- /dev/null +++ b/src/Decomposition/ie_ghost.hpp @@ -0,0 +1,244 @@ +/* + * ie_ghost.hpp + * + * Created on: Aug 8, 2015 + * Author: i-bird + */ + +#ifndef SRC_DECOMPOSITION_IE_GHOST_HPP_ +#define SRC_DECOMPOSITION_IE_GHOST_HPP_ + +#include "common.hpp" + +/*! \brief structure that store and compute the internal and external local ghost box + * + * \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 ... + * + * \see CartDecomposition + * + */ +template<unsigned int dim, typename T> +class ie_ghost +{ + //! for each sub-domain (first vector), contain the list (nested vector) of the neighborhood processors + //! and for each processor contain the boxes calculated from the intersection + //! of the sub-domains + ghost with the near-by processor sub-domain () and the other way around + //! \see calculateGhostBoxes + openfpm::vector< openfpm::vector< Box_proc<dim,T> > > box_nn_processor_int; + + //! It store the same information of box_nn_processor_int organized by processor id + openfpm::vector< Box_dom<dim,T> > proc_int_box; + + /*! \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) + * + * \param ghost margins + * + * \note Are the G8_0 G9_0 G9_1 G5_0 boxes in calculateGhostBoxes + * \see calculateGhostBoxes + * + */ + void create_box_nn_processor_ext(Ghost<dim,T> & ghost, openfpm::vector<SpaceBox<dim,T>> & sub_domains) + { +/* box_nn_processor_int.resize(sub_domains.size()); + proc_int_box.resize(getNNProcessors()); + + // For each sub-domain + for (size_t i = 0 ; i < sub_domains.size() ; i++) + { + SpaceBox<dim,T> sub_with_ghost = sub_domains.get(i); + + // enlarge the sub-domain with the ghost + sub_with_ghost.enlarge(ghost); + + // resize based on the number of adjacent processors + box_nn_processor_int.get(i).resize(box_nn_processor.get(i).size()); + + // For each processor adjacent to this sub-domain + for (size_t j = 0 ; j < box_nn_processor.get(i).size() ; j++) + { + // Contiguous 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 + Box_dom & proc_int_box_g = proc_int_box.get(ProctoID(p_id)); + + // get the set of sub-domains of the adjacent processor p_id + openfpm::vector< ::Box<dim,T> > & nn_processor_subdomains_g = nn_processor_subdomains[p_id].bx; + + // near processor sub-domain intersections + 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 (size_t b = 0 ; b < nn_processor_subdomains_g.size() ; b++) + { + ::Box<dim,T> bi; + + bool intersect = sub_with_ghost.Intersect(::Box<dim,T>(nn_processor_subdomains_g.get(b)),bi); + + if (intersect == true) + { + struct p_box pb; + + pb.box = bi; + pb.proc = p_id; + pb.lc_proc = ProctoID(p_id); + + // + // Updating + // + // vb_ext + // box_nn_processor_int + // proc_int_box + // + // They all store the same information but organized in different ways + // read the description of each for more information + // + vb_ext.add(pb); + box_nn_processor_int_gg.add(bi); + proc_int_box_g.ebx.add(); + proc_int_box_g.ebx.last() = bi; + proc_int_box_g.ebx.last().sub = i; + + // Search for the correct id + size_t k = 0; + size_t p_idp = ProctoID(p_id); + for (k = 0 ; k < proc_adj_box.get(p_idp).size() ; k++) + { + if (proc_adj_box.get(p_idp).get(k) == i) + break; + } + if (k == proc_adj_box.get(p_idp).size()) + std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " sub-domain not found\n"; + + proc_int_box_g.ebx.last().id = (k * nn_processor_subdomains_g.size() + b) * v_cl.getProcessingUnits() + p_id; + } + } + } + }*/ + } + + /*! \brief Create the box_nn_processor_int (nbx part) structure, the geo_cell list and proc_int_box + * + * This structure store for each sub-domain of this processors the boxes that come from the intersection + * of the near processors sub-domains enlarged by the ghost size (Internal ghost box). These boxes + * fill a geometrical cell list. The proc_int_box store the same information ordered by near processors + * + * \param ghost margins + * + * \note Are the B8_0 B9_0 B9_1 B5_0 boxes in calculateGhostBoxes + * \see calculateGhostBoxes + * + */ + void create_box_nn_processor_int(Ghost<dim,T> & ghost, openfpm::vector<SpaceBox<dim,T>> & sub_domains, const openfpm::vector<openfpm::vector<long unsigned int> > & box_nn_processors, const nn_prcs<dim,T> & nn_p ) + { + box_nn_processor_int.resize(sub_domains.size()); + proc_int_box.resize(nn_p.getNNProcessors()); + + // For each sub-domain + for (size_t i = 0 ; i < sub_domains.size() ; i++) + { + // For each processor contiguous to this sub-domain + for (size_t j = 0 ; j < box_nn_processor.get(i).size() ; j++) + { + // Contiguous processor + size_t p_id = box_nn_processor.get(i).get(j); + + // get the set of sub-domains of the contiguous processor p_id + openfpm::vector< ::Box<dim,T> > & nn_p_box = nn_p.get nn_processor_subdomains[p_id].bx; + + // get the local processor id + size_t lc_proc = nn_processor_subdomains[p_id].id; + + // For each near processor sub-domains enlarge and intersect with the local sub-domain and store the result + for (size_t k = 0 ; k < nn_p_box.size() ; k++) + { + + // enlarge the near-processor sub-domain + ::Box<dim,T> n_sub = nn_p_box.get(k); + + // local sub-domain + ::SpaceBox<dim,T> l_sub = sub_domains.get(i); + + // Create a margin of ghost size around the near processor sub-domain + n_sub.enlarge(ghost); + + // Intersect with the local sub-domain + p_box b_int; + bool intersect = n_sub.Intersect(l_sub,b_int.box); + + // store if it intersect + if (intersect == true) + { + // the box fill with the processor id + b_int.proc = p_id; + + // fill the local processor id + b_int.lc_proc = lc_proc; + + // + // Updating + // + // vb_int + // box_nn_processor_int + // proc_int_box + // + // They all store the same information but organized in different ways + // read the description of each for more information + // + + // add the box to the near processor sub-domain intersections + openfpm::vector< ::Box<dim,T> > & p_box_int = box_nn_processor_int.get(i).get(j).nbx; + p_box_int.add(b_int.box); + vb_int.add(b_int); + + // store the box in proc_int_box storing from which sub-domain they come from + Box_dom & pr_box_int = proc_int_box.get(ProctoID(p_id)); + Box_sub<dim,T> sb; + sb = b_int.box; + sb.sub = i; + + // Search for the correct id + size_t s = 0; + size_t p_idp = ProctoID(p_id); + for (s = 0 ; s < proc_adj_box.get(p_idp).size() ; s++) + { + if (proc_adj_box.get(p_idp).get(s) == i) + break; + } + if (s == proc_adj_box.get(p_idp).size()) + std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " sub-domain not found\n"; + + sb.id = (k * proc_adj_box.get(p_idp).size() + s) * v_cl.getProcessingUnits() + v_cl.getProcessUnitID(); + + pr_box_int.ibx.add(sb); + + // update the geo_cell list + + // get the cells this box span + const grid_key_dx<dim> p1 = geo_cell.getCellGrid(b_int.box.getP1()); + const grid_key_dx<dim> p2 = geo_cell.getCellGrid(b_int.box.getP2()); + + // Get the grid and the sub-iterator + auto & gi = geo_cell.getGrid(); + grid_key_dx_iterator_sub<dim> g_sub(gi,p1,p2); + + // add the box-id to the cell list + while (g_sub.isNext()) + { + auto key = g_sub.get(); + geo_cell.addCell(gi.LinId(key),vb_int.size()-1); + ++g_sub; + } + } + } + } + } + } +}; + + +#endif /* SRC_DECOMPOSITION_IE_GHOST_HPP_ */ diff --git a/src/Decomposition/nn_processor.hpp b/src/Decomposition/nn_processor.hpp new file mode 100644 index 00000000..b4328817 --- /dev/null +++ b/src/Decomposition/nn_processor.hpp @@ -0,0 +1,226 @@ +/* + * nn_processor.hpp + * + * Created on: Aug 9, 2015 + * Author: i-bird + */ + +#ifndef SRC_DECOMPOSITION_NN_PROCESSOR_HPP_ +#define SRC_DECOMPOSITION_NN_PROCESSOR_HPP_ + +#include "common.hpp" + +/*! \brief This class store the adjacent processors and the adjacent sub_domains + * + * \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 ... + * + * \see CartDecomposition + * + */ +template<unsigned int dim, typename T> +class nn_prcs +{ + //! Virtual cluster + Vcluster & v_cl; + + //! List of adjacent processors + openfpm::vector<size_t> nn_processors; + + // for each near-processor store the sub-domain of the near 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 + openfpm::vector<openfpm::vector<size_t>> proc_adj_box; + + //! contain the internal adjacent sub-domains sent to the other processors + openfpm::vector< openfpm::vector< ::SpaceBox<dim,T>> > boxes; + + // Receive counter + size_t recv_cnt; + + /*! \brief Message allocation + * + * \param message size required to receive from i + * \param total message size to receive from all the processors + * \param the total number of processor want to communicate with you + * \param i processor id + * \param ri request id (it is an id that goes from 0 to total_p, and is unique + * every time message_alloc is called) + * \param ptr a pointer to the vector_dist structure + * + * \return the pointer where to store the message + * + */ + static void * message_alloc(size_t msg_i ,size_t total_msg, size_t total_p, size_t i, size_t ri, void * ptr) + { + // cast the pointer + nn_prcs<dim,T> * cd = static_cast< nn_prcs<dim,T> *>(ptr); + + // Resize the memory + cd->nn_processor_subdomains[i].bx.resize(msg_i / sizeof(::Box<dim,T>) ); + + // Return the receive pointer + return cd->nn_processor_subdomains[i].bx.getPointer(); + } + +public: + + nn_prcs(Vcluster & v_cl) + :v_cl(v_cl){} + + /*! \brief Create the list of adjacent processors and the list of adjacent sub-domains + * + * \param box_nn_processors + * + */ + 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 + for (size_t i = 0 ; i < box_nn_processor.size() ; i++) + { + for (size_t j = 0 ; j < box_nn_processor.get(i).size() ; j++) + { + nn_processors.add(box_nn_processor.get(i).get(j)); + } + } + + // make the list sorted and unique + std::sort(nn_processors.begin(), nn_processors.end()); + auto last = std::unique(nn_processors.begin(), nn_processors.end()); + nn_processors.erase(last, nn_processors.end()); + + // 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 + // + proc_adj_box.resize(getNNProcessors()); + boxes.resize(nn_processors.size()); + + for (size_t b = 0 ; b < box_nn_processor.size() ; b++) + { + for (size_t p = 0 ; p < box_nn_processor.get(b).size() ; p++) + { + size_t prc = box_nn_processor.get(b).get(p); + + // id of the processor in the processor list + // [value between 0 and the number of the near processors] + size_t id = nn_processor_subdomains[prc].id; + + boxes.get(id).add(sub_domains.get(b)); + proc_adj_box.get(id).add(b); + } + } + + // 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 + * + * \return the number of near processors + * + */ + inline size_t getNNProcessors() const + { + return nn_processors.size(); + } + + /*! \brief Return the processor id of the near processor list at place id + * + * \param id + * + * \return return the processor rank + * + */ + inline size_t IDtoProc(size_t id) + { + return nn_processors.get(id); + } + + /*! \brief Get the sub-domain pf an adjacent processor + * + * \param p_id adjacent processor (id from 0 to getNNProcessors()) + * + * \return the sub-domains + * + */ + inline const openfpm::vector< ::Box<dim,T> > & getAdjacentSubdomain(size_t p_id) + { + return nn_processor_subdomains[p_id].bx; + } + + /*! \brief Get the adjacent processor id + * + * \param p_id adjacent processor (id from 0 to getNNProcessors()) + * + * \return the processor rank + * + */ + inline size_t getAdjacentProcessor(size_t p_id) + { + return nn_processor_subdomains[p_id].id; + } + + + /*! \brief Get the local sub-domains adjacent to a processor p_id + * + * \param p_id adjacent processor (id from 0 to getNNProcessors()) + * + * \return the sub-domains + * + */ + inline const openfpm::vector<size_t> & getInternalAdjSubdomain(size_t p_id) + { + return proc_adj_box.get(p_id); + } + + /*! \brief Convert the processor rank to the id in the list + * + * \param p processor rank + * + * \return the id + * + */ + inline size_t ProctoID(size_t p) + { + return nn_processor_subdomains[p].id; + } + + /*! \brief Write the decomposition as VTK file + * + * The function generate several files + * + * 1) subdomains_adjacent_X.vtk sub-domains adjacent to the local processor (X) + * + * where X is the local processor rank + * + * \param output directory where to write the files + * \param p_id id of the local processor + * + */ + bool write(std::string output) const + { + //! subdomains_adjacent_X.vtk sub-domains adjacent to the local processor (X) + VTKWriter<openfpm::vector<::Box<dim,T>>,VECTOR_BOX> vtk_box2; + for (size_t p = 0 ; p < nn_processors.size() ; p++) + { + size_t prc = nn_processors.get(p); + auto it = nn_processor_subdomains.find(prc); + if (it != nn_processor_subdomains.end()) + vtk_box2.add(nn_processor_subdomains.at(prc).bx); + } + vtk_box2.write(output + std::string("subdomains_adjacent_") + std::to_string(v_cl.getProcessUnitID()) + std::string(".vtk")); + + return true; + } + +}; + + +#endif /* SRC_DECOMPOSITION_NN_PROCESSOR_HPP_ */ -- GitLab