~ubuntu-branches/ubuntu/trusty/rheolef/trusty

« back to all changes in this revision

Viewing changes to skit/ptst2/mpi_boost_polymorphe_tst.cc

  • Committer: Package Import Robot
  • Author(s): Pierre Saramito
  • Date: 2012-04-06 09:12:21 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20120406091221-m58me99p1nxqui49
Tags: 6.0-1
* New upstream release 6.0 (major changes):
  - massively distributed and parallel support
  - full FEM characteristic method (Lagrange-Gakerkin method) support
  - enhanced users documentation 
  - source code supports g++-4.7 (closes: #667356)
* debian/control: dependencies for MPI distributed solvers added
* debian/rules: build commands simplified
* debian/librheolef-dev.install: man1/* to man9/* added
* debian/changelog: package description rewritted (closes: #661689)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
///
2
 
/// This file is part of Rheolef.
3
 
///
4
 
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
5
 
///
6
 
/// Rheolef is free software; you can redistribute it and/or modify
7
 
/// it under the terms of the GNU General Public License as published by
8
 
/// the Free Software Foundation; either version 2 of the License, or
9
 
/// (at your option) any later version.
10
 
///
11
 
/// Rheolef is distributed in the hope that it will be useful,
12
 
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
/// GNU General Public License for more details.
15
 
///
16
 
/// You should have received a copy of the GNU General Public License
17
 
/// along with Rheolef; if not, write to the Free Software
18
 
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
///
20
 
/// =========================================================================
21
 
//
22
 
// Maquette d'une classe geo avec type elements varies (polymorphe)
23
 
//  1-ere version
24
 
//
25
 
// MPI: on envoie les elements par groupes de type HPTqtep homogenes
26
 
// ce qui fait que ca reste performant du point de vue MPI
27
 
//
28
 
// limitation:
29
 
//  * Les elements ont supposes ici consecutifs.
30
 
//  * Pour s'etendre au cas des variantes curvilignes (Hc,...,qc,tc)
31
 
//    cela pose un probleme, car les elements touchant la frontiere 
32
 
//    ne sont pas consecutifs par numeros.
33
 
//    On pourrait renumeroter tous les elements apres l'identification
34
 
//    de la frontiere, mais on peut eviter cette renumerotation tardive.
35
 
//  * Pour faire sauter l'hypothese des consecutif,
36
 
//    on peut aussi envoyer une paire (index,element) puis ranger x(index) = element
37
 
//  => c'est l'etape suivante
38
 
//
39
 
// test: on construit sur le proc=0 et envoie au proc=1 qui depaquette
40
 
//
41
 
// Author: Pierre.Saramito@imag.fr
42
 
//
43
 
// Date: 14 dec 2010
44
 
//
45
 
#include "rheolef/config.h"
46
 
#ifndef _RHEOLEF_HAVE_MPI
47
 
int main() { return 0; }
48
 
#else // _RHEOLEF_HAVE_MPI
49
 
 
50
 
#include "rheolef/array.h"
51
 
#include <boost/serialization/export.hpp>
52
 
#include <boost/ptr_container/ptr_container.hpp>
53
 
#include <boost/ptr_container/serialize_ptr_vector.hpp>
54
 
#include <boost/archive/text_oarchive.hpp>
55
 
#include <boost/archive/text_iarchive.hpp>
56
 
using namespace rheolef;
57
 
using namespace std;
58
 
 
59
 
static size_t dummy = size_t(-1);
60
 
 
61
 
char uu [2] = {'a','b'};
62
 
 
63
 
class geo_element {
64
 
public:
65
 
    typedef std::vector<int>::size_type size_type;
66
 
    typedef enum {
67
 
        p = 0, 
68
 
        e = 1, 
69
 
        t = 2, 
70
 
        q = 3, 
71
 
        T = 4, 
72
 
        P = 5, 
73
 
        H = 6, 
74
 
        enum_type_max = 7 
75
 
    } enum_type; 
76
 
 
77
 
    static char tab_name [enum_type_max];
78
 
 
79
 
    virtual enum_type type() const = 0;
80
 
    virtual char      name() const = 0;
81
 
    virtual size_type size() const = 0;
82
 
    virtual size_type dimension() const = 0;
83
 
    virtual size_type  operator[] (size_type i) const = 0;
84
 
    virtual size_type& operator[] (size_type i)       = 0;
85
 
};
86
 
char geo_element::tab_name [geo_element::enum_type_max] = {'p', 'e', 't', 'q', 'T', 'P', 'H'};
87
 
inline
88
 
std::ostream&
89
 
operator<< (std::ostream& os, const geo_element& K) {
90
 
        os << K.name() << "\t";
91
 
        for (geo_element::size_type iloc = 0; iloc < K.size(); iloc++) {
92
 
          os << K[iloc];
93
 
          if (iloc < K.size() - 1) os << " ";
94
 
        }
95
 
        return os;
96
 
}
97
 
class geo_element_t : public geo_element {
98
 
public:
99
 
    geo_element_t () : geo_element() { 
100
 
        for (size_type iloc = 0; iloc < size(); iloc++) {
101
 
            _vertex[iloc] = std::numeric_limits<size_type>::max();
102
 
        }
103
 
    }
104
 
    geo_element_t (const geo_element_t& K) : geo_element() {    
105
 
        for (size_type iloc = 0; iloc < size(); iloc++) {
106
 
            _vertex[iloc] = K[iloc];
107
 
        }
108
 
    }
109
 
    geo_element_t& operator= (const geo_element_t& K) {
110
 
        for (size_type iloc = 0; iloc < size(); iloc++) {
111
 
            _vertex[iloc] = K[iloc];
112
 
        }
113
 
        return *this;
114
 
    }
115
 
    geo_element_t (size_type a, size_type b, size_type c) : geo_element() {
116
 
        _vertex[0] = a;
117
 
        _vertex[1] = b;
118
 
        _vertex[2] = c;
119
 
    } 
120
 
    enum_type type() const     { return  t; };
121
 
    char      name() const     { return 't'; };
122
 
    size_type size() const     { return  3; }
123
 
    size_type dimension() const { return 2; };
124
 
    size_type  operator[] (size_type i) const { return _vertex[i]; }
125
 
    size_type& operator[] (size_type i)       { return _vertex[i]; }
126
 
    template<class Archive>
127
 
    void serialize (Archive& ar, const unsigned int version) {
128
 
        ar & _vertex[0];
129
 
        ar & _vertex[1];
130
 
        ar & _vertex[2];
131
 
    }
132
 
// data:
133
 
protected:
134
 
    size_type _vertex[3];
135
 
};
136
 
class geo_element_q : public geo_element {
137
 
public:
138
 
    geo_element_q () : geo_element() { 
139
 
        for (size_type iloc = 0; iloc < size(); iloc++) {
140
 
            _vertex[iloc] = std::numeric_limits<size_type>::max();
141
 
        }
142
 
    }
143
 
    geo_element_q (const geo_element_t& K) : geo_element() {    
144
 
        for (size_type iloc = 0; iloc < size(); iloc++) {
145
 
            _vertex[iloc] = K[iloc];
146
 
        }
147
 
    }
148
 
    geo_element_q& operator= (const geo_element_q& K) {
149
 
        for (size_type iloc = 0; iloc < size(); iloc++) {
150
 
            _vertex[iloc] = K[iloc];
151
 
        }
152
 
        return *this;
153
 
    }
154
 
    geo_element_q (size_type a, size_type b, size_type c, size_type d) : geo_element() {
155
 
        _vertex[0] = a;
156
 
        _vertex[1] = b;
157
 
        _vertex[2] = c;
158
 
        _vertex[3] = d;
159
 
    } 
160
 
    enum_type type() const      { return  q; };
161
 
    char      name() const      { return 'q'; };
162
 
    size_type size() const      { return  4; }
163
 
    size_type dimension() const { return  2; };
164
 
    size_type  operator[] (size_type i) const { return _vertex[i]; }
165
 
    size_type& operator[] (size_type i)       { return _vertex[i]; }
166
 
    template<class Archive> 
167
 
    void serialize (Archive& ar, const unsigned int version) {
168
 
        ar & _vertex[0];
169
 
        ar & _vertex[1];
170
 
        ar & _vertex[2];
171
 
        ar & _vertex[3];
172
 
    }
173
 
// data:
174
 
protected:
175
 
    size_type _vertex[4];
176
 
};
177
 
struct my_polymorphic_geo {
178
 
  typedef boost::ptr_vector<geo_element>::size_type size_type;
179
 
  typedef boost::ptr_vector<geo_element>::iterator iterator;
180
 
  typedef boost::ptr_vector<geo_element>::const_iterator const_iterator;
181
 
  my_polymorphic_geo () : _x(), _comm() {
182
 
    fill (_count_by_type, _count_by_type+geo_element::enum_type_max, 0);
183
 
    if (_comm.rank() == 0) {
184
 
      _x.push_back (new geo_element_t (1,2,3));
185
 
      _x.push_back (new geo_element_t (4,5,6));
186
 
      _x.push_back (new geo_element_q (11,12,13,14));
187
 
      _x.push_back (new geo_element_q (15,16,17,18));
188
 
      _count_by_type [geo_element::t] = 2;
189
 
      _count_by_type [geo_element::q] = 2;
190
 
      reset_starters();
191
 
      for (size_type i = 0; i < size_type(geo_element::enum_type_max); i++) {
192
 
        warning_macro ("init count " << geo_element::tab_name[i] << " " << _count_by_type [i]);
193
 
      }
194
 
    }
195
 
  }
196
 
  void reset_starters () {
197
 
      _start_by_type [0] = 0;
198
 
      for (size_type i = 0; i < size_type(geo_element::enum_type_max); i++) {
199
 
        _start_by_type [i+1] = _start_by_type [i] + _count_by_type [i];
200
 
      }
201
 
  }
202
 
  iterator begin (geo_element::enum_type typ) { return _x.begin() + _start_by_type[size_type(typ)]; }
203
 
  iterator end   (geo_element::enum_type typ) { return _x.begin() + _start_by_type[size_type(typ)+1]; }
204
 
  const_iterator begin (geo_element::enum_type typ) const { return _x.begin() + _start_by_type[size_type(typ)]; }
205
 
  const_iterator end   (geo_element::enum_type typ) const { return _x.begin() + _start_by_type[size_type(typ)+1]; }
206
 
  void put () const {
207
 
    cout << "geo " << _x.size() << endl;
208
 
    for (size_t i = 0; i < _x.size(); i++) {
209
 
      const geo_element& K = _x[i];
210
 
      cout << K << endl;
211
 
    }
212
 
  }
213
 
  void test_mpi () {
214
 
    pair<size_type,size_type> count_tag_pair [size_type(geo_element::enum_type_max)];
215
 
    int tag_count = 0;
216
 
    if (_comm.rank() == 0) {
217
 
      for (size_type i = 0; i < size_type(geo_element::enum_type_max); i++) {
218
 
        size_type tag = 100+i;
219
 
        count_tag_pair [i] = make_pair(_count_by_type[i], tag);
220
 
      }
221
 
      for (size_type i = 0; i < size_type(geo_element::enum_type_max); i++) {
222
 
        warning_macro ("send count " << geo_element::tab_name[i] << " " << count_tag_pair [i].first);
223
 
      }
224
 
      _comm.send (1, tag_count, count_tag_pair, size_type(geo_element::enum_type_max));
225
 
      for (size_type i = 0; i < size_type(geo_element::enum_type_max); i++) {
226
 
        size_type i_msg_size = count_tag_pair [i].first;
227
 
        size_type i_msg_tag  = count_tag_pair [i].second;
228
 
        if (i_msg_size == 0) continue;
229
 
        // envoi
230
 
        switch (geo_element::enum_type(i)) {
231
 
          case geo_element::t: {
232
 
            vector<geo_element_t> buffer (i_msg_size);
233
 
            for (size_type j = 0; j < i_msg_size; j++) {
234
 
              for (size_type k = 0; k < 3; k++) {
235
 
                buffer[j][k] = _x[_start_by_type[i]+j][k];
236
 
              }
237
 
            }
238
 
            _comm.send (1, i_msg_tag, buffer.begin().operator->(), i_msg_size);
239
 
            break;
240
 
          }
241
 
          case geo_element::q: {
242
 
            vector<geo_element_q> buffer (i_msg_size);
243
 
            for (size_type j = 0; j < i_msg_size; j++) {
244
 
              for (size_type k = 0; k < 4; k++) {
245
 
                buffer[j][k] = _x[_start_by_type[i]+j][k];
246
 
              }
247
 
            }
248
 
            _comm.send (1, i_msg_tag, buffer.begin().operator->(), i_msg_size);
249
 
            break;
250
 
          }
251
 
          default : {
252
 
            error_macro ("unexpected element " << geo_element::tab_name[i]);
253
 
          }
254
 
        }
255
 
      }
256
 
    } else if (_comm.rank() == 1) {
257
 
      _comm.recv (0, tag_count, count_tag_pair, size_type(geo_element::enum_type_max));
258
 
      for (size_type i = 0; i < size_type(geo_element::enum_type_max); i++) {
259
 
        _count_by_type[i] = count_tag_pair [i].first;
260
 
        warning_macro ("recv count " << geo_element::tab_name[i] << " " << count_tag_pair [i].first);
261
 
      }
262
 
      reset_starters();
263
 
      _x.reserve (_start_by_type [geo_element::enum_type_max]);
264
 
      for (size_type i = 0; i < size_type(geo_element::enum_type_max); i++) {
265
 
        size_type i_msg_size = count_tag_pair [i].first;
266
 
        size_type i_msg_tag  = count_tag_pair [i].second;
267
 
        if (i_msg_size == 0) continue;
268
 
        // reception
269
 
        switch (geo_element::enum_type(i)) {
270
 
          case geo_element::t: {
271
 
            vector<geo_element_t> buffer (i_msg_size);
272
 
            _comm.recv (0, i_msg_tag, buffer.begin().operator->(), i_msg_size);
273
 
            for (size_type j = 0; j < i_msg_size; j++) {
274
 
              //_x[_start_by_type[i]+j] = buffer[j];
275
 
              //_x.push_back (buffer[j]);
276
 
              _x.push_back (new geo_element_t (buffer[j]));
277
 
            }
278
 
            break;
279
 
          }
280
 
          case geo_element::q: {
281
 
            vector<geo_element_q> buffer (i_msg_size);
282
 
            _comm.recv (0, i_msg_tag, buffer.begin().operator->(), i_msg_size);
283
 
            for (size_type j = 0; j < i_msg_size; j++) {
284
 
              //_x[_start_by_type[i]+j] = buffer[j];
285
 
              //_x.push_back (buffer[j]);
286
 
              _x.push_back (new geo_element_q (buffer[j]));
287
 
            }
288
 
            break;
289
 
          }
290
 
          default : {
291
 
            error_macro ("unexpected element " << geo_element::tab_name[i]);
292
 
          }
293
 
        }
294
 
      }
295
 
      put();
296
 
    }
297
 
  }
298
 
// data:
299
 
  boost::ptr_vector<geo_element> _x;
300
 
  mpi::communicator              _comm;
301
 
  size_type _count_by_type [geo_element::enum_type_max];
302
 
  size_type _start_by_type [geo_element::enum_type_max+1];
303
 
};
304
 
int main(int argc, char**argv) {
305
 
  environment distributed(argc, argv);
306
 
  mpi::communicator comm;
307
 
  if (comm.size() == 1) {
308
 
        cerr << "not sequential : use mpirun -np 2 !" << endl;
309
 
        return 0;
310
 
  }
311
 
  my_polymorphic_geo omega;
312
 
  omega.test_mpi();
313
 
}
314
 
#endif // _RHEOLEF_HAVE_MPI