~ubuntu-branches/ubuntu/raring/rheolef/raring-proposed

« back to all changes in this revision

Viewing changes to skit/plib2/array.h

  • Committer: Bazaar Package Importer
  • Author(s): Pierre Saramito
  • Date: 2011-03-23 11:14:26 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20110323111426-cjvhey7lxt6077ty
Tags: 5.93-1
* New upstream release (minor changes):
  - some extra warning message deleted in heap_allocator
  - graphic output with mayavi2 fixed
  - add doc refman in .info and .pdf format

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
/// 
22
22
/// =========================================================================
23
23
 
24
 
# include "rheolef/parallel.h"
25
 
# include "rheolef/distributor.h"
26
 
# include "rheolef/parstream.h"
27
 
# include "rheolef/heap_allocator.h"
28
 
 
 
24
#include "rheolef/distributed.h"
 
25
#include "rheolef/distributor.h"
 
26
#include "rheolef/diststream.h"
 
27
#include "rheolef/heap_allocator.h"
 
28
#include "rheolef/msg_util.h"
 
29
 
 
30
#include <boost/mpl/bool.hpp>
 
31
 
 
32
namespace rheolef {
29
33
/// @brief array element output helper
30
34
template <class T>
31
35
struct _array_put_element_type {
36
40
struct _array_get_element_type {
37
41
  std::istream& operator() (std::istream& is, T& x) { return is >> x; }
38
42
};
39
 
#ifdef _RHEOLEF_HAVE_MPI
 
43
} // namespace rheolef
 
44
 
40
45
// -------------------------------------------------------------
41
46
// send a pair<size_t,T> via mpi & serialization
42
47
// -------------------------------------------------------------
43
48
// non-intrusive version of serialization for pair<size_t,T> 
 
49
#ifdef _RHEOLEF_HAVE_MPI
44
50
namespace boost {
45
51
 namespace serialization {
46
52
  template<class T, class Archive>
57
63
namespace boost {
58
64
 namespace mpi {
59
65
  template <>
60
 
  struct is_mpi_datatype<std::pair<size_t,double> > : mpl::true_ { };
 
66
  struct is_mpi_datatype<std::pair<size_t,double> > : boost::mpl::true_ { };
61
67
 } // namespace mpi
62
68
} // namespace boost
63
69
#endif // _RHEOLEF_HAVE_MPI
74
80
} // namespace rheolef
75
81
#endif // TO_CLEAN
76
82
// -------------------------------------------------------------
 
83
// support both array<T> with T=size_t and T=set<size_t>
 
84
// but we declare whether
 
85
// T is a simple mpi_datatype or a container of mpi_datatype
 
86
// -------------------------------------------------------------
 
87
namespace rheolef {
 
88
  template <class T>
 
89
  struct is_container_of_mpi_datatype : boost::mpl::false_ {
 
90
    typedef boost::mpl::false_ type;
 
91
  };
 
92
} // namespace rheolef
 
93
// -------------------------------------------------------------
77
94
// the sequential representation
78
95
// -------------------------------------------------------------
79
96
namespace rheolef {
87
104
    typedef typename std::vector<T>::const_iterator const_iterator;
88
105
    typedef typename std::vector<T>::const_reference const_reference;
89
106
    typedef typename std::vector<T>::reference      reference;
 
107
    typedef reference                               dis_reference;
90
108
    typedef distributor::communicator_type          communicator_type;
91
109
    typedef sequential                              memory_type;
92
110
 
93
 
    array_seq_rep (size_type loc_size = 0,       const T& init_val = T());
94
111
    array_seq_rep (const distributor& ownership, const T& init_val = T());
95
 
    array_seq_rep (const array_seq_rep<T>& x);
96
112
    void resize   (const distributor& ownership, const T& init_val = T());
 
113
    array_seq_rep (size_type loc_size = 0,       const T& init_val = T());
97
114
    void resize   (size_type loc_size = 0,       const T& init_val = T());
 
115
    array_seq_rep (const array_seq_rep<T>& x);
98
116
 
99
117
    size_type size() const { return std::vector<T>::size(); }
100
118
    iterator begin() { return std::vector<T>::begin(); }
106
124
    reference       operator[] (size_type i)       { return std::vector<T>::operator[] (i); }
107
125
    const_reference operator[] (size_type i) const { return std::vector<T>::operator[] (i); }
108
126
   
109
 
    size_type par_size () const { return std::vector<T>::size(); }
 
127
    size_type dis_size () const { return std::vector<T>::size(); }
110
128
    size_type first_index () const { return 0; }
111
129
    size_type last_index () const { return std::vector<T>::size(); }
112
 
    void set (size_type i, const T& xi) { operator[](i) = xi; }
113
 
    void assembly_begin () {}
114
 
