map_grid.hpp 22.2 KB
Newer Older
Pietro Incardona's avatar
Pietro Incardona committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#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 <boost/fusion/include/mpl.hpp>
#include <boost/fusion/sequence/intrinsic/at_c.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/container/vector/vector_fwd.hpp>
#include <boost/fusion/include/vector_fwd.hpp>
#include <boost/type_traits.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/for_each.hpp>
#include "memory_conf.hpp"
#include "meta_copy.hpp"
#include "Memleak_check.hpp"
23
#include "for_each_ref.hpp"
Pietro Incardona's avatar
Pietro Incardona committed
24

Pietro Incardona's avatar
Pietro Incardona committed
25

Pietro Incardona's avatar
Pietro Incardona committed
26
#include "grid_sm.hpp"
Pietro Incardona's avatar
Pietro Incardona committed
27
#include "Encap.hpp"
Pietro Incardona's avatar
Pietro Incardona committed
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include "memory_array.hpp"
#include "memory_c.hpp"
#include <vector>

/*! \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<unsigned int dim, typename S>
struct copy_cpu
{
	//! size to allocate
	grid_key_dx<dim> & key;

	//! grid where we have to store the data
52
	S & grid_dst;
Pietro Incardona's avatar
Pietro Incardona committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

	//! 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
	 *
	 */
72
73
	copy_cpu(grid_key_dx<dim> & key, S & grid_dst, obj_type & obj)
	:key(key),grid_dst(grid_dst),obj(obj){};
Pietro Incardona's avatar
Pietro Incardona committed
74
75
76
77
78
79
80
81
82
83
84

	//! It call the copy function for each property
    template<typename T>
    void operator()(T& t) const
    {
    	// This is the type of the object we have to copy
    	typedef typename boost::fusion::result_of::at_c<ov_seq,T::value>::type copy_type;

    	// Remove the reference from the type to copy
    	typedef typename boost::remove_reference<copy_type>::type copy_rtype;

85
    	meta_copy<copy_rtype> cp(boost::fusion::at_c<T::value>(obj.data),grid_dst.template get<T::value>(key));
Pietro Incardona's avatar
Pietro Incardona committed
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
    }
};

/*! \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<unsigned int dim, typename S>
struct copy_cpu_sd
{
	//! size to allocate
	grid_key_dx<dim> & key;

	//! Source grid
109
	const S & grid_src;
Pietro Incardona's avatar
Pietro Incardona committed
110
111
112
113
114
115
116

	//! Destination grid
	S & grid_dst;

	//! type of the object boost::sequence
	typedef typename S::type::type ov_seq;

117
118
	//! constructor
	copy_cpu_sd(grid_key_dx<dim> & key, const S grid_src, S grid_dst)
Pietro Incardona's avatar
Pietro Incardona committed
119
120
121
122
123
124
125
126
127
128
129
130
	:key(key),grid_src(grid_src),grid_dst(grid_dst){};

	//! It call the copy function for each member
    template<typename T>
    void operator()(T& t) const
    {
    	// This is the type of the object we have to copy
    	typedef typename boost::fusion::result_of::at_c<ov_seq,T::value>::type copy_type;

    	// Remove the reference from the type to copy
    	typedef typename boost::remove_reference<copy_type>::type copy_rtype;

131
    	meta_copy<copy_rtype> cp(grid_src.template get<T::value>(key),grid_dst.template get<T::value>(key));
Pietro Incardona's avatar
Pietro Incardona committed
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    }
};


/*! \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<unsigned int dim, typename S>
struct copy_cpu_sd_k
{
	//! source key
	grid_key_dx<dim> & key_s;

	//! destination key
	grid_key_dx<dim> & key_d;

	//! Source grid
159
	const S & grid_src;
Pietro Incardona's avatar
Pietro Incardona committed
160
161
162
163
164
165
166

	//! Destination grid
	S & grid_dst;

	//! type of the object boost::sequence
	typedef typename S::type::type ov_seq;

167
168
	//! constructor
	copy_cpu_sd_k(grid_key_dx<dim> & key_s, grid_key_dx<dim> & key_d, const S & grid_src, S & grid_dst)
Pietro Incardona's avatar
Pietro Incardona committed
169
170
171
172
173
174
175
176
177
178
179
180
	: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<typename T>
    void operator()(T& t) const
    {
    	// This is the type of the object we have to copy
    	typedef typename boost::fusion::result_of::at_c<ov_seq,T::value>::type copy_type;

    	// Remove the reference from the type to copy
    	typedef typename boost::remove_reference<copy_type>::type copy_rtype;

181
    	meta_copy<copy_rtype> cp(grid_src.template get<T::value>(key_s),grid_dst.template get<T::value>(key_d));
Pietro Incardona's avatar
Pietro Incardona committed
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    }
};

/*! \brief Metafunction take T and return a reference
 *
 * Metafunction take T and return a reference
 *
 * \param T type
 *
 */

