#ifndef MAP_HPP_ #define MAP_HPP_ #include "config.h" //! Warning: apparently you cannot used nested boost::mpl with boost::fusion //! can create template circularity, this include avoid the problem #include #include #include #include #include #include #include #include #include #include #include #include #include "memory_conf.hpp" #include "meta_copy.hpp" #include "Memleak_check.hpp" #include "for_each_ref.hpp" #include "grid_sm.hpp" #include "Encap.hpp" #include "memory_array.hpp" #include "memory_c.hpp" #include /*! \brief this class is a functor for "for_each" algorithm * * This class is a functor for "for_each" algorithm. For each * element of the boost::vector the operator() is called. * Is mainly used to copy one object into one target * grid element in a generic way for a * generic object T with variable number of property * * \param dim Dimensionality * \param S type of grid * */ template struct copy_cpu { //! size to allocate grid_key_dx & key; //! grid where we have to store the data S & grid_dst; //! type of the object we have to set typedef typename S::type obj_type; //! type of the object boost::sequence typedef typename S::type::type ov_seq; //! object we have to store obj_type & obj; /*! \brief constructor * * It define the copy parameters. * * \param key which element we are modifying * \param grid_src grid we are updating * \param obj object we have to set in grid_src * */ copy_cpu(grid_key_dx & key, S & grid_dst, obj_type & obj) :key(key),grid_dst(grid_dst),obj(obj){}; //! It call the copy function for each property template void operator()(T& t) const { // This is the type of the object we have to copy typedef typename boost::fusion::result_of::at_c::type copy_type; // Remove the reference from the type to copy typedef typename boost::remove_reference::type copy_rtype; meta_copy cp(boost::fusion::at_c(obj.data),grid_dst.template get(key)); } }; /*! \brief this class is a functor for "for_each" algorithm * * This class is a functor for "for_each" algorithm. For each * element of the boost::vector the operator() is called. * Is mainly used to copy one source grid element into one target * grid element in a generic way for an object T with variable * number of property * * \param dim Dimensionality * \param S grid type * */ template struct copy_cpu_sd { //! size to allocate grid_key_dx & key; //! Source grid const S & grid_src; //! Destination grid S & grid_dst; //! type of the object boost::sequence typedef typename S::type::type ov_seq; //! constructor copy_cpu_sd(grid_key_dx & key, const S grid_src, S grid_dst) :key(key),grid_src(grid_src),grid_dst(grid_dst){}; //! It call the copy function for each member template void operator()(T& t) const { // This is the type of the object we have to copy typedef typename boost::fusion::result_of::at_c::type copy_type; // Remove the reference from the type to copy typedef typename boost::remove_reference::type copy_rtype; meta_copy cp(grid_src.template get(key),grid_dst.template get(key)); } }; /*! \brief this class is a functor for "for_each" algorithm * * This class is a functor for "for_each" algorithm. For each * element of the boost::vector the operator() is called. * Is mainly used to copy one source grid element into one target * grid element in a generic way for an object T with variable * number of property * * \param dim Dimensionality * \param S grid type * */ template struct copy_cpu_sd_k { //! source key grid_key_dx & key_s; //! destination key grid_key_dx & key_d; //! Source grid const S & grid_src; //! Destination grid S & grid_dst; //! type of the object boost::sequence typedef typename S::type::type ov_seq; //! constructor copy_cpu_sd_k(grid_key_dx & key_s, grid_key_dx & key_d, const S & grid_src, S & grid_dst) :key_s(key_s),key_d(key_d),grid_src(grid_src),grid_dst(grid_dst){}; //! It call the copy function for each member template void operator()(T& t) const { // This is the type of the object we have to copy typedef typename boost::fusion::result_of::at_c::type copy_type; // Remove the reference from the type to copy typedef typename boost::remove_reference::type copy_rtype; meta_copy cp(grid_src.template get(key_s),grid_dst.template get(key_d)); } }; /*! \brief Metafunction take T and return a reference * * Metafunction take T and return a reference * * \param T type * */ template struct mem_reference { typedef T& type; }; /*! * * \brief This is an N-dimensional grid or an N-dimensional array working on CPU * * This is an N-Dimensional grid or an N-dimensional array working on CPU * * \param dim Dimensionality of the grid * \param T type of object the grid store * \param Mem interface used to allocate memory * */ template::type > class grid_cpu { //! Access the key typedef grid_key_dx access_key; //! boost::vector that describe the data type typedef typename T::type T_type; //! This is an header that store all information related to the grid grid_sm g1; //! This is the interface to allocate an resize memory //! and give also a representation to the allocated memory Mem data; /*! \brief Get 1D vector with the * * Get std::vector with element 0 to dim set to 0 * */ std::vector getV() { std::vector tmp; for (unsigned int i = 0 ; i < dim ; i++) { tmp.push_back(0); } return tmp; } public: //! Memory traits typedef Mem memory_t; //! Object container for T, it is the return type of get_o it return a object type trough // you can access all the properties of T typedef encapc container; // The object type the grid is storing typedef T type; //! Default constructor grid_cpu() :g1(getV()) { } //! Set the grid dimensions void setDimensions(std::vector & sz) { g1.setDimension(sz); } /*! \brief create a grid from another grid * * \param the grid to copy * \param S memory type, used for template deduction * */ template grid_cpu(const grid_cpu & g, S & mem) { swap(g.duplicate()); } //! Constructor allocate memory and give them a representation grid_cpu(std::vector & sz) :g1(sz) { } //! Constructor allocate memory and give them a representation grid_cpu(std::vector && sz) :g1(sz) { } //! Constructor allocate memory and give them a representation grid_cpu(size_t (& sz)[dim]) :g1(sz) { } /*! \brief create a duplicated version of the grid * */ template grid_cpu duplicate() { //! Create a completely new grid with sz grid_cpu grid_new(g1.getSize()); //! Set the allocator and allocate the memory grid_new.template setMemory(); // We know that, if it is 1D we can safely copy the memory if (dim == 1) { //! 1-D copy (This case is simple we use raw memory copy because is the fastest option) grid_new.data.mem->copy(*data.mem); } else { //! N-D copy //! create a source grid iterator grid_key_dx_iterator it(g1); while(it.isNext()) { // get the grid key grid_key_dx key = it.get(); // create a copy element copy_cpu_sd> cp(key,*this,grid_new); // copy each property for each point of the grid boost::mpl::for_each_ref< boost::mpl::range_c >(cp); ++it; } } // copy grid_new to the base return grid_new; } /*! \brief Return the internal grid information * * Return the internal grid information * * \return the internal grid * */ grid_sm getGrid() { return g1; } /*! \brief Create the object that provide memory * * Create the object that provide memory * * \param T memory * */ template void setMemory() { //! Create and set the memory allocator data.setMemory(*new S()); //! Allocate the memory and create the reppresentation data.allocate(g1.size()); } /*! \brief Return a plain pointer to the internal data * * Return a plain pointer to the internal data * * \return plain data pointer * */ void * getPointer() { return data.mem->getPointer(); } /*! \brief Get the reference of the selected element * * \param p property to get (is an integer) * \param v1 grid_key that identify the element in the grid * * \return a reference to the element * */ template inline typename type_cpu_prop::type & get(grid_key

