OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
grid_base_implementation.hpp
1 /*
2  * grid_base_implementation.hpp
3  *
4  * Created on: May 2, 2016
5  * Author: i-bird
6  */
7 
8 #ifndef OPENFPM_DATA_SRC_GRID_GRID_BASE_IMPLEMENTATION_HPP_
9 #define OPENFPM_DATA_SRC_GRID_GRID_BASE_IMPLEMENTATION_HPP_
10 
11 #include "grid_base_impl_layout.hpp"
12 #include "copy_grid_fast.hpp"
13 
25 template<unsigned int dim, typename T, typename S, typename layout_, template<typename> class layout_base >
27 {
29  typedef layout_ layout;
30 
31 public:
32 
34  typedef layout_ layout_type;
35 
37  static constexpr unsigned int dims = dim;
38 
41 
43  typedef typename T::type T_type;
44 
45 protected:
46 
49 
52 
53 private:
54 
56  bool is_mem_init = false;
57 
59  bool isExternal;
60 
61 #ifdef SE_CLASS1
62 
67  inline void check_init() const
68  {
69  if (is_mem_init == false)
70  {
71  std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " you must call SetMemory before access the grid\n";
72  ACTION_ON_ERROR(GRID_ERROR_OBJECT);
73  }
74  }
75 
81  inline void check_bound(const grid_key_dx<dim> & v1) const
82  {
83  for (long int i = 0 ; i < dim ; i++)
84  {
85  if (v1.get(i) >= (long int)getGrid().size(i))
86  {
87  std::cerr << "Error " __FILE__ << ":" << __LINE__ <<" grid overflow " << "x=[" << i << "]=" << v1.get(i) << " >= " << getGrid().size(i) << "\n";
88  ACTION_ON_ERROR(GRID_ERROR_OBJECT);
89  }
90  else if (v1.get(i) < 0)
91  {
92  std::cerr << "Error " __FILE__ << ":" << __LINE__ <<" grid overflow " << "x=[" << i << "]=" << v1.get(i) << " is negative " << "\n";
93  ACTION_ON_ERROR(GRID_ERROR_OBJECT);
94  }
95  }
96  }
97 
103  inline void check_bound(size_t v1) const
104  {
105  if (v1 >= getGrid().size())
106  {
107  std::cerr << "Error " __FILE__ << ":" << __LINE__ <<" grid overflow " << v1<< " >= " << getGrid().size() << "\n";
108  ACTION_ON_ERROR(GRID_ERROR_OBJECT);
109  }
110  }
111 
120  template<typename Mem> inline void check_bound(const grid_base_impl<dim,T,Mem,layout,layout_base> & g,const grid_key_dx<dim> & key2) const
121  {
122  for (size_t i = 0 ; i < dim ; i++)
123  {
124  if (key2.get(i) >= (long int)g.getGrid().size(i))
125  {
126  std::cerr << "Error " __FILE__ << ":" << __LINE__ <<" grid overflow " << "x=[" << i << "]=" << key2.get(i) << " >= " << g.getGrid().size(i) << "\n";
127  ACTION_ON_ERROR(GRID_ERROR_OBJECT);
128  }
129  else if (key2.get(i) < 0)
130  {
131  std::cerr << "Error " __FILE__ << ":" << __LINE__ <<" grid overflow " << "x=[" << i << "]=" << key2.get(i) << " is negative " << "\n";
132  ACTION_ON_ERROR(GRID_ERROR_OBJECT);
133  }
134  }
135  }
136 
145  template<typename Mem> inline void check_bound(const grid_base_impl<dim,T,Mem,layout,layout_base> & g,const size_t & key2) const
146  {
147  if (key2 >= g.getGrid().size())
148  {
149  std::cerr << "Error " __FILE__ << ":" << __LINE__ <<" grid overflow " << key2 << " >= " << getGrid().size() << "\n";
150  ACTION_ON_ERROR(GRID_ERROR_OBJECT);
151  }
152  }
153 
154 #endif
155 
156 public:
157 
158  // Implementation of packer and unpacker for grid
159  #include "grid_pack_unpack.ipp"
160 
162  typedef int yes_i_am_grid;
163 
166 
168  // you can access all the properties of T
170 
172  typedef T value_type;
173 
176  :g1(0),isExternal(false)
177  {
178  // Add this pointer
179 #ifdef SE_CLASS2
180  check_new(this,8,GRID_EVENT,1);
181 #endif
182  }
183 
191  :isExternal(false)
192  {
193  this->operator=(g);
194  }
195 
201  grid_base_impl(const size_t & sz) THROW
202  :g1(sz),isExternal(false)
203  {
204  // Add this pointer
205 #ifdef SE_CLASS2
206  check_new(this,8,GRID_EVENT,1);
207 #endif
208  }
209 
217  grid_base_impl(const size_t (& sz)[dim]) THROW
218  :g1(sz),isExternal(false)
219  {
220  // Add this pointer
221 #ifdef SE_CLASS2
222  check_new(this,8,GRID_EVENT,1);
223 #endif
224  }
225 
228  {
229  // delete this pointer
230 #ifdef SE_CLASS2
231  check_delete(this);
232 #endif
233  }
234 
243  {
244  // Add this pointer
245 #ifdef SE_CLASS2
246  check_new(this,8,GRID_EVENT,1);
247 #endif
248  swap(g.duplicate());
249 
250  return *this;
251  }
252 
261  {
262  // Add this pointer
263 #ifdef SE_CLASS2
264  check_new(this,8,GRID_EVENT,1);
265 #endif
266 
267  swap(g);
268 
269  return *this;
270  }
271 
280  {
281  // check if the have the same size
282  if (g1 != g.g1)
283  return false;
284 
285  auto it = getIterator();
286 
287  while (it.isNext())
288  {
289  auto key = it.get();
290 
291  if (this->get_o(key) != this->get_o(key))
292  return false;
293 
294  ++it;
295  }
296 
297  return true;
298  }
299 
306  {
307 #ifdef SE_CLASS2
308  check_valid(this,8);
309 #endif
310 
313 
315  grid_new.setMemory();
316 
317  // We know that, if it is 1D we can safely copy the memory
318 // if (dim == 1)
319 // {
321 // grid_new.data_.mem->copy(*data_.mem);
322 // }
323 // else
324 // {
326 
329 
330  while(it.isNext())
331  {
332  grid_new.set(it.get(),*this,it.get());
333 
334  ++it;
335  }
336 // }
337 
338  // copy grid_new to the base
339 
340  return grid_new;
341  }
342 
351  const grid_sm<dim,T> & getGrid() const
352  {
353 #ifdef SE_CLASS2
354  check_valid(this,8);
355 #endif
356  return g1;
357  }
358 
367  void setMemory()
368  {
369 #ifdef SE_CLASS2
370  check_valid(this,8);
371 #endif
372 
373  mem_setm<S,layout_base<T>,decltype(this->data_),decltype(this->g1)>::setMemory(data_,g1,is_mem_init);
374  }
375 
388  void setMemory(S & m)
389  {
390 #ifdef SE_CLASS2
391  check_valid(this,8);
392 #endif
393  isExternal = true;
395 
397  data_.setMemory(m);
398 
400  if (g1.size() != 0) data_.allocate(g1.size(),T::noPointers());
401 
402  is_mem_init = true;
403  }
404 
413  void * getPointer()
414  {
415 #ifdef SE_CLASS2
416  check_valid(this,8);
417 #endif
418  if (data_.mem_r == NULL)
419  return NULL;
420 
421  return data_.mem_r->get_pointer();
422  }
423 
432  const void * getPointer() const
433  {
434 #ifdef SE_CLASS2
435  check_valid(this,8);
436 #endif
437  if (data_.mem_r == NULL)
438  return NULL;
439 
440  return data_.mem_r->get_pointer();
441  }
442 
450  template <unsigned int p, typename r_type=decltype(mem_get<p,layout_base<T>,layout,grid_sm<dim,T>,grid_key_dx<dim>>::get(data_,g1,grid_key_dx<dim>()))> inline r_type get(const grid_key_dx<dim> & v1)
451  {
452 #ifdef SE_CLASS2
453  check_valid(this,8);
454 #endif
455 #ifdef SE_CLASS1
456  check_init();
457  check_bound(v1);
458 #endif
459  return mem_get<p,layout_base<T>,decltype(this->data_),decltype(this->g1),decltype(v1)>::get(data_,g1,v1);
460  }
461 
469  template <unsigned int p, typename r_type=decltype(mem_get<p,layout_base<T>,layout,grid_sm<dim,T>,grid_key_dx<dim>>::get(data_,g1,grid_key_dx<dim>()))>
470  inline const r_type get(const grid_key_dx<dim> & v1) const
471  {
472 #ifdef SE_CLASS2
473  check_valid(this,8);
474 #endif
475 #ifdef SE_CLASS1
476  check_init();
477  check_bound(v1);
478 #endif
479  return mem_get<p,layout_base<T>,decltype(this->data_),decltype(this->g1),decltype(v1)>::get(data_,g1,v1);
480  }
481 
489  template <unsigned int p, typename r_type=decltype(mem_get<p,layout_base<T>,layout,grid_sm<dim,T>,grid_key_dx<dim>>::get_lin(data_,g1,0))>
490  inline r_type get(const size_t lin_id)
491  {
492 #ifdef SE_CLASS2
493  check_valid(this,8);
494 #endif
495 #ifdef SE_CLASS1
496  check_init();
497  check_bound(lin_id);
498 #endif
499  return mem_get<p,layout_base<T>,decltype(this->data_),decltype(this->g1),grid_key_dx<dim>>::get_lin(data_,g1,lin_id);
500  }
501 
509  template <unsigned int p, typename r_type=decltype(mem_get<p,layout_base<T>,layout,grid_sm<dim,T>,grid_key_dx<dim>>::get_lin(data_,g1,0))> inline const r_type get(size_t lin_id) const
510  {
511 #ifdef SE_CLASS2
512  check_valid(this,8);
513 #endif
514 #ifdef SE_CLASS1
515  check_init();
516  check_bound(lin_id);
517 #endif
518  return mem_get<p,layout_base<T>,decltype(this->data_),decltype(this->g1),grid_key_dx<dim>>::get_lin(data_,g1,lin_id);
519  }
520 
521 
534  {
535 #ifdef SE_CLASS2
536  check_valid(this,8);
537 #endif
538 #ifdef SE_CLASS1
539  check_init();
540  check_bound(v1);
541 #endif
542  return mem_geto<dim,T,layout_base<T>,decltype(this->data_),decltype(this->g1),decltype(v1)>::get(data_,g1,v1);
543  }
544 
556  inline const encapc<dim,T,layout> get_o(const grid_key_dx<dim> & v1) const
557  {
558 #ifdef SE_CLASS2
559  check_valid(this,8);
560 #endif
561 #ifdef SE_CLASS1
562  check_init();
563  check_bound(v1);
564 #endif
565  return mem_geto<dim,T,layout_base<T>,decltype(this->data_),decltype(this->g1),decltype(v1)>::get(const_cast<decltype(this->data_) &>(data_),g1,v1);
566  }
567 
579  inline encapc<dim,T,layout> get_o(size_t v1)
580  {
581 #ifdef SE_CLASS2
582  check_valid(this,8);
583 #endif
584 #ifdef SE_CLASS1
585  check_init();
586  check_bound(v1);
587 #endif
588  return mem_geto<dim,T,layout_base<T>,decltype(this->data_),decltype(this->g1),decltype(v1)>::get_lin(data_,v1);
589  }
590 
602  inline const encapc<dim,T,layout> get_o(size_t v1) const
603  {
604 #ifdef SE_CLASS2
605  check_valid(this,8);
606 #endif
607 #ifdef SE_CLASS1
608  check_init();
609  check_bound(v1);
610 #endif
611  return mem_geto<dim,T,layout_base<T>,decltype(this->data_),decltype(this->g1),decltype(v1)>::get_lin(const_cast<decltype(this->data_) &>(data_),v1);
612  }
613 
621  void fill(unsigned char fl)
622  {
623 #ifdef SE_CLASS2
624  check_valid(this,8);
625 #endif
626  memset(getPointer(),fl,size() * sizeof(T));
627  }
628 
638  void resize(const size_t (& sz)[dim])
639  {
640 #ifdef SE_CLASS2
641  check_valid(this,8);
642 #endif
643 
646 
648  if (isExternal == true)
649  {
650 /* grid_new.setMemory(static_cast<S&>(data_.getMemory()));
651 
652  // Create an empty memory allocator for the actual structure
653 
654  setMemory();*/
655  mem_setext<decltype(grid_new),S,layout_base<T>,decltype(data_)>::set(grid_new,*this,this->data_);
656  }
657  else
658  grid_new.setMemory();
659 
660 
661  // We know that, if it is 1D we can safely copy the memory
662 // if (dim == 1)
663 // {
664 // //! 1-D copy (This case is simple we use raw memory copy because is the fastest option)
665 // grid_new.data_.mem->copy(*data_.mem);
666 // }
667 // else
668 // {
669  // It should be better to separate between fast and slow cases
670 
672 
673  size_t sz_c[dim];
674  for (size_t i = 0 ; i < dim ; i++)
675  sz_c[i] = (g1.size(i) < sz[i])?g1.size(i):sz[i];
676 
677  grid_sm<dim,void> g1_c(sz_c);
678 
680  grid_key_dx_iterator<dim> it(g1_c);
681 
682  while(it.isNext())
683  {
684  // get the grid key
685  grid_key_dx<dim> key = it.get();
686 
687  // create a copy element
688 
689  grid_new.get_o(key) = this->get_o(key);
690 
691  ++it;
692  }
693 // }
694 
695  // copy grid_new to the base
696 
697  this->swap(grid_new);
698  }
699 
705  void remove(size_t key)
706  {
707 #ifdef SE_CLASS2
708  check_valid(this,8);
709 #endif
710  if (dim != 1)
711  {
712 #ifdef SE_CLASS1
713  std::cerr << "Error: " << __FILE__ << " " << __LINE__ << " remove work only on dimension == 1 " << "\n";
714 #endif
715  return;
716  }
717 
718  // It is safe to do a memory copy
719 
720  data_.move(&this->template get<0>());
721  }
722 
723 
734  {
735 #ifdef SE_CLASS2
736  check_valid(this,8);
737 #endif
738 
739  mem_swap<T,layout_base<T>,decltype(data_),decltype(grid)>::swap(data_,grid.data_);
740 
741  // exchange the grid info
742  g1.swap(grid.g1);
743 
744  // exchange the init status
745  bool exg = is_mem_init;
746  is_mem_init = grid.is_mem_init;
747  grid.is_mem_init = exg;
748 
749  // exchange the is external status
750  exg = isExternal;
751  isExternal = grid.isExternal;
752  grid.isExternal = exg;
753  }
754 
765  {
766 #ifdef SE_CLASS2
767  check_valid(this,8);
768 #endif
769  swap(grid);
770  }
771 
781  template<typename Memory> inline void set(grid_key_dx<dim> dx, const encapc<1,T,Memory> & obj)
782  {
783 #ifdef SE_CLASS2
784  check_valid(this,8);
785 #endif
786 #ifdef SE_CLASS1
787  check_init();
788  check_bound(dx);
789 #endif
790 
791  // create the object to copy the properties
793 
794  // copy each property
795  boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp);
796  }
797 
807  inline void set(grid_key_dx<dim> dx, const T & obj)
808  {
809 #ifdef SE_CLASS2
810  check_valid(this,8);
811 #endif
812 #ifdef SE_CLASS1
813  check_init();
814  check_bound(dx);
815 #endif
816 
817  this->get_o(dx) = obj;
818  }
819 
820 
829  inline void set(const grid_key_dx<dim> & key1,
831  const grid_key_dx<dim> & key2)
832  {
833 #ifdef SE_CLASS2
834  check_valid(this,8);
835 #endif
836 #ifdef SE_CLASS1
837  check_init();
838  check_bound(key1);
839  check_bound(g,key2);
840 #endif
841 
842  this->get_o(key1) = g.get_o(key2);
843  }
844 
853  inline void set(const size_t key1,
855  const size_t key2)
856  {
857 #ifdef SE_CLASS2
858  check_valid(this,8);
859 #endif
860 #ifdef SE_CLASS1
861  check_init();
862  check_bound(key1);
863  check_bound(g,key2);
864 #endif
865 
866  this->get_o(key1) = g.get_o(key2);
867  }
868 
877  template<typename Mem> inline void set(const grid_key_dx<dim> & key1,const grid_base_impl<dim,T,Mem,layout,layout_base> & g, const grid_key_dx<dim> & key2)
878  {
879 #ifdef SE_CLASS2
880  check_valid(this,8);
881 #endif
882 #ifdef SE_CLASS1
883  check_init();
884  check_bound(key1);
885  check_bound(g,key2);
886 #endif
887 
888  this->get_o(key1) = g.get_o(key2);
889  }
890 
896  inline size_t size() const
897  {
898 #ifdef SE_CLASS2
899  check_valid(this,8);
900 #endif
901  return g1.size();
902  }
903 
915  {
916 #ifdef SE_CLASS2
917  check_valid(this,8);
918 #endif
919  return g1.getSubIterator(start,stop);
920  }
921 
932  {
933 #ifdef SE_CLASS2
934  check_valid(this,8);
935 #endif
937  }
938 
947  {
948 #ifdef SE_CLASS2
949  check_valid(this,8);
950 #endif
952  }
953 
961  template<unsigned int Np>
963  getIteratorStencil(const grid_key_dx<dim> (& stencil_pnt)[Np]) const
964  {
965 #ifdef SE_CLASS2
966  check_valid(this,8);
967 #endif
969  }
970 
983  {
984 #ifdef SE_CLASS2
985  check_valid(this,8);
986 #endif
987  // get the starting point and the end point of the real domain
988 
989  return grid_key_dx_iterator_sub<dim>(g1,start,stop);
990  }
991 
992 
1000  long int who()
1001  {
1002 #ifdef SE_CLASS2
1003  return check_whoami(this,8);
1004 #else
1005  return -1;
1006 #endif
1007  }
1008 };
1009 
1010 
1011 #endif /* OPENFPM_DATA_SRC_GRID_GRID_BASE_IMPLEMENTATION_HPP_ */
void swap(grid_base_impl< dim, T, S, layout, layout_base > &&grid)
It move the allocated object from one grid to another.
grid_key_dx< dim > access_key
Access key.
grid_sm< dim, T > g1
This is a structure that store all information related to the grid and how indexes are linearized...
void * getPointer()
Return a plain pointer to the internal data.
grid_key_dx is the key to access any element in the grid
Definition: grid_key.hpp:18
void set(grid_key_dx< dim > dx, const encapc< 1, T, Memory > &obj)
set an element of the grid
memory_traits_lin< typename T::type >::type memory_lin
Definition of the layout.
Case memory_traits_lin.
T value_type
The object type the grid is storing.
grid_base_impl() THROW
Default constructor.
size_t size() const
Return the size of the grid.
Definition: grid_sm.hpp:572
r_type get(const grid_key_dx< dim > &v1)
Get the reference of the selected element.
void resize(const size_t(&sz)[dim])
Resize the space.
bool operator==(const grid_base_impl< dim, T, S, layout, layout_base > &g)
Compare two grids.
bool is_mem_init
Is the memory initialized.
encapc< dim, T, layout > get_o(const grid_key_dx< dim > &v1)
Get the of the selected element as a boost::fusion::vector.
~grid_base_impl() THROW
Destructor.
grid_key_dx_iterator_sub< dim > getSubIterator(grid_key_dx< dim > &start, grid_key_dx< dim > &stop) const
Return a sub-grid iterator.
layout data_
Memory layout specification + memory chunk pointer.
encapc< dim, T, layout > get_o(size_t v1)
Get the of the selected element as a boost::fusion::vector.
void set(const size_t key1, const grid_base_impl< dim, T, S, layout, layout_base > &g, const size_t key2)
Set an element of the grid from another element of another grid.
Case memory_traits_lin.
this class is a functor for "for_each" algorithm
Definition: grid_common.hpp:28
T::type T_type
boost::vector that describe the data type
grid_key_dx_iterator_sub< dim > getSubIterator(size_t m)
Return a sub-grid iterator.
mem_id get(size_t i) const
Get the i index.
Definition: grid_key.hpp:394
void set(const grid_key_dx< dim > &key1, const grid_base_impl< dim, T, S, layout, layout_base > &g, const grid_key_dx< dim > &key2)
Set an element of the grid from another element of another grid.
void set(const grid_key_dx< dim > &key1, const grid_base_impl< dim, T, Mem, layout, layout_base > &g, const grid_key_dx< dim > &key2)
Set an element of the grid from another element of another grid.
Case memory_traits_lin.
Case memory_traits_lin.
grid_base_impl(const size_t &sz) THROW
create a grid of size sz on each direction
Case memory_traits_lin.
const encapc< dim, T, layout > get_o(size_t v1) const
Get the of the selected element as a boost::fusion::vector.
const grid_sm< dim, T > & getGrid() const
Return the internal grid information.
void swap(grid_sm< N, T > &g)
swap the grid_sm informations
Definition: grid_sm.hpp:700
grid_base_impl< dim, T, S, layout, layout_base > & operator=(grid_base_impl< dim, T, S, layout, layout_base > &&g)
It copy a grid.
layout_ layout_type
memory layout
const size_t(& getSize() const)[N]
Return the size of the grid as an array.
Definition: grid_sm.hpp:677
const grid_key_dx< dim > & get() const
Get the actual key.
grid_base_impl(const grid_base_impl &g) THROW
create a grid from another grid
void fill(unsigned char fl)
Fill the memory with the selected byte.
size_t size() const
return the size of the grid
void setMemory()
Create the object that provide memory.
bool isNext()
Check if there is the next element.
long int who()
It return the id of structure in the allocation list.
grid_base_impl(const size_t(&sz)[dim]) THROW
Constructor.
This class is a trick to indicate the compiler a specific specialization pattern. ...
Definition: memory_c.hpp:201
grid_base_impl< dim, T, S, layout, layout_base > & operator=(const grid_base_impl< dim, T, S, layout, layout_base > &g)
It copy a grid.
const encapc< dim, T, layout > get_o(const grid_key_dx< dim > &v1) const
Get the of the selected element as a boost::fusion::vector.
grid_key_dx_iterator_sub< dim > getIterator(const grid_key_dx< dim > &start, const grid_key_dx< dim > &stop) const
Return a grid iterator over all points included between start and stop point.
void swap(grid_base_impl< dim, T, S, layout, layout_base > &grid)
It move the allocated object from one grid to another.
int yes_i_am_grid
it define that it is a grid
const void * getPointer() const
Return a plain pointer to the internal data.
This class is a container for the memory interface like HeapMemory CudaMemory.
Definition: memory_c.hpp:31
void setMemory(S &m)
Get the object that provide memory.
static constexpr unsigned int dims
expose the dimansionality as a static const
void set(grid_key_dx< dim > dx, const T &obj)
set an element of the grid
grid_key_dx_iterator< dim > getIterator() const
Return a grid iterator.
layout_ layout
memory layout
grid_key_dx_iterator_sub< N > getSubIterator(grid_key_dx< N > &start, grid_key_dx< N > &stop) const
Return a sub-grid iterator.
Definition: grid_sm.hpp:690
encapc< dim, T, layout > container
Object container for T, it is the return type of get_o it return a object type trough.
grid_base_impl< dim, T, S, layout, layout_base > duplicate() const THROW
create a duplicated version of the grid
grid_key_dx_iterator< dim, stencil_offset_compute< dim, Np > > getIteratorStencil(const grid_key_dx< dim >(&stencil_pnt)[Np]) const
Return a grid iterator.
bool isExternal
The memory allocator is not internally created.
Implementation of a N-dimensional grid.