    void assembly_end () {}
 
130
    reference dis_entry (size_type dis_i) { return operator[](dis_i); }
 
131
    template<class SetOp> void dis_entry_assembly_begin (SetOp) {}
 
132
    template<class SetOp> void dis_entry_assembly_end (SetOp) {}
 
133
    void dis_entry_assembly_begin () {}
 
134
    void dis_entry_assembly_end () {}
115
135
    void repartition (                                        // old_numbering for *this
116
136
        const array_seq_rep<size_type>& partition,            // old_ownership
117
137
        array_seq_rep<T>&               new_array,            // new_ownership (created)
120
140
    {
121
141
        error_macro ("not yet");
122
142
    }
123
 
    iparstream& get (iparstream& s);
124
 
    oparstream& put (oparstream& s) const;
125
 
    template <class GetFunction> iparstream& get (iparstream& ips, GetFunction get_element);
126
 
    template <class PutFunction> oparstream& put (oparstream& ops, PutFunction put_element) const;
 
143
    idiststream& get_values (idiststream& s);
 
144
    odiststream& put_values (odiststream& s) const;
 
145
    template <class GetFunction> idiststream& get_values (idiststream& ips, GetFunction get_element);
 
146
    template <class PutFunction> odiststream& put_values (odiststream& ops, PutFunction put_element) const;
127
147
    void dump (std::string name) const;
128
148
protected:
129
149
// data:
134
154
// -------------------------------------------------------------
135
155
#ifdef _RHEOLEF_HAVE_MPI
136
156
template <class T>
137
 
class array_mpi_rep : public array_seq_rep<T>
138
 
{
 
157
class array_mpi_rep : public array_seq_rep<T> {
139
158
public:
 
159
 
 
160
// typedefs:
 
161
 
140
162
    typedef typename array_seq_rep<T>::value_type     value_type;
141
163
    typedef typename array_seq_rep<T>::size_type      size_type;
 
164
    typedef typename array_seq_rep<T>::reference      reference;
142
165
    typedef typename array_seq_rep<T>::iterator       iterator;
143
166
    typedef typename array_seq_rep<T>::const_iterator const_iterator;
144
 
    typedef distributor::communicator_type          communicator_type;
 
167
    typedef distributor::communicator_type            communicator_type;
145
168
    typedef distributed                               memory_type;
146
169
 
147
 
    array_mpi_rep (const array_mpi_rep<T>& x);
 
170
    struct dis_reference {
 
171
      dis_reference (array_mpi_rep<T>& x, size_type dis_i)
 
172
       : _x(x), _dis_i(dis_i) {}
 
173
 
 
174
      dis_reference& operator= (const T& value) {
 
175
        _x.set_dis_entry (_dis_i, value);
 
176
        return *this;
 
177
      }
 
178
      dis_reference& operator+= (const T& value) {
 
179
        _x.set_add_dis_entry (_dis_i, value);
 
180
        return *this;
 
181
      }
 
182
    // data:
 
183
    protected:
 
184
      array_mpi_rep<T>& _x;
 
185
      size_type         _dis_i;
 
186
    };
 
187
 
 
188
// allocators:
 
189
 
 
190
#ifdef TO_CLEAN
148
191
    array_mpi_rep (
149
 
        size_type par_size = 0,
 
192
        size_type dis_size = 0,
150
193
        const T&  init_val = T(),
151
194
        size_type loc_size = distributor::decide); 
152
195
    void resize (
153
 
        size_type par_size = 0,
 
196
        size_type dis_size = 0,
154
197
        const T&  init_val = T(),
155
198
        size_type loc_size = distributor::decide);
156
 
    array_mpi_rep (
157
 
        const distributor& ownership,
158
 
        const T&  init_val = T());
159
 
    void resize (
160
 
        const distributor& ownership,
161
 
        const T&  init_val = T());
 
199
#endif // TO_CLEAN
 
200
    array_mpi_rep (const distributor& ownership, const T&  init_val = T());
 
201
    void resize   (const distributor& ownership, const T&  init_val = T());
 
202
    array_mpi_rep (const array_mpi_rep<T>& x);
162
203
 
163
204
    size_type size() const       { return array_seq_rep<T>::size(); }
164
205
    const_iterator begin() const { return array_seq_rep<T>::begin(); }
170
211
    const mpi::communicator& comm() const { return ownership().comm(); }
171
212
    size_type first_index () const        { return ownership().first_index(); }
172
213
    size_type last_index () const         { return ownership().last_index(); }
173
 
    size_type par_size () const           { return ownership().par_size(); }
174
 
    void set (size_type i, const T& xi);
175
 
    void assembly_begin ();
176
 
    void assembly_end ();
 
214
    size_type dis_size () const           { return ownership().dis_size(); }
 
215
 
 
216
    dis_reference dis_entry (size_type dis_i) { return dis_reference (*this, dis_i); }
 
217
 
 
218
    template<class SetOp> void dis_entry_assembly_begin (SetOp my_set_op);
 
219
    template<class SetOp> void dis_entry_assembly_end   (SetOp my_set_op);
 
220
    template<class SetOp> void dis_entry_assembly       (SetOp my_set_op)
 
221
                { dis_entry_assembly_begin (my_set_op); dis_entry_assembly_end (my_set_op); }
 
222
 
 
223
    void dis_entry_assembly_begin () { dis_entry_assembly_begin (set_op<T,T>()); }
 
224
    void dis_entry_assembly_end ()   { dis_entry_assembly_end   (set_op<T,T>()); }
 
225
    void dis_entry_assembly ()       { dis_entry_assembly_begin (); dis_entry_assembly_end (); }
 
226
 
 
227
    template<class Set, class Map>
 
228
    void get_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const;
 
229
 
 
230
    template<class Set>
 
231
    void set_dis_indexes (const Set& ext_idx_set) { get_dis_entry (ext_idx_set, _ext_x); }
 
232
 
 
233
    const T& dis_at (size_type dis_i) const;
 
234
 
177
235
    void repartition (                                        // old_numbering for *this
178
236
        const array_mpi_rep<size_type>& partition,            // old_ownership
179
237
        array_mpi_rep<T>&               new_array,            // new_ownership (created)
180
238
        array_mpi_rep<size_type>&       old_numbering,        // new_ownership
181
239
        array_mpi_rep<size_type>&       new_numbering) const; // old_ownership
182
 
    template<class Set, class Map>
183
 
    void scatter (const Set& ext_idx_set, Map& ext_idx_map) const;
184
 
 
185
 
    iparstream& get (iparstream& s);
186
 
    oparstream& put (oparstream& s) const;
187
 
    template <class GetFunction> iparstream& get (iparstream& ips, GetFunction get_element);
188
 
    template <class PutFunction> oparstream& put (oparstream& ops, PutFunction put_element) const;
189
 
    template <class PutFunction> oparstream& permuted_put (oparstream& ops, const array_mpi_rep<size_type>& perm,
 
240
 
 
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)
 
244
 
 
245
    idiststream& get_values (idiststream& s);
 
246
    odiststream& put_values (odiststream& s) const;
 
247
    template <class GetFunction> idiststream& get_values (idiststream& ips, GetFunction get_element);
 
248
    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,
190
250
                PutFunction put_element) const;
191
251
    void dump (std::string name) const;
192
252
protected:
193
 
// data:
194
 
    // for communication during assembly_begin(), assembly_end()
195
 
    typedef std::map <size_type, T, std::less<size_type>, heap_allocator<std::pair<size_type,T> > >   map_type;
 
253
    void set_dis_entry (size_type dis_i, const T& val);
 
254
    void set_add_dis_entry (size_type dis_i, const T& val);
 
255
// typedefs:
 
256
    /** 1) stash: store data before assembly() communications:
 
257
      *   select multimap<U> when T=set<U> and map<T> otherwise
 
258
      */
 
259
    template<class U, class IsContainer> struct stash_traits {};
 
260
    template<class U>
 
261
    struct stash_traits<U,boost::mpl::false_> {
 
262
        typedef U mapped_type;
 
263
        typedef std::map <size_type, U, std::less<size_type>, heap_allocator<std::pair<size_type,U> > >   map_type;
 
264
    };
 
265
    template<class U>
 
266
    struct stash_traits<U,boost::mpl::true_> {
 
267
        typedef typename U::value_type mapped_type;
 
268
        typedef std::multimap <size_type, mapped_type, std::less<size_type>, heap_allocator<std::pair<size_type,mapped_type> > >   map_type;
 
269
    };
 
270
    typedef typename is_container_of_mpi_datatype<T>::type is_container;
 
271
    typedef typename stash_traits<T,is_container>::mapped_type stash_value;
 
272
    typedef typename stash_traits<T,is_container>::map_type    map_type;
 
273
#ifdef TODO
 
274
    typedef std::map <size_type, T, std::less<size_type>, heap_allocator<std::pair<size_type,T> > >  scatter_map_type;
 
275
#endif // TODO
 
276
    typedef std::map <size_type, T>  scatter_map_type;
 
277
 
 
278
    /** 2) message: for communication during assembly_begin(), assembly_end()
 
279
      */
196
280
    struct message_type {
197
 
        std::list<std::pair<size_t,mpi::request> >  waits;
198
 
        std::vector<std::pair<size_type,T> >        data;
 
281
        std::list<std::pair<size_t,mpi::request> >       waits;
 
282
        std::vector<std::pair<size_type,stash_value> >   data;
199
283
    };
200
 
    map_type        _stash;
201
 
    message_type    _send;
202
 
    message_type    _receive;
203
 
    size_type       _receive_max_size;
 
284
    /** 3) scatter (get_entry): specialized versions for T=container and T=simple type
 
285
      */
 
286
    template<class Set, class Map>
 
287
    void get_dis_entry (const Set& ext_idx_set, Map& ext_idx_map, boost::mpl::true_) const;
 
288
    template<class Set, class Map>
 
289
    void get_dis_entry (const Set& ext_idx_set, Map& ext_idx_map, boost::mpl::false_) const;
 
290
 
 
291
// data:
 
292
    map_type         _stash;            // for assembly msgs:
 
293
    message_type     _send;
 
294
    message_type     _receive;
 
295
    size_type        _receive_max_size;
 
296
    scatter_map_type _ext_x;            // for ext values (scatter)
204
297
};
205
298
#endif // _RHEOLEF_HAVE_MPI
206
299
// -------------------------------------------------------------
214
307
EXAMPLE:
215
308
   A sample usage of the class is:
216
309
   @example
217
 
     int main(int argc, char**argv) {
218
 
        environment parallel(argc, argv);
219
 
        array<double> x(100, 3.14);
220
 
        pcout << x << endl;
221
 
     }
222
 
   @end example
223
 
SEE ALSO: "parstream"(1)
 
310
     int main(int argc, char**argv) @{
 
311
        environment distributed(argc, argv);
 
312
        array<double> x(distributor(100), 3.14);
 
313
        dcout << x << endl;
 
314
     @}
 
315
   @end example
 
316
   The array<T> interface is similar to those of the std::vector<T> with the 
 
317
   addition of some communication features in the distributed case:
 
318
   write accesses with entry/assembly and read access with dis_at.
 
319
 
 
320
DISTRIBUTED WRITE ACCESS:
 
321
   Loop on any @code{dis_i} that is not managed by the current processor:
 
322
   @example
 
323
        x.dis_entry (dis_i) = value;
 
324
   @end example
 
325
   and then, after loop, perform all communication:
 
326
   @example
 
327
        x.dis_entry_assembly();
 
328
   @end example
 
329
   After this command, each value is stored in the array, available the processor
 
330
   associated to @code{dis_i}.
 
331
DISTRIBUTED READ ACCESS:
 
332
   First, define the set of indexes:
 
333
   @example
 
334
        std::set<size_t> ext_idx_set; 
 
335
   @end example
 
336
   Then, loop on @code{dis_i} indexes that are not managed by the current processor:
 
337
   @example
 
338
        ext_idx_set.insert (dis_i);
 
339
   @end example
 
340
   After the loop, performs the communications:
 
341
   @example
 
342
        x.set_dis_indexes (ext_idx_set);
 
343
   @end example
 
344
   After this command, each values associated to the @code{dis_i} index,
 
345
   and that belongs to the index set, is now available also on the
 
346
   current processor as:
 
347
   @example
 
348
        value = x.dis_at (dis_i);
 
349
   @end example
 
350
   For convenience, if @code{dis_i} is managed by the current processor, this
 
351
   function returns also the value.
 
352
NOTE:
 
353
  The class takes two template parameters: one for the type T and the second
 
354
  for the memory model M, that could be either M=distributed or M=sequential.
 
355
  The two cases are associated to two diferent implementations, but proposes
 
356
  exactly the same interface. The sequential interface propose also a supplementary
 
357
  constructor:
 
358
   @example
 
359
        array<double,sequential> x(local_size, init_val);
 
360
   @end example
 
361
   This constructor is a STL-like one but could be consufused in the distributed case,
 
362
   since there are two sizes: a local one and a global one. In that case, the use
 
363
   of the distributor, as a generalization of the size concept, clarify the situation
 
364
   (@pxref{distributor class}).
 
365
 
 
366
IMPLEMENTATION NOTE:
 
367
  "scatter" via "get_dis_entry".
 
368
 
 
369
  "gather" via "dis_entry(dis_i) = value"
 
370
  or "dis_entry(dis_i) += value". Note that += applies when T=idx_set where
 
371
  idx_set is a wrapper class of std::set<size_t> ; the += operator represents the
 
372
  union of a set. The operator= is used when T=double or others simple T types
 
373
  without algebra. If there is a conflict, i.e. several processes set the dis_i
 
374
  index, then the result of operator+= depends upon the order of the process at
 
375
  each run and is not deterministic. Such ambiguous behavior is not detected
 
376
  yet at run time.
 
377
 
 
378
AUTHOR: Pierre.Saramito@imag.fr
224
379
End:
225
380
*/
226
 
template <class R>
227
 
class basic_array : public smart_pointer<R> {
228
 
public:
229
 
 
230
 
// typedefs:
231
 
 
232
 
    typedef typename R::value_type value_type;
233
 
    typedef typename R::value_type T;
234
 
    typedef typename R::size_type  size_type;
235
 
    typedef typename R::memory_type memory_type;
236
 
    typedef typename R::iterator iterator;
237
 
    typedef typename R::const_iterator const_iterator;
238
 
    typedef typename R::communicator_type communicator_type;
239
 
    typedef typename R::reference reference;
240
 
    typedef typename R::const_reference const_reference;
241
 
 
242
 
// allocators/deallocators:
243
 
 
244
 
    basic_array (size_type par_size = 0,       const T&  init_val = T());
245
 
    void resize (size_type par_size = 0,       const T&  init_val = T());
246
 
    basic_array (const distributor& ownership, const T&  init_val = T());
247
 
    void resize (const distributor& ownership, const T&  init_val = T());
248
 
 
249
 
// accessors:
250
 
 
251
 
    // sizes
252
 
    size_type size () const;
253
 
    size_type par_size () const;
254
 
    const distributor& ownership() const;
255
 
    const communicator_type& comm() const;
256
 
 
257
 
    // range on local memory
258
 
    size_type first_index () const;
259
 
    size_type last_index () const;
260
 
 
261
 
    // local iterators
262
 
    iterator begin();
263
 
    const_iterator begin() const;
264
 
    iterator end();
265
 
    const_iterator end() const;
266
 
 
267
 
    reference operator[] (size_type i);
268
 
    const_reference operator[] (size_type i) const;
269
 
 
270
 
// global modifiers:
271
 
 
272
 
    void set (size_type i, const T& xi);
273
 
    void assembly();
274
 
    void assembly_begin ();
275
 
    void assembly_end ();
276
 
 
277
 
// apply a partition:
278
 
 
279
 
    template<class RepSize>
280
 
    void repartition (                        // old_numbering for *this
281
 
        const RepSize&  partition,            // old_ownership
282
 
        basic_array<R>& new_array,            // new_ownership (created)
283
 
        RepSize&        old_numbering,        // new_ownership
284
 
        RepSize&        new_numbering) const;  // old_ownership
285
 
 
286
 
// i/o:
287
 
 
288
 
    void dump (std::string name) const;
289
 
};
290
381
template <class T, class M = rheo_default_memory_model>
291
382
class array {
292
383
public:
293
384
    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;
294
388
};
295
389
//<verbatim:
296
390
template <class T>
297
 
class array<T,sequential> : public basic_array<array_seq_rep<T> > {
 
391
class array<T,sequential> : public smart_pointer<array_seq_rep<T> > {
298
392
public:
299
 
    typedef sequential memory_type;
300
 
    typedef typename basic_array<array_seq_rep<T> >::size_type size_type;
301
 
    typedef typename basic_array<array_seq_rep<T> >::reference reference;
302
 
    typedef typename basic_array<array_seq_rep<T> >::const_reference const_reference;
303
 
    array (size_type par_size = 0,       const T& init_val = T());
304
 
    array (const distributor& ownership, const T& init_val = T());
305
 
    reference       operator[] (size_type i)       { return basic_array<array_seq_rep<T> >::operator[] (i); }
306
 
    const_reference operator[] (size_type i) const { return basic_array<array_seq_rep<T> >::operator[] (i); }
307
 
    oparstream& put (oparstream& ops) const { return basic_array<array_seq_rep<T> >::data().put(ops); }
308
 
    iparstream& get (iparstream& ips)       { return basic_array<array_seq_rep<T> >::data().get(ips); }
 
393
 
 
394
// typedefs:
 
395
 
 
396
    typedef array_seq_rep<T>              rep;
 
397
    typedef smart_pointer<rep>            base;
 
398
 
 
399
    typedef sequential                    memory_type;
 
400
    typedef typename rep::size_type       size_type;
 
401
    typedef typename rep::value_type      value_type;
 
402
    typedef typename rep::reference       reference;
 
403
    typedef typename rep::dis_reference   dis_reference;
 
404
    typedef typename rep::iterator        iterator;
 
405
    typedef typename rep::const_reference const_reference;
 
406
    typedef typename rep::const_iterator  const_iterator;
 
407
 
 
408
// allocators:
 
409
 
 
410
 
 
411
    array       (size_type loc_size = 0,       const T& init_val = T());
 
412
    void resize (size_type loc_size = 0,       const T& init_val = T());
 
413
    array       (const distributor& ownership, const T& init_val = T());
 
414
    void resize (const distributor& ownership, const T& init_val = T());
 
415
 
 
416
// local accessors & modifiers:
 
417
 
 
418
    size_type     size () const          { return base::data().size(); }
 
419
    size_type dis_size () const          { return base::data().dis_size(); }
 
420
    const distributor& ownership() const { return base::data().ownership(); }
 
421
    const communicator& comm() const     { return ownership().comm(); }
 
422
 
 
423
    reference       operator[] (size_type i)       { return base::data().operator[] (i); }
 
424
    const_reference operator[] (size_type i) const { return base::data().operator[] (i); }
 
425
 
 
426
          iterator begin()       { return base::data().begin(); }
 
427
    const_iterator begin() const { return base::data().begin(); }
 
428
          iterator end()         { return base::data().end(); }
 
429
    const_iterator end() const   { return base::data().end(); }
 
430
 
 
431
// global modifiers (for compatibility with distributed interface):
 
432
 
 
433
    dis_reference dis_entry (size_type dis_i) { return base::data().dis_entry(dis_i); }
 
434
    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)   {}
 
441
 
 
442
// apply a partition:
 
443
 
 
444
    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
 
450
        { return base::data().repartition (partition, new_array, old_numbering, new_numbering); }
 
451
 
 
452
    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)
 
456
        { return base::data().permutation_apply (new_numbering, new_array); }
 
457
 
 
458
// i/o:
 
459
 
 
460
    odiststream& put_values (odiststream& ops) const { return base::data().put_values(ops); }
 
461
    idiststream& get_values (idiststream& ips)       { return base::data().get_values(ips); }
309
462
    template <class GetFunction>
310
 
    iparstream& get (iparstream& ips, GetFunction get_element) { return basic_array<array_seq_rep<T> >::data().get(ips, get_element); }
 
463
    idiststream& get_values (idiststream& ips, GetFunction get_element)       { return base::data().get_values(ips, get_element); }
311
464
    template <class PutFunction>
312
 
    oparstream& put (oparstream& ops, PutFunction put_element) const { return basic_array<array_seq_rep<T> >::data().put(ops, put_element); }
 
465
    odiststream& put_values (odiststream& ops, PutFunction put_element) const { return base::data().put_values(ops, put_element); }
 
466
    void dump (std::string name) const { return base::data().dump(name); }
313
467
};
314
468
//>verbatim:
 
469
template <class T>
 
470
inline
 
471
array<T,sequential>::array (
 
472
        size_type loc_size,
 
473
        const T&  init_val)
 
474
 : base(new_macro(rep(loc_size,init_val)))
 
475
{
 
476
}
 
477
template <class T>
 
478
inline
 
479
array<T,sequential>::array (
 
480
        const distributor& ownership,
 
481
        const T&           init_val)
 
482
 : base(new_macro(rep(ownership,init_val)))
 
483
{
 
484
}
 
485
template <class T>
 
486
inline
 
487
void
 
488
array<T,sequential>::resize (
 
489
        size_type loc_size,
 
490
        const T&  init_val)
 
491
{
 
492
  base::data().resize (loc_size,init_val);
 
493
}
 
494
template <class T>
 
495
inline
 
496
void
 
497
array<T,sequential>::resize (
 
498
        const distributor& ownership,
 
499
        const T&           init_val)
 
500
{
 
501
  base::data().resize (ownership,init_val);
 
502
}
315
503
#ifdef _RHEOLEF_HAVE_MPI
316
504
//<verbatim:
317
505
template <class T>
318
 
class array<T,distributed> : public basic_array<array_mpi_rep<T> > {
 
506
class array<T,distributed> : public smart_pointer<array_mpi_rep<T> > {
319
507
public:
320
 