& v1) { #ifdef MEMLEAK_CHECK check_valid(&boost::fusion::at_c

(&data.mem_r->operator[](g1.LinId(v1.getId())))); #endif return boost::fusion::at_c

(data.mem_r->operator[](g1.LinId(v1.getId()))); } /*! \brief Get the const reference of the selected element * * \param p property to get (is an integer) * \param v1 grid_key that identify the element in the grid * * \return a const reference to the element * */ template inline const typename type_cpu_prop::type & get(grid_key

& v1) const { #ifdef MEMLEAK_CHECK check_valid(&boost::fusion::at_c

(&data.mem_r->operator[](g1.LinId(v1.getId())))); #endif return boost::fusion::at_c

(data.mem_r->operator[](g1.LinId(v1.getId()))); } /*! \brief Get the reference of the selected element * * \param v1 grid_key that identify the element in the grid * * \return the reference to the element * */ template inline typename type_cpu_prop::type & get(grid_key_d & v1) { #ifdef MEMLEAK_CHECK check_valid(&boost::fusion::at_c

(data.mem_r->operator[](g1.LinId(v1)))); #endif return boost::fusion::at_c

(data.mem_r->operator[](g1.LinId(v1))); } /*! \brief Get the const reference of the selected element * * \param v1 grid_key that identify the element in the grid * * \return the const reference to the element * */ template inline const typename type_cpu_prop::type & get(grid_key_d & v1) const { #ifdef MEMLEAK_CHECK check_valid(&boost::fusion::at_c

(data.mem_r->operator[](g1.LinId(v1)))); #endif return boost::fusion::at_c