template<typename T>
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<unsigned int dim, typename T, typename Mem = typename memory_traits_lin< typename T::type >::type >
class grid_cpu
{
		//! Access the key
		typedef grid_key_dx<dim> access_key;

Pietro Incardona's avatar
Pietro Incardona committed
218
		//! boost::vector that describe the data type
Pietro Incardona's avatar
Pietro Incardona committed
219
220
221
		typedef typename T::type T_type;

		//! This is an header that store all information related to the grid
Pietro Incardona's avatar
Pietro Incardona committed
222
		grid_sm<dim,T> g1;
Pietro Incardona's avatar
Pietro Incardona committed
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

		//! 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<size_t> getV()
		{
			std::vector<size_t> tmp;

			for (unsigned int i = 0 ; i < dim ; i++)
			{
				tmp.push_back(0);
			}

			return tmp;
		}

	public:

Pietro Incardona's avatar
Pietro Incardona committed
248
249
250
		//! Memory traits
		typedef Mem memory_t;

Pietro Incardona's avatar
Pietro Incardona committed
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
		//! 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<dim,T,Mem> 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<size_t> & 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<typename S> grid_cpu(const grid_cpu & g, S & mem)
		{
			swap(g.duplicate<S>());
		}

		//! Constructor allocate memory and give them a representation
		grid_cpu(std::vector<size_t> & sz)
		:g1(sz)
		{
		}