    typedef distributed memory_type;
321
 
    typedef typename basic_array<array_mpi_rep<T> >::size_type size_type;
322
 
    typedef typename basic_array<array_mpi_rep<T> >::reference reference;
323
 
    typedef typename basic_array<array_mpi_rep<T> >::const_reference const_reference;
324
 
    array (size_type par_size = 0,       const T&  init_val = T());
325
 
    array (const distributor& ownership, const T&  init_val = T());
326
 
    reference       operator[] (size_type i)       { return basic_array<array_mpi_rep<T> >::operator[] (i); }
327
 
    const_reference operator[] (size_type i) const { return basic_array<array_mpi_rep<T> >::operator[] (i); }
328
 
    oparstream& put (oparstream& ops) const { return basic_array<array_mpi_rep<T> >::data().put(ops); }
329
 
    iparstream& get (iparstream& ips)       { return basic_array<array_mpi_rep<T> >::data().get(ips); }
 
508
 
 
509
// typedefs:
 
510
 
 
511
    typedef array_mpi_rep<T>              rep;
 
512
    typedef smart_pointer<rep>            base;
 
513
 
 
514
    typedef distributed                   memory_type;
 
515
    typedef typename rep::size_type       size_type;
 
516
    typedef typename rep::value_type      value_type;
 
517
    typedef typename rep::reference       reference;
 
518
    typedef typename rep::dis_reference   dis_reference;
 
519
    typedef typename rep::iterator        iterator;
 
520
    typedef typename rep::const_reference const_reference;
 
521
    typedef typename rep::const_iterator  const_iterator;
 
522
 
 
523
// allocators:
 
524
 
 
525
    array       (const distributor& ownership = distributor(), const T& init_val = T());
 
526
    void resize (const distributor& ownership = distributor(), const T& init_val = T());
 
527
 
 
528
// local accessors & modifiers:
 
529
 
 
530
    size_type     size () const          { return base::data().size(); }
 
531
    size_type dis_size () const          { return base::data().dis_size(); }
 
532
    const distributor& ownership() const { return base::data().ownership(); }
 
533
    const communicator& comm() const     { return base::data().comm(); }
 
534
 
 
535
    reference       operator[] (size_type i)       { return base::data().operator[] (i); }
 
536
    const_reference operator[] (size_type i) const { return base::data().operator[] (i); }
 
537
 
 
538
          iterator begin()       { return base::data().begin(); }
 
539
    const_iterator begin() const { return base::data().begin(); }
 
540
          iterator end()         { return base::data().end(); }
 
541
    const_iterator end() const   { return base::data().end(); }
 
542
 
 
543
// global accessor:
 
544
 
330
545
    template<class Set, class Map>
331
 
