95
95
// -------------------------------------------------------------
96
96
namespace rheolef {
99
class array_seq_rep : public std::vector<T> {
98
template <class T, class A>
99
class array_seq_rep : public std::vector<T,A> {
101
typedef T value_type;
102
typedef typename std::vector<T>::size_type size_type;
103
typedef typename std::vector<T>::iterator iterator;
104
typedef typename std::vector<T>::const_iterator const_iterator;
105
typedef typename std::vector<T>::const_reference const_reference;
106
typedef typename std::vector<T>::reference reference;
107
typedef reference dis_reference;
108
typedef distributor::communicator_type communicator_type;
109
typedef sequential memory_type;
101
typedef T value_type;
102
typedef A allocator_type;
103
typedef typename A::difference_type difference_type;
104
typedef typename std::vector<T,A>::size_type size_type;
105
typedef typename std::vector<T,A>::iterator iterator;
106
typedef typename std::vector<T,A>::const_iterator const_iterator;
107
typedef typename std::vector<T,A>::const_reference const_reference;
108
typedef typename std::vector<T,A>::reference reference;
109
typedef reference dis_reference;
110
typedef distributor::communicator_type communicator_type;
111
typedef sequential memory_type;
111
array_seq_rep (const distributor& ownership, const T& init_val = T());
113
explicit array_seq_rep (const A& alloc = A());
114
array_seq_rep (const distributor& ownership, const T& init_val = T(), const A& alloc = A());
112
115
void resize (const distributor& ownership, const T& init_val = T());
113
array_seq_rep (size_type loc_size = 0, const T& init_val = T());
116
array_seq_rep (size_type loc_size = 0, const T& init_val = T(), const A& alloc = A());
114
117
void resize (size_type loc_size = 0, const T& init_val = T());
115
array_seq_rep (const array_seq_rep<T>& x);
118
array_seq_rep (const array_seq_rep<T,A>& x);
117
size_type size() const { return std::vector<T>::size(); }
118
iterator begin() { return std::vector<T>::begin(); }
119
const_iterator begin() const { return std::vector<T>::begin(); }
120
iterator end() { return std::vector<T>::end(); }
121
const_iterator end() const { return std::vector<T>::end(); }
120
A get_allocator() const { return std::vector<T,A>::get_allocator(); }
121
size_type size() const { return std::vector<T,A>::size(); }
122
iterator begin() { return std::vector<T,A>::begin(); }
123
const_iterator begin() const { return std::vector<T,A>::begin(); }
124
iterator end() { return std::vector<T,A>::end(); }
125
const_iterator end() const { return std::vector<T,A>::end(); }
122
126
const distributor& ownership() const { return _ownership; }
124
reference operator[] (size_type i) { return std::vector<T>::operator[] (i); }
125
const_reference operator[] (size_type i) const { return std::vector<T>::operator[] (i); }
128
reference operator[] (size_type i) { return std::vector<T,A>::operator[] (i); }
129
const_reference operator[] (size_type i) const { return std::vector<T,A>::operator[] (i); }
130
const_reference dis_at (size_type dis_i) const { return operator[] (dis_i); }
127
size_type dis_size () const { return std::vector<T>::size(); }
132
size_type dis_size () const { return std::vector<T,A>::size(); }
128
133
size_type first_index () const { return 0; }
129
size_type last_index () const { return std::vector<T>::size(); }
134
size_type last_index () const { return std::vector<T,A>::size(); }
130
135
reference dis_entry (size_type dis_i) { return operator[](dis_i); }
136
void reset_dis_indexes() const {}
131
137
template<class SetOp> void dis_entry_assembly_begin (SetOp) {}
132
138
template<class SetOp> void dis_entry_assembly_end (SetOp) {}
133
139
void dis_entry_assembly_begin () {}
134
140
void dis_entry_assembly_end () {}
135
141
void repartition ( // old_numbering for *this
136
const array_seq_rep<size_type>& partition, // old_ownership
137
array_seq_rep<T>& new_array, // new_ownership (created)
138
array_seq_rep<size_type>& old_numbering, // new_ownership
139
array_seq_rep<size_type>& new_numbering) const // old_ownership
142
const array_seq_rep<size_type,A>& partition, // old_ownership
143
array_seq_rep<T,A>& new_array, // new_ownership (created)
144
array_seq_rep<size_type,A>& old_numbering, // new_ownership
145
array_seq_rep<size_type,A>& new_numbering) const // old_ownership
141
147
error_macro ("not yet");
150
void reverse_permutation ( // old_ownership for *this=iold2dis_inew
151
array_seq_rep<size_type,A2>& inew2dis_iold) const; // new_ownership
143
153
idiststream& get_values (idiststream& s);
144
154
odiststream& put_values (odiststream& s) const;
145
155
template <class GetFunction> idiststream& get_values (idiststream& ips, GetFunction get_element);
153
163
// the distributed representation
154
164
// -------------------------------------------------------------
155
165
#ifdef _RHEOLEF_HAVE_MPI
157
class array_mpi_rep : public array_seq_rep<T> {
166
template <class T, class A>
167
class array_mpi_rep : public array_seq_rep<T,A> {
162
typedef typename array_seq_rep<T>::value_type value_type;
163
typedef typename array_seq_rep<T>::size_type size_type;
164
typedef typename array_seq_rep<T>::reference reference;
165
typedef typename array_seq_rep<T>::iterator iterator;
166
typedef typename array_seq_rep<T>::const_iterator const_iterator;
167
typedef distributor::communicator_type communicator_type;
168
typedef distributed memory_type;
172
typedef array_seq_rep<T,A> base;
173
typedef typename base::value_type value_type;
174
typedef typename base::size_type size_type;
175
typedef typename base::difference_type difference_type;
176
typedef typename base::reference reference;
177
typedef typename base::const_reference const_reference;
178
typedef typename base::iterator iterator;
179
typedef typename base::const_iterator const_iterator;
180
typedef distributor::communicator_type communicator_type;
181
typedef distributed memory_type;
182
typedef std::map <size_type, T, std::less<size_type>, heap_allocator<std::pair<size_type,T> > >
170
185
struct dis_reference {
171
dis_reference (array_mpi_rep<T>& x, size_type dis_i)
186
dis_reference (array_mpi_rep<T,A>& x, size_type dis_i)
172
187
: _x(x), _dis_i(dis_i) {}
174
189
dis_reference& operator= (const T& value) {
184
array_mpi_rep<T>& _x;
199
array_mpi_rep<T,A>& _x;
192
size_type dis_size = 0,
193
const T& init_val = T(),
194
size_type loc_size = distributor::decide);
196
size_type dis_size = 0,
197
const T& init_val = T(),
198
size_type loc_size = distributor::decide);
200
array_mpi_rep (const distributor& ownership, const T& init_val = T());
205
array_mpi_rep (const distributor& ownership, const T& init_val = T(), const A& alloc = A());
201
206
void resize (const distributor& ownership, const T& init_val = T());
202
array_mpi_rep (const array_mpi_rep<T>& x);
204
size_type size() const { return array_seq_rep<T>::size(); }
205
const_iterator begin() const { return array_seq_rep<T>::begin(); }
206
const_iterator end() const { return array_seq_rep<T>::end(); }
207
iterator begin() { return array_seq_rep<T>::begin(); }
208
iterator end() { return array_seq_rep<T>::end(); }
210
const distributor& ownership() const { return array_seq_rep<T>::_ownership; }
207
array_mpi_rep (const array_mpi_rep<T,A>& x);
209
A get_allocator() const { return base::get_allocator(); }
210
size_type size() const { return base::size(); }
211
const_iterator begin() const { return base::begin(); }
212
const_iterator end() const { return base::end(); }
213
iterator begin() { return base::begin(); }
214
iterator end() { return base::end(); }
216
const distributor& ownership() const { return base::_ownership; }
211
217
const mpi::communicator& comm() const { return ownership().comm(); }
212
218
size_type first_index () const { return ownership().first_index(); }
213
219
size_type last_index () const { return ownership().last_index(); }
225
231
void dis_entry_assembly () { dis_entry_assembly_begin (); dis_entry_assembly_end (); }
227
233
template<class Set, class Map>
228
void get_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const;
231
void set_dis_indexes (const Set& ext_idx_set) { get_dis_entry (ext_idx_set, _ext_x); }
233
const T& dis_at (size_type dis_i) const;
234
void append_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const;
236
template<class Set, class Map>
237
void get_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const {
239
append_dis_entry (ext_idx_set, ext_idx_map);
243
void append_dis_indexes (const Set& ext_idx_set) const { append_dis_entry (ext_idx_set, _ext_x); }
246
void set_dis_indexes (const Set& ext_idx_set) const { get_dis_entry (ext_idx_set, _ext_x); }
247
void reset_dis_indexes() const;
249
const_reference dis_at (size_type dis_i) const;
251
// get all external pairs (dis_i, values):
252
const scatter_map_type& get_dis_map_entries() const { return _ext_x; }
235
255
void repartition ( // old_numbering for *this
236
const array_mpi_rep<size_type>& partition, // old_ownership
237
array_mpi_rep<T>& new_array, // new_ownership (created)
238
array_mpi_rep<size_type>& old_numbering, // new_ownership
239
array_mpi_rep<size_type>& new_numbering) const; // old_ownership
241
void permutation_apply ( // old_numbering for *this
242
const array_mpi_rep<size_type>& new_numbering, // old_ownership
243
array_mpi_rep<T>& new_array) const; // new_ownership (already allocated)
256
const array_mpi_rep<size_type,A2>& partition, // old_ownership
257
array_mpi_rep<T,A>& new_array, // new_ownership (created)
258
array_mpi_rep<size_type,A2>& old_numbering, // new_ownership
259
array_mpi_rep<size_type,A2>& new_numbering) const; // old_ownership
262
void permutation_apply ( // old_numbering for *this
263
const array_mpi_rep<size_type,A2>& new_numbering, // old_ownership
264
array_mpi_rep<T,A>& new_array) const; // new_ownership (already allocated)
267
void reverse_permutation ( // old_ownership for *this=iold2dis_inew
268
array_mpi_rep<size_type,A2>& inew2dis_iold) const; // new_ownership
245
270
idiststream& get_values (idiststream& s);
246
271
odiststream& put_values (odiststream& s) const;
247
272
template <class GetFunction> idiststream& get_values (idiststream& ips, GetFunction get_element);
248
273
template <class PutFunction> odiststream& put_values (odiststream& ops, PutFunction put_element) const;
249
template <class PutFunction> odiststream& permuted_put_values (odiststream& ops, const array_mpi_rep<size_type>& perm,
274
template <class PutFunction, class A2> odiststream& permuted_put_values (odiststream& ops, const array_mpi_rep<size_type,A2>& perm,
250
275
PutFunction put_element) const;
251
276
void dump (std::string name) const;
270
295
typedef typename is_container_of_mpi_datatype<T>::type is_container;
271
296
typedef typename stash_traits<T,is_container>::mapped_type stash_value;
272
typedef typename stash_traits<T,is_container>::map_type map_type;
274
typedef std::map <size_type, T, std::less<size_type>, heap_allocator<std::pair<size_type,T> > > scatter_map_type;
276
typedef std::map <size_type, T> scatter_map_type;
297
typedef typename stash_traits<T,is_container>::map_type stash_map_type;
278
299
/** 2) message: for communication during assembly_begin(), assembly_end()
280
301
struct message_type {
281
std::list<std::pair<size_t,mpi::request> > waits;
282
std::vector<std::pair<size_type,stash_value> > data;
302
std::list<std::pair<size_type,mpi::request>,A> waits;
303
std::vector<std::pair<size_type,stash_value>,A> data;
284
305
/** 3) scatter (get_entry): specialized versions for T=container and T=simple type
286
307
template<class Set, class Map>
287
void get_dis_entry (const Set& ext_idx_set, Map& ext_idx_map, boost::mpl::true_) const;
308
void append_dis_entry (const Set& ext_idx_set, Map& ext_idx_map, boost::mpl::true_) const;
288
309
template<class Set, class Map>
289
void get_dis_entry (const Set& ext_idx_set, Map& ext_idx_map, boost::mpl::false_) const;
310
void append_dis_entry (const Set& ext_idx_set, Map& ext_idx_map, boost::mpl::false_) const;
292
map_type _stash; // for assembly msgs:
313
stash_map_type _stash; // for assembly msgs:
293
314
message_type _send;
294
315
message_type _receive;
295
316
size_type _receive_max_size;
296
scatter_map_type _ext_x; // for ext values (scatter)
317
mutable scatter_map_type _ext_x; // for ext values (scatter)
298
319
#endif // _RHEOLEF_HAVE_MPI
299
320
// -------------------------------------------------------------
378
399
AUTHOR: Pierre.Saramito@imag.fr
381
template <class T, class M = rheo_default_memory_model>
402
template <class T, class M = rheo_default_memory_model, class A = std::allocator<T> >
384
405
typedef M memory_type;
385
typedef typename std::vector<T>::size_type size_type;
386
typedef typename std::vector<T>::iterator iterator;
387
typedef typename std::vector<T>::const_iterator const_iterator;
406
typedef typename std::vector<T,A>::size_type size_type;
407
typedef typename std::vector<T,A>::iterator iterator;
408
typedef typename std::vector<T,A>::const_iterator const_iterator;
391
class array<T,sequential> : public smart_pointer<array_seq_rep<T> > {
411
template <class T, class A>
412
class array<T,sequential,A> : public smart_pointer<array_seq_rep<T,A> > {
396
typedef array_seq_rep<T> rep;
417
typedef array_seq_rep<T,A> rep;
397
418
typedef smart_pointer<rep> base;
399
420
typedef sequential memory_type;
400
421
typedef typename rep::size_type size_type;
422
typedef typename rep::difference_type difference_type;
401
423
typedef typename rep::value_type value_type;
402
424
typedef typename rep::reference reference;
403
425
typedef typename rep::dis_reference dis_reference;
433
459
dis_reference dis_entry (size_type dis_i) { return base::data().dis_entry(dis_i); }
434
460
void dis_entry_assembly() {}
435
template<class SetOp>
436
void dis_entry_assembly(SetOp my_set_op) {}
437
template<class SetOp>
438
void dis_entry_assembly_begin (SetOp my_set_op) {}
439
template<class SetOp>
440
void dis_entry_assembly_end (SetOp my_set_op) {}
461
template<class SetOp> void dis_entry_assembly(SetOp my_set_op) {}
462
template<class SetOp> void dis_entry_assembly_begin (SetOp my_set_op) {}
463
template<class SetOp> void dis_entry_assembly_end (SetOp my_set_op) {}
465
void reset_dis_indexes() const {}
466
template<class Set> void set_dis_indexes (const Set& ext_idx_set) const {}
467
template<class Set> void append_dis_indexes (const Set& ext_idx_set) const {}
468
template<class Set, class Map> void append_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const {}
469
template<class Set, class Map> void get_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const {}
442
471
// apply a partition:
444
473
template<class RepSize>
445
void repartition ( // old_numbering for *this
446
const RepSize& partition, // old_ownership
447
array<T,sequential>& new_array, // new_ownership (created)
448
RepSize& old_numbering, // new_ownership
449
RepSize& new_numbering) const // old_ownership
474
void repartition ( // old_numbering for *this
475
const RepSize& partition, // old_ownership
476
array<T,sequential,A>& new_array, // new_ownership (created)
477
RepSize& old_numbering, // new_ownership
478
RepSize& new_numbering) const // old_ownership
450
479
{ return base::data().repartition (partition, new_array, old_numbering, new_numbering); }
452
481
template<class RepSize>
453
void permutation_apply ( // old_numbering for *this
454
const RepSize& new_numbering, // old_ownership
455
array<T,sequential>& new_array) const // new_ownership (already allocated)
482
void permutation_apply ( // old_numbering for *this
483
const RepSize& new_numbering, // old_ownership
484
array<T,sequential,A>& new_array) const // new_ownership (already allocated)
456
485
{ return base::data().permutation_apply (new_numbering, new_array); }
487
void reverse_permutation ( // old_ownership for *this=iold2dis_inew
488
array<size_type,sequential,A>& inew2dis_iold) const // new_ownership
489
{ base::data().reverse_permutation (inew2dis_iold.data()); }
460
493
odiststream& put_values (odiststream& ops) const { return base::data().put_values(ops); }
466
499
void dump (std::string name) const { return base::data().dump(name); }
502
template <class T, class A>
471
array<T,sequential>::array (
504
array<T,sequential,A>::array (
472
505
size_type loc_size,
474
: base(new_macro(rep(loc_size,init_val)))
508
: base(new_macro(rep(loc_size,init_val,alloc)))
511
template <class T, class A>
479
array<T,sequential>::array (
513
array<T,sequential,A>::array (
480
514
const distributor& ownership,
482
: base(new_macro(rep(ownership,init_val)))
517
: base(new_macro(rep(ownership,init_val,alloc)))
520
template <class T, class A>
488
array<T,sequential>::resize (
523
array<T,sequential,A>::resize (
489
524
size_type loc_size,
490
525
const T& init_val)
492
527
base::data().resize (loc_size,init_val);
529
template <class T, class A>
497
array<T,sequential>::resize (
532
array<T,sequential,A>::resize (
498
533
const distributor& ownership,
499
534
const T& init_val)
503
538
#ifdef _RHEOLEF_HAVE_MPI
506
class array<T,distributed> : public smart_pointer<array_mpi_rep<T> > {
540
template <class T, class A>
541
class array<T,distributed,A> : public smart_pointer<array_mpi_rep<T,A> > {
511
typedef array_mpi_rep<T> rep;
546
typedef array_mpi_rep<T,A> rep;
512
547
typedef smart_pointer<rep> base;
514
549
typedef distributed memory_type;
515
550
typedef typename rep::size_type size_type;
551
typedef typename rep::difference_type difference_type;
516
552
typedef typename rep::value_type value_type;
517
553
typedef typename rep::reference reference;
518
554
typedef typename rep::dis_reference dis_reference;
519
555
typedef typename rep::iterator iterator;
520
556
typedef typename rep::const_reference const_reference;
521
557
typedef typename rep::const_iterator const_iterator;
558
typedef typename rep::scatter_map_type scatter_map_type;
525
array (const distributor& ownership = distributor(), const T& init_val = T());
562
array (const distributor& ownership = distributor(), const T& init_val = T(), const A& alloc = A());
526
563
void resize (const distributor& ownership = distributor(), const T& init_val = T());
528
565
// local accessors & modifiers:
567
A get_allocator() const { return base::data().get_allocator(); }
530
568
size_type size () const { return base::data().size(); }
531
569
size_type dis_size () const { return base::data().dis_size(); }
532
570
const distributor& ownership() const { return base::data().ownership(); }
543
583
// global accessor:
545
585
template<class Set, class Map>
546
void get_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const { base::data().get_dis_entry (ext_idx_set, ext_idx_map); }
549
void set_dis_indexes (const Set& ext_idx_set) { base::data().set_dis_indexes (ext_idx_set); }
586
void append_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const { base::data().append_dis_entry (ext_idx_set, ext_idx_map); }
588
template<class Set, class Map>
589
void get_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const { base::data().get_dis_entry (ext_idx_set, ext_idx_map); }
592
void append_dis_indexes (const Set& ext_idx_set) const { base::data().append_dis_indexes (ext_idx_set); }
593
void reset_dis_indexes() const { base::data().reset_dis_indexes(); }
596
void set_dis_indexes (const Set& ext_idx_set) const { base::data().set_dis_indexes (ext_idx_set); }
551
598
const T& dis_at (size_type dis_i) const { return base::data().dis_at (dis_i); }
600
// get all external pairs (dis_i, values):
601
const scatter_map_type& get_dis_map_entries() const { return base::data().get_dis_map_entries(); }
553
603
// global modifiers (for compatibility with distributed interface):
555
605
dis_reference dis_entry (size_type dis_i) { return base::data().dis_entry(dis_i); }
574
624
{ return base::data().repartition (partition.data(), new_array.data(), old_numbering.data(), new_numbering.data()); }
576
626
template<class RepSize>
577
void permutation_apply ( // old_numbering for *this
578
const RepSize& new_numbering, // old_ownership
579
array<T,distributed>& new_array) const // new_ownership (already allocated)
627
void permutation_apply ( // old_numbering for *this
628
const RepSize& new_numbering, // old_ownership
629
array<T,distributed,A>& new_array) const // new_ownership (already allocated)
580
630
{ base::data().permutation_apply (new_numbering.data(), new_array.data()); }
632
void reverse_permutation ( // old_ownership for *this=iold2dis_inew
633
array<size_type,distributed,A>& inew2dis_iold) const // new_ownership
634
{ base::data().reverse_permutation (inew2dis_iold.data()); }
584
638
odiststream& put_values (odiststream& ops) const { return base::data().put_values(ops); }
589
643
idiststream& get_values (idiststream& ips, GetFunction get_element) { return base::data().get_values(ips, get_element); }
590
644
template <class PutFunction>
591
645
odiststream& put_values (odiststream& ops, PutFunction put_element) const { return base::data().put_values(ops, put_element); }
592
template <class PutFunction> odiststream& permuted_put_values (
593
odiststream& ops, const array<size_type,distributed>& perm, PutFunction put_element) const
646
template <class PutFunction, class A2> odiststream& permuted_put_values (
647
odiststream& ops, const array<size_type,distributed,A2>& perm, PutFunction put_element) const
594
648
{ return base::data().permuted_put_values (ops, perm.data(), put_element); }
651
template <class T, class A>
599
array<T,distributed>::array (
653
array<T,distributed,A>::array (
600
654
const distributor& ownership,
602
: base(new_macro(rep(ownership,init_val)))
657
: base(new_macro(rep(ownership,init_val,alloc)))
660
template <class T, class A>
608
array<T,distributed>::resize (
663
array<T,distributed,A>::resize (
609
664
const distributor& ownership,
610
665
const T & init_val)
616
671
// -------------------------------------------------------------
617
672
// i/o with operator<< & >>
618
673
// -------------------------------------------------------------
674
template <class T, class A>
622
operator >> (idiststream& ips, array<T,sequential>& x)
677
operator >> (idiststream& ips, array<T,sequential,A>& x)
624
679
return x.get_values(ips);
681
template <class T, class A>
629
operator << (odiststream& ops, const array<T,sequential>& x)
684
operator << (odiststream& ops, const array<T,sequential,A>& x)
631
686
return x.put_values(ops);
633
688
#ifdef _RHEOLEF_HAVE_MPI
689
template <class T, class A>
637
operator >> (idiststream& ips, array<T,distributed>& x)
692
operator >> (idiststream& ips, array<T,distributed,A>& x)
639
694
return x.get_values(ips);
696
template <class T, class A>
644
operator << (odiststream& ops, const array<T,distributed>& x)
699
operator << (odiststream& ops, const array<T,distributed,A>& x)
646
701
return x.put_values(ops);