		//! Constructor allocate memory and give them a representation
		grid_cpu(std::vector<size_t> && 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<typename S> grid_cpu<dim,T,Mem> duplicate()
		{
			//! Create a completely new grid with sz

			grid_cpu<dim,T,Mem> grid_new(g1.getSize());

			//! Set the allocator and allocate the memory
			grid_new.template setMemory<S>();

	        // 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<dim> it(g1);

	        	while(it.isNext())
	        	{
	        		// get the grid key
	        		grid_key_dx<dim> key = it.get();

	        		// create a copy element

	        		copy_cpu_sd<dim,grid_cpu<dim,T,Mem>> cp(key,*this,grid_new);

	        		// copy each property for each point of the grid

336
	        		boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp);
Pietro Incardona's avatar
Pietro Incardona committed
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354

	        		++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
		 *
		 */

Pietro Incardona's avatar
Pietro Incardona committed
355
		grid_sm<dim,T> getGrid()
Pietro Incardona's avatar
Pietro Incardona committed
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
		{
			return g1;
		}

		/*! \brief Create the object that provide memory
		 *
		 * Create the object that provide memory
		 *
		 * \param T memory
		 *
		 */

		template<typename S> 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
		 *
395
396
		 * \return a reference to the element
		 *
Pietro Incardona's avatar
Pietro Incardona committed
397
398
399
400
401
402
403
404
		 */
		template <unsigned int p>inline typename type_cpu_prop<p,T>::type & get(grid_key<p> & v1)
		{
#ifdef MEMLEAK_CHECK
			check_valid(&boost::fusion::at_c<p>(&data.mem_r->operator[](g1.LinId(v1.getId()))));
#endif
			return boost::fusion::at_c<p>(data.mem_r->operator[](g1.LinId(v1.getId())));
		}
405
406

		/*! \brief Get the const reference of the selected element
Pietro Incardona's avatar
Pietro Incardona committed
407
		 *
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
		 * \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 <unsigned int p>inline const typename type_cpu_prop<p,T>::type & get(grid_key<p> & v1) const
		{
#ifdef MEMLEAK_CHECK
			check_valid(&boost::fusion::at_c<p>(&data.mem_r->operator[](g1.LinId(v1.getId()))));
#endif
			return boost::fusion::at_c<p>(data.mem_r->operator[](g1.LinId(v1.getId())));
		}

		/*! \brief Get the reference of the selected element
Pietro Incardona's avatar
Pietro Incardona committed
423
424
425
		 *
		 * \param v1 grid_key that identify the element in the grid
		 *
426
427
		 * \return the reference to the element
		 *
Pietro Incardona's avatar
Pietro Incardona committed
428
429
430
431
432
433
434
435
436
		 */
		template <unsigned int p>inline typename type_cpu_prop<p,T>::type & get(grid_key_d<dim,p> & v1)
		{
#ifdef MEMLEAK_CHECK
			check_valid(&boost::fusion::at_c<p>(data.mem_r->operator[](g1.LinId(v1))));
#endif
			return boost::fusion::at_c<p>(data.mem_r->operator[](g1.LinId(v1)));
		}
  
437
438
439
		/*! \brief Get the const reference of the selected element
		 *
		 * \param v1 grid_key that identify the element in the grid
Pietro Incardona's avatar
Pietro Incardona committed
440
		 *
441
442
443
444
445
446
447
448
449
450
451
452
		 * \return the const reference to the element
		 *
		 */
		template <unsigned int p>inline const typename type_cpu_prop<p,T>::type & get(grid_key_d<dim,p> & v1) const
		{
#ifdef MEMLEAK_CHECK
			check_valid(&boost::fusion::at_c<p>(data.mem_r->operator[](g1.LinId(v1))));
#endif
			return boost::fusion::at_c<p>(data.mem_r->operator[](g1.LinId(v1)));
		}

		/*! \brief Get the reference of the selected element
Pietro Incardona's avatar
Pietro Incardona committed
453
454
455
		 *
		 * \param v1 grid_key that identify the element in the grid
		 *
456
457
		 * \return the reference of the element
		 *
Pietro Incardona's avatar
Pietro Incardona committed
458
		 */
459
		template <unsigned int p>inline typename type_cpu_prop<p,T>::type & get(const grid_key_dx<dim> & v1)
Pietro Incardona's avatar
Pietro Incardona committed
460
461
462
463
464
465
466
		{
#ifdef MEMLEAK_CHECK
			check_valid(&boost::fusion::at_c<p>(data.mem_r->operator[](g1.LinId(v1))),sizeof(typename type_cpu_prop<p,T>::type));
#endif
			return boost::fusion::at_c<p>(data.mem_r->operator[](g1.LinId(v1)));
		}

467
468
469
470
471
472
473
474
475
476
477
478
479
480
		/*! \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 <unsigned int p>inline const typename type_cpu_prop<p,T>::type & get(const grid_key_dx<dim> & v1) const
		{
#ifdef MEMLEAK_CHECK
			check_valid(&boost::fusion::at_c<p>(data.mem_r->operator[](g1.LinId(v1))),sizeof(typename type_cpu_prop<p,T>::type));
#endif
			return boost::fusion::at_c<p>(data.mem_r->operator[](g1.LinId(v1)));
		}
Pietro Incardona's avatar
Pietro Incardona committed
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540

		/*! \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<dim,T,Mem> get_o(const grid_key_dx<dim> & v1)
		{
#ifdef MEMLEAK_CHECK
			check_valid(&data.mem_r->operator[](g1.LinId(v1)),sizeof(typename type_cpu_prop<p,T>::type));
#endif
			return encapc<dim,T,Mem>(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<typename S> void resize(size_t (& sz)[dim])
		{
			//! Create a completely new grid with sz

			grid_cpu<dim,T,Mem> grid_new(sz);

			//! Set the allocator and allocate the memory
			grid_new.template setMemory<S>();

	        // 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<dim> it(g1);

	        	while(it.isNext())
	        	{
	        		// get the grid key
	        		grid_key_dx<dim> key = it.get();

	        		// create a copy element

	        		copy_cpu_sd<dim,grid_cpu<dim,T,Mem>> cp(key,*this,grid_new);

	        		// copy each property for each point of the grid

541
	        		boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp);
Pietro Incardona's avatar
Pietro Incardona committed
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584

	        		++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<typename S> void resize(std::vector<size_t> & 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<S>(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<dim,T,Mem> & grid)
		{
			// move the data
585
			data.swap(grid.data);
Pietro Incardona's avatar
Pietro Incardona committed
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631

			// 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<dim,T,Mem> && 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<dim> 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<dim,grid_cpu<dim,T,Mem>> cp(dx,*this,obj);

    		// copy each property
632
    		boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp);
Pietro Incardona's avatar
Pietro Incardona committed
633
634
635
636
637
638
639
640
641
642
643
644
		}

		/*! \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
		 *
		 */

645
		inline void set(grid_key_dx<dim> key1,const grid_cpu<dim,T,Mem> & g, grid_key_dx<dim> key2)
Pietro Incardona's avatar
Pietro Incardona committed
646
647
		{
			//create the object to copy the properties
648
    		copy_cpu_sd_k<dim,grid_cpu<dim,T,Mem>> cp(key1,key2,g,*this);
Pietro Incardona's avatar
Pietro Incardona committed
649
650
651

    		// copy each property for each point of the grid

652
    		boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(cp);
Pietro Incardona's avatar
Pietro Incardona committed
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670

		}

		/*! \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
		 *
Pietro Incardona's avatar
Fix    
Pietro Incardona committed
671
672
673
		 * \param start start point
		 * \param stop stop point
		 *
Pietro Incardona's avatar
Pietro Incardona committed
674
675
676
677
678
679
680
		 */

		inline grid_key_dx_iterator_sub<dim> getSubIterator(grid_key_dx<dim> & start, grid_key_dx<dim> & stop)
		{
			return grid_key_dx_iterator_sub<dim>(g1,start,stop);
		}

Pietro Incardona's avatar
Fix    
Pietro Incardona committed
681
682
683
684
685
686
687
688
689
690
691
692
693
		/*! \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<dim> getSubIterator(size_t m)
		{
			return grid_key_dx_iterator_sub<dim>(g1,m);
		}

Pietro Incardona's avatar
Pietro Incardona committed
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
		/*! \brief Return a grid iterator
		 *
		 * Return a grid iterator, to iterate through the grid
		 *
		 */

		inline grid_key_dx_iterator<dim> getIterator()
		{
			return grid_key_dx_iterator<dim>(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
		 *
		 */

Pietro Incardona's avatar
Fix    
Pietro Incardona committed
713
		inline grid_key_dx_iterator_sub<dim> getDomainIterator()
Pietro Incardona's avatar
Pietro Incardona committed
714
715
716
		{
			// get the starting point and the end point of the real domain

Pietro Incardona's avatar
Fix    
Pietro Incardona committed
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
			return grid_key_dx_iterator_sub<dim>(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;
Pietro Incardona's avatar
Pietro Incardona committed
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
		}
};

/*! \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<typename S>
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<typename T>
    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<unsigned int dim, typename T, typename Mem = typename memory_traits_inte< typename T::type >::type >
class grid_gpu
{
	//! Access the key
	typedef grid_key_dx<dim> access_key;

	//! It store all the information regarding the grid
Pietro Incardona's avatar
Pietro Incardona committed
788
	grid_sm<dim,void> g1;
Pietro Incardona's avatar
Pietro Incardona committed
789
790
791
792
793
794
795

	//! This is the interface to allocate,resize ... memory
	//! and give also a representation to the allocated memory
	Mem data;

public:

Pietro Incardona's avatar
Pietro Incardona committed
796
797
798
	//! Memory traits
	typedef Mem memory_t;

Pietro Incardona's avatar
Pietro Incardona committed
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
	//! 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<dim,T,Mem> container;

	// The object type the grid is storing
	typedef T type;

	//! Default constructor
	grid_gpu()
	{
	}

	//! Set the grid dimensions
	void setDimensions(std::vector<size_t> & sz)
	{
		g1.setDimension(sz);
	}

	//! Constructor it initialize the memory and give representation
	grid_gpu(std::vector<size_t> & sz)
	:g1(sz)
	{
	}

	/*! \brief Return the internal grid information
	 *
	 * Return the internal grid information
	 *
	 * \return the internal grid
	 *
	 */

Pietro Incardona's avatar
Pietro Incardona committed
831
	grid_sm<dim,void> getGrid()
Pietro Incardona's avatar
Pietro Incardona committed
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
	{
		return g1;
	}

	/*! \brief Create the object that provide memory
	 *
	 * Create the object that provide memory
	 *
	 * \param T memory
	 *
	 */

	template<typename S> void setMemory()
	{
		//! Create an allocate object
		allocate<S> all(g1.size());

		//! for each element in the vector allocate the buffer
		boost::fusion::for_each(data,all);
	}

	template <unsigned int p>inline typename type_gpu_prop<p,T>::type::reference get(grid_key_d<dim,p> & v1)
	{
		return boost::fusion::at_c<p>(data).mem_r->operator[](g1.LinId(v1));
	}

	template <unsigned int p>inline typename type_gpu_prop<p,T>::type::reference get(grid_key_dx<dim> & v1)
	{
		return boost::fusion::at_c<p>(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<dim,T,Mem> get_o(grid_key_dx<dim> & v1)
	{
		return encapg<dim,T,Mem>(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<dim> getIterator()
	{
		return grid_key_dx_iterator<dim>(g1);
	}


	/*! \brief Return a sub-grid iterator
	 *
	 * Return a sub-grid iterator, to iterate through the grid
	 *
	 */

	inline grid_key_dx_iterator_sub<dim> getSubIterator(grid_key_dx<dim> & start, grid_key_dx<dim> & stop)
	{
		return grid_key_dx_iterator_sub<dim>(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<dim,T,Mem> & 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<unsigned int dim, typename T>
struct device_g
{
	//! cpu
	typedef grid_cpu<dim,T> cpu;
	//! gpu
	typedef grid_gpu<dim,T> gpu;
};

#endif