    void scatter (const Set& ext_idx_set, Map& ext_idx_map) const {
332
 
        return basic_array<array_mpi_rep<T> >::data().scatter (ext_idx_set, ext_idx_map);
333
 
    }
 
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); }
 
547
 
 
548
    template<class Set>
 
549
    void set_dis_indexes (const Set& ext_idx_set)  { base::data().set_dis_indexes (ext_idx_set); }
 
550
 
 
551
    const T& dis_at (size_type dis_i) const { return base::data().dis_at (dis_i); }
 
552
 
 
553
// global modifiers (for compatibility with distributed interface):
 
554
 
 
555
    dis_reference dis_entry (size_type dis_i)       { return base::data().dis_entry(dis_i); }
 
556
 
 
557
    void dis_entry_assembly()                       { return base::data().dis_entry_assembly(); }
 
558
 
 
559
    template<class SetOp>
 
560
    void dis_entry_assembly       (SetOp my_set_op) { return base::data().dis_entry_assembly       (my_set_op); }
 
561
    template<class SetOp>
 
562
    void dis_entry_assembly_begin (SetOp my_set_op) { return base::data().dis_entry_assembly_begin (my_set_op); }
 
563
    template<class SetOp>
 
564
    void dis_entry_assembly_end   (SetOp my_set_op) { return base::data().dis_entry_assembly_end   (my_set_op); }
 
565
 
 
566
// apply a partition:
 
567
 
 
568
    template<class RepSize>
 
569
    void repartition (                              // old_numbering for *this
 
570
        const RepSize&        partition,            // old_ownership
 
571
        array<T,distributed>& new_array,            // new_ownership (created)
 
572
        RepSize&              old_numbering,        // new_ownership
 
573
        RepSize&              new_numbering) const  // old_ownership
 
574
        { return base::data().repartition (partition.data(), new_array.data(), old_numbering.data(), new_numbering.data()); }
 
575
 
 
576
    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)
 
580
        { base::data().permutation_apply (new_numbering.data(), new_array.data()); }
 
581
 
 
582
// i/o:
 
583
 
 
584
    odiststream& put_values (odiststream& ops) const { return base::data().put_values(ops); }
 
585
    idiststream& get_values (idiststream& ips)       { return base::data().get_values(ips); }
 
586
    void dump (std::string name) const      { return base::data().dump(name); }
 
587
 
334
588
    template <class GetFunction>
335
 