(data.mem_r->operator[](g1.LinId(v1))); } /*! \brief Get the reference of the selected element * * \param v1 grid_key that identify the element in the grid * * \return the reference of the element * */ template inline typename type_cpu_prop::type & get(const grid_key_dx & v1) { #ifdef MEMLEAK_CHECK check_valid(&boost::fusion::at_c

(data.mem_r->operator[](g1.LinId(v1))),sizeof(typename type_cpu_prop::type)); #endif return boost::fusion::at_c

(data.mem_r->operator[](g1.LinId(v1))); } /*! \brief Get the const reference of the selected element * * \param v1 grid_key that identify the element in the grid * * \return the const reference of the element * */ template inline const typename type_cpu_prop::type & get(const grid_key_dx & v1) const { #ifdef MEMLEAK_CHECK check_valid(&boost::fusion::at_c

(data.mem_r->operator[](g1.LinId(v1))),sizeof(typename type_cpu_prop::type)); #endif return boost::fusion::at_c

(data.mem_r->operator[](g1.LinId(v1))); } /*! \brief Get the of the selected element as a boost::fusion::vector * * Get the selected element as a boost::fusion::vector * * \param v1 grid_key that identify the element in the grid * */ inline encapc get_o(const grid_key_dx & v1) { #ifdef MEMLEAK_CHECK check_valid(&data.mem_r->operator[](g1.LinId(v1)),sizeof(typename type_cpu_prop::type)); #endif return encapc(data.mem_r->operator[](g1.LinId(v1))); } /*! \brief Resize the space * * Resize the space to a new grid, the element are retained on the new grid, * if the new grid is bigger the new element are now initialized, if is smaller * the data are cropped * * \param sz reference to an array of dimension dim * */ template void resize(size_t (& sz)[dim]) { //! Create a completely new grid with sz grid_cpu grid_new(sz); //! Set the allocator and allocate the memory grid_new.template setMemory(); // We know that, if it is 1D we can safely copy the memory if (dim == 1) { //! 1-D copy (This case is simple we use raw memory copy because is the fastest option) grid_new.data.mem->copy(*data.mem); } else { //! N-D copy //! create a source grid iterator grid_key_dx_iterator it(g1); while(it.isNext()) { // get the grid key grid_key_dx key = it.get(); // create a copy element copy_cpu_sd> cp(key,*this,grid_new); // copy each property for each point of the grid boost::mpl::for_each_ref< boost::mpl::range_c >(cp); ++it; } } // copy grid_new to the base this->swap(grid_new); } /*! \brief Resize the space * * Resize the space to a new grid, the element are retained on the new grid, * if the new grid is bigger the new element are now initialized, if is smaller * the data are cropped * */ template void resize(std::vector & sz) { // array containing the size of the grid size_t sz_a[dim]; // fill the array for (int i = 0 ; i < dim ; i++) {sz_a[i] = sz[i];} // resize resize(sz_a); } /*! \brief It move the allocated object from one grid to another * * It move the allocated object from one grid to another, after this * call the argument grid is no longer valid * * \param grid to move/copy * */ void swap(grid_cpu & grid) { // move the data data.swap(grid.data); // move the grid info g1 = grid.g1; } /*! \brief It move the allocated object from one grid to another * * It move the allocated object from one grid to another, after this * call the argument grid is no longer valid * * \param grid to move/copy * */ void swap(grid_cpu && grid) { swap(grid); } /*! \brief set an element of the grid * * set an element of the grid * * \param dx is the grid key or the position to set * \param obj value to set * */ inline void set(grid_key_dx dx, T & obj) { #ifdef DEBUG // Check that the element exist for (int i = 0 ; i < dim ; i++) { if (dx.get(i) >= g1.size(i)) { std::cerr << "Error map_grid.hpp: out of bound" << "\n"; } } #endif // create the object to copy the properties copy_cpu> cp(dx,*this,obj); // copy each property boost::mpl::for_each_ref< boost::mpl::range_c >(cp); } /*! \brief set an element of the grid * * set an element of the grid from another element of another grid * * \param key1 element of the grid to set * \param g source grid * \param element of the source grid to copy * */ inline void set(grid_key_dx key1,const grid_cpu & g, grid_key_dx key2) { //create the object to copy the properties copy_cpu_sd_k> cp(key1,key2,g,*this); // copy each property for each point of the grid boost::mpl::for_each_ref< boost::mpl::range_c >(cp); } /*! \brief return the size of the grid * * Return the size of the grid * */ inline size_t size() { return g1.size(); } /*! \brief Return a sub-grid iterator * * Return a sub-grid iterator, to iterate through the grid * * \param start start point * \param stop stop point * */ inline grid_key_dx_iterator_sub getSubIterator(grid_key_dx & start, grid_key_dx & stop) { return grid_key_dx_iterator_sub(g1,start,stop); } /*! \brief Return a sub-grid iterator * * Return a sub-grid iterator, to iterate through the grid * * \param m Margin * */ inline grid_key_dx_iterator_sub getSubIterator(size_t m) { return grid_key_dx_iterator_sub(g1,m); } /*! \brief Return a grid iterator * * Return a grid iterator, to iterate through the grid * */ inline grid_key_dx_iterator getIterator() { return grid_key_dx_iterator(g1); } /*! \brief Return a grid iterator over all the point with the exception * of the ghost part * * Return a grid iterator over all the point with the exception of the * ghost part * */ inline grid_key_dx_iterator_sub getDomainIterator() { // get the starting point and the end point of the real domain return grid_key_dx_iterator_sub(g1,g1.getDomainStart(),g1.getDomainStop()); } /*! \brief Return the size of the message needed to pack this object * * TODO They just return 0 for now * * \return The size of the object to pack this object * * */ size_t packObjectSize() { return 0; } /*! \brief It fill the message packet * * TODO They just return 0 doing nothing * * \return The packet size * * */ size_t packObject(void * mem) { return 0; } }; /*! \brief this class is a functor for "for_each" algorithm * * This class is a functor for "for_each" algorithm. For each * element of the boost::vector the operator() is called * * \param T Type of memory allocator * */ template struct allocate { //! size to allocate size_t sz; //! constructor it fix the size allocate(size_t sz) :sz(sz){}; //! It call the allocate function for each member template void operator()(T& t) const { //! Create and set the memory allocator t.setMemory(*new S()); //! Allocate the memory and create the reppresentation t.allocate(sz); } }; template::type > class grid_gpu { //! Access the key typedef grid_key_dx access_key; //! It store all the information regarding the grid grid_sm g1; //! This is the interface to allocate,resize ... memory //! and give also a representation to the allocated memory Mem data; public: //! Memory traits typedef Mem memory_t; //! Object container for T, it is the return type of get_o it return a object type trough // you can access all the properties of T typedef encapg container; // The object type the grid is storing typedef T type; //! Default constructor grid_gpu() { } //! Set the grid dimensions void setDimensions(std::vector & sz) { g1.setDimension(sz); } //! Constructor it initialize the memory and give representation grid_gpu(std::vector & sz) :g1(sz) { } /*! \brief Return the internal grid information * * Return the internal grid information * * \return the internal grid * */ grid_sm getGrid() { return g1; } /*! \brief Create the object that provide memory * * Create the object that provide memory * * \param T memory * */ template void setMemory() { //! Create an allocate object allocate all(g1.size()); //! for each element in the vector allocate the buffer boost::fusion::for_each(data,all); } template inline typename type_gpu_prop::type::reference get(grid_key_d & v1) { return boost::fusion::at_c

(data).mem_r->operator[](g1.LinId(v1)); } template inline typename type_gpu_prop::type::reference get(grid_key_dx & v1) { return boost::fusion::at_c

(data).mem_r->operator[](g1.LinId(v1)); } /*! \brief Get the of the selected element as a boost::fusion::vector * * Get the selected element as a boost::fusion::vector * * \param v1 grid_key that identify the element in the grid * */ inline encapg get_o(grid_key_dx & v1) { return encapg(data,v1,g1); } inline size_t size() { return g1.size(); } //! this function set the memory interface if required //! this operation is required when we define a void memory //! allocator void set_memory(memory & mem) { data.mem.set_memory(mem); } /*! \brief Return a grid iterator * * Return a grid iterator, to iterate through the grid * */ inline grid_key_dx_iterator getIterator() { return grid_key_dx_iterator(g1); } /*! \brief Return a sub-grid iterator * * Return a sub-grid iterator, to iterate through the grid * */ inline grid_key_dx_iterator_sub getSubIterator(grid_key_dx & start, grid_key_dx & stop) { return grid_key_dx_iterator_sub(g1,start,stop); } /*! \brief Swap the memory of another grid * * Swap the memory of another grid * * \obj Memory to swap with * */ void swap(grid_gpu & obj) { g1.swap(obj.g1); data.swap(obj.data); } }; /*! device selector struct * * device selector struct, it return the correct data type for each device * */ template struct device_g { //! cpu typedef grid_cpu cpu; //! gpu typedef grid_gpu gpu; }; #endif