    iparstream& get (iparstream& ips, GetFunction get_element) {
336
 
        return basic_array<array_mpi_rep<T> >::data().get(ips, get_element); }
337
 
    template <class PutFunction>
338
 
    oparstream& put (oparstream& ops, PutFunction put_element) const {
339
 
        return basic_array<array_mpi_rep<T> >::data().put(ops, put_element); }
340
 
    template <class PutFunction>
341
 
    oparstream& permuted_put (oparstream& ops, const array<size_type,distributed>& perm, PutFunction put_element) const {
342
 
        return basic_array<array_mpi_rep<T> >::data().permuted_put (ops, perm.data(), put_element); }
 
589
    idiststream& get_values (idiststream& ips, GetFunction get_element)       { return base::data().get_values(ips, get_element); }
 
590
    template <class PutFunction>
 
591
    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 
 
594
                                                                     { return base::data().permuted_put_values (ops, perm.data(), put_element); }
343
595
};
344
596
//>verbatim:
345
 
#endif // _RHEOLEF_HAVE_MPI
346
 
 
347
 
// inputs/outputs:
348
 
template <class T, class M>
349
 
iparstream& operator >> (iparstream& s, array<T,M>& x);
350
 
 
351
 
template <class T, class M>
352
 
oparstream& operator << (oparstream& s, const array<T,M>& x);
353
 
// -------------------------------------------------------------
354
 
// inline'd : basic_array
355
 
// -------------------------------------------------------------
356
 
template <class R>
357
 
inline
358
 
basic_array<R>::basic_array (
359
 
        size_type          par_size,
360
 
        const value_type&  init_val)
361
 
 : smart_pointer<R> (new_macro(R(par_size,init_val)))
362
 
{
363
 
}
364
 
template <class R>
365
 
inline
366
 
void
367
 
basic_array<R>::resize (
368
 
        size_type          par_size,
369
 
        const value_type&  init_val)
370
 
{
371
 
    smart_pointer<R>::data().resize(par_size,init_val);
372
 
}
373
 
template <class R>
374
 
inline
375
 
basic_array<R>::basic_array (
376
 
        const distributor& ownership,
377
 
        const T&           init_val)
378
 
 : smart_pointer<R> (new_macro(R(ownership,init_val)))
379
 
{
380
 
}
381
 
template <class R>
382
 
inline
383
 
void
384
 
basic_array<R>::resize (
385
 
        const distributor& ownership,
386
 
        const T&           init_val)
387
 
{
388
 
    smart_pointer<R>::data().resize(ownership,init_val);
389
 
}
390
 
template <class R>
391
 
inline
392
 
const distributor&
393
 
basic_array<R>::ownership () const
394
 
{
395
 
    return smart_pointer<R>::data().ownership();
396
 
}
397
 
template <class R>
398
 
inline
399
 
const typename basic_array<R>::communicator_type&
400
 
basic_array<R>::comm () const
401
 
{
402
 
    return ownership().comm();
403
 
}
404
 
template <class R>
405
 
inline
406
 
typename basic_array<R>::size_type
407
 
basic_array<R>::last_index () const 
408
 
{
409
 
    return smart_pointer<R>::data().last_index();
410
 
}
411
 
template <class R>
412
 
inline
413
 
typename basic_array<R>::size_type
414
 
basic_array<R>::first_index () const 
415
 
{
416
 
    return smart_pointer<R>::data().first_index();
417
 
}
418
 
template <class R>
419
 
inline
420
 
typename basic_array<R>::size_type
421
 
basic_array<R>::size () const
422
 
{
423
 
    return smart_pointer<R>::data().size();
424
 
}
425
 
template <class R>
426
 
inline
427
 
typename basic_array<R>::size_type
428
 
basic_array<R>::par_size () const
429
 
{
430
 
    return smart_pointer<R>::data().par_size();
431
 
}
432
 
template <class R>
433
 
inline
434
 
typename basic_array<R>::iterator
435
 
basic_array<R>::begin ()
436
 
{
437
 
    return smart_pointer<R>::data().begin();
438
 
}
439
 
template <class R>
440
 
inline
441
 
typename basic_array<R>::iterator
442
 
basic_array<R>::end ()
443
 
{
444
 
    return smart_pointer<R>::data().end();
445
 
}
446
 
template <class R>
447
 
inline
448
 
typename basic_array<R>::const_iterator
449
 
basic_array<R>::begin () const
450
 
{
451
 
    return smart_pointer<R>::data().begin();
452
 
}
453
 
template <class R>
454
 
inline
455
 
typename basic_array<R>::const_iterator
456
 
basic_array<R>::end () const
457
 
{
458
 
    return smart_pointer<R>::data().end();
459
 
}
460
 
template <class R>
461
 
inline
462
 
void
463
 
basic_array<R>::assembly_begin ()
464
 
{
465
 
    smart_pointer<R>::data().assembly_begin();
466
 
}
467
 
template <class R>
468
 
inline
469
 
void
470
 
basic_array<R>::assembly_end ()
471
 
{
472
 
    smart_pointer<R>::data().assembly_end();
473
 
}
474
 
template <class R>
475
 
inline
476
 
void
477
 
basic_array<R>::assembly()
478
 
{
479
 
    smart_pointer<R>::data().assembly_begin();
480
 
    smart_pointer<R>::data().assembly_end();
481
 
}
482
 
template<class R>
483
 
template<class RepSize>
484
 
inline
485
 
void
486
 
basic_array<R>::repartition (
487
 
        const RepSize&  partition,
488
 
        basic_array<R>& new_array,
489
 
        RepSize&        old_numbering,
490
 
        RepSize&        new_numbering) const
491
 
{
492
 
    smart_pointer<R>::data().repartition(
493
 
        partition.data(),
494
 
        new_array.data(),
495
 
        old_numbering.data(),
496
 
        new_numbering.data());
497
 
}
498
 
template <class R>
499
 
inline
500
 
void
501
 
basic_array<R>::set (size_type i, const value_type& val)
502
 
{
503
 
    smart_pointer<R>::data().set(i, val);
504
 
}
505
 
template <class R>
506
 
inline
507
 
typename basic_array<R>::reference
508
 
basic_array<R>::operator[] (size_type i) 
509
 
{
510
 
    return smart_pointer<R>::data().operator[] (i);
511
 
}
512
 
template <class R>
513
 
inline
514
 
typename basic_array<R>::const_reference
515
 
basic_array<R>::operator[] (size_type i) const
516
 
{
517
 
    return smart_pointer<R>::data().operator[] (i);
518
 
}
519
 
template <class R>
520
 
inline
521
 
void
522
 
basic_array<R>::dump (std::string name) const
523
 
{
524
 
    return smart_pointer<R>::data().dump (name);
525
 
}
526
 
// ===========================================================
527
 
// inlined : array
528
 
// ===========================================================
529
 
template <class T>
530
 
inline
531
 
array<T,sequential>::array (size_type par_size, const T&  init_val)
532
 
  : basic_array<array_seq_rep<T> >(par_size,init_val)
533
 
{
534
 
}
535
 
template <class T>
536
 
inline
537
 
array<T,sequential>::array (const distributor&  ownership, const T&  init_val)
538
 
  : basic_array<array_seq_rep<T> >(ownership,init_val)
539
 
{
540
 
}
541
 
#ifdef _RHEOLEF_HAVE_MPI
542
 
template <class T>
543
 
inline
544
 
array<T,distributed>::array (size_type par_size, const T&  init_val)
545
 
  : basic_array<array_mpi_rep<T> >(par_size,init_val)
546
 
{
547
 
}
548
 
template <class T>
549
 
inline
550
 
array<T,distributed>::array (const distributor&  ownership, const T&  init_val)
551
 
  : basic_array<array_mpi_rep<T> >(ownership,init_val)
552
 
{
553
 
}
554
 
#endif // _RHEOLEF_HAVE_MPI
555
 
 
556
 
template <class T>
557
 
inline
558
 
iparstream&
559
 
operator >> (iparstream& ips,  array<T,sequential>& x)
560
 
561
 
    return x.get(ips); 
562
 
}
563
 
template <class T> 
564
 
inline
565
 
oparstream&
566
 
operator << (oparstream& ops, const array<T,sequential>& x)
567
 
{
568
 
    return x.put(ops);
569
 
}
570
 
#ifdef _RHEOLEF_HAVE_MPI
571
 
template <class T>
572
 
inline
573
 
iparstream&
574
 
operator >> (iparstream& ips,  array<T,distributed>& x)
575
 
576
 
    return x.get(ips); 
577
 
}
578
 
template <class T> 
579
 
inline
580
 
oparstream&
581
 
operator << (oparstream& ops, const array<T,distributed>& x)
582
 
{
583
 
    return x.put(ops);
 
597
template <class T>
 
598
inline
 
599
array<T,distributed>::array (
 
600
        const distributor& ownership,
 
601
        const T&           init_val)
 
602
 : base(new_macro(rep(ownership,init_val)))
 
603
{
 
604
}
 
605
template <class T>
 
606
inline
 
607
void
 
608
array<T,distributed>::resize (
 
609
        const distributor& ownership,
 
610
        const T         &  init_val)
 
611
{
 
612
  base::data().resize (ownership,init_val);
 
613
}
 
614
#endif // _RHEOLEF_HAVE_MPI
 
615
 
 
616
// -------------------------------------------------------------
 
617
// i/o with operator<< & >>
 
618
// -------------------------------------------------------------
 
619
template <class T>
 
620
inline
 
621
idiststream&
 
622
operator >> (idiststream& ips,  array<T,sequential>& x)
 
623
 
624
    return x.get_values(ips); 
 
625
}
 
626
template <class T> 
 
627
inline
 
628
odiststream&
 
629
operator << (odiststream& ops, const array<T,sequential>& x)
 
630
{
 
631
    return x.put_values(ops);
 
632
}
 
633
#ifdef _RHEOLEF_HAVE_MPI
 
634
template <class T>
 
635
inline
 
636
idiststream&
 
637
operator >> (idiststream& ips,  array<T,distributed>& x)
 
638
 
639
    return x.get_values(ips); 
 
640
}
 
641
template <class T> 
 
642
inline
 
643
odiststream&
 
644
operator << (odiststream& ops, const array<T,distributed>& x)
 
645
{
 
646
    return x.put_values(ops);
584
647
}
585
648
#endif // _RHEOLEF_HAVE_MPI
586
649
} // namespace rheolef