2
/// This file is part of Rheolef.
4
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
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.
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.
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
20
/// =========================================================================
22
// Maquette d'une classe geo avec type elements varies (polymorphe)
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
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
39
// test: on construit sur le proc=0 et envoie au proc=1 qui depaquette
41
// Author: Pierre.Saramito@imag.fr
45
#include "rheolef/config.h"
46
#ifndef _RHEOLEF_HAVE_MPI
47
int main() { return 0; }
48
#else // _RHEOLEF_HAVE_MPI
50
#include "rheolef/array.h"
51
#include <boost/array.hpp>
52
#include <boost/ptr_container/ptr_container.hpp>
54
// =====================================================================
55
class geo_element : boost::noncopyable {
57
typedef std::vector<int>::size_type size_type;
69
static char tab_name [enum_type_max];
71
virtual ~geo_element () {}
72
virtual enum_type type() const = 0;
73
virtual char name() const = 0;
74
virtual size_type size() const = 0;
75
virtual size_type dimension() const = 0;
76
virtual size_type operator[] (size_type i) const = 0;
77
virtual size_type& operator[] (size_type i) = 0;
79
virtual geo_element* do_clone() const = 0;
80
geo_element* clone() const { return do_clone(); }
81
geo_element* new_clone (const geo_element& K) { return K.clone(); }
83
char geo_element::tab_name [geo_element::enum_type_max] = {'p', 'e', 't', 'q', 'T', 'P', 'H'};
86
operator<< (std::ostream& os, const geo_element& K) {
87
os << K.name() << "\t";
88
for (geo_element::size_type iloc = 0; iloc < K.size(); iloc++) {
90
if (iloc < K.size() - 1) os << " ";
94
template <class Array>
96
dump (const geo_element& K1, Array& K2) {
97
check_macro (K1.size() == K2.size(), "invalid element sizes: K1.size="<<K1.size()<<" and K2.size="<<K2.size());
98
for (geo_element::size_type iloc = 0; iloc < K1.size(); iloc++) {
102
class geo_element_t : public geo_element {
103
static const enum_type _type = t;
104
static const char _name = 't';
105
static const size_type _size = 3;
106
static const size_type _dim = 2;
108
typedef boost::array<size_type,_size> array_type;
110
geo_element_t () /* : geo_element() */ {
111
for (size_type iloc = 0; iloc < size(); iloc++) {
112
_vertex[iloc] = std::numeric_limits<size_type>::max();
115
geo_element_t (size_type a, size_type b, size_type c) : geo_element() {
120
geo_element_t (const array_type& K) { _vertex = K; }
121
geo_element* do_clone() const {
122
return new geo_element_t (_vertex[0], _vertex[1], _vertex[2]);
124
enum_type type() const { return _type; };
125
char name() const { return _name; };
126
size_type size() const { return _size; }
127
size_type dimension() const { return _dim; };
128
size_type operator[] (size_type i) const { return _vertex[i]; }
129
size_type& operator[] (size_type i) { return _vertex[i]; }
130
template<class Archive>
131
void serialize (Archive& ar, const unsigned int version) {
132
for (size_type iloc = 0; iloc < size(); iloc++) {
140
// =====================================================================
141
class geo_element_q : public geo_element {
142
static const enum_type _type = q;
143
static const char _name = 'q';
144
static const size_type _size = 4;
145
static const size_type _dim = 2;
147
typedef boost::array<size_type,_size> array_type;
148
geo_element_q () : geo_element() {
149
for (size_type iloc = 0; iloc < size(); iloc++) {
150
_vertex[iloc] = std::numeric_limits<size_type>::max();
153
geo_element_q (size_type a, size_type b, size_type c, size_type d) : geo_element() {
159
geo_element_q (const array_type& K) { _vertex = K; }
160
geo_element* do_clone() const {
161
return new geo_element_q (_vertex[0], _vertex[1], _vertex[2], _vertex[3]);
163
enum_type type() const { return _type; };
164
char name() const { return _name; };
165
size_type size() const { return _size; }
166
size_type dimension() const { return _dim; };
167
size_type operator[] (size_type i) const { return _vertex[i]; }
168
size_type& operator[] (size_type i) { return _vertex[i]; }
169
template<class Archive>
170
void serialize (Archive& ar, const unsigned int version) {
171
for (size_type iloc = 0; iloc < size(); iloc++) {
179
} // namespace rheolef
180
// =====================================================================
181
// Some serializable types, like geo_element, have a fixed amount of data stored at fixed field positions.
182
// When this is the case, boost::mpi can optimize their serialization and transmission to avoid extraneous
184
// To enable this optimization, we specialize the type trait is_mpi_datatype, e.g.:
187
template <> struct is_mpi_datatype<rheolef::geo_element_t> : mpl::true_ { };
188
template <> struct is_mpi_datatype<rheolef::geo_element_q> : mpl::true_ { };
192
// =====================================================================
193
// classe polymorphe & MPI
194
// =====================================================================
196
using namespace rheolef;
199
struct my_polymorphic_geo {
200
typedef boost::ptr_vector<geo_element>::size_type size_type;
201
typedef boost::ptr_vector<geo_element>::iterator iterator;
202
typedef boost::ptr_vector<geo_element>::const_iterator const_iterator;
203
my_polymorphic_geo () : _x(), _comm() {
204
fill (_count_by_type, _count_by_type+geo_element::enum_type_max, 0);
205
if (_comm.rank() == 0) {
206
_x.push_back (new geo_element_t (1,2,3));
207
_x.push_back (new geo_element_q (11,12,13,14));
208
_x.push_back (new geo_element_t (4,5,6));
209
_x.push_back (new geo_element_q (15,16,17,18));
210
_x.push_back (new geo_element_t (7,8,9));
211
_count_by_type [geo_element::t] = 3;
212
_count_by_type [geo_element::q] = 2;
216
cout << "geo " << _x.size() << endl;
217
for (size_t i = 0; i < _x.size(); i++) {
218
const geo_element& K = _x[i];
220
const std::type_info& rtti = typeid(K);
221
cerr << "type " << rtti.name() << ": " << K << endl;
227
pair<size_type,size_type> count_tag_pair [size_type(geo_element::enum_type_max)];
229
if (_comm.rank() == 0) {
230
for (size_type i = 0; i < size_type(geo_element::enum_type_max); i++) {
231
size_type tag = 100+i;
232
count_tag_pair [i] = make_pair(_count_by_type[i], tag);
234
_comm.send (1, tag_count, count_tag_pair, size_type(geo_element::enum_type_max));
236
vector<pair<size_type,geo_element_t::array_type> > buffer_t (_count_by_type[geo_element::t]);
237
vector<pair<size_type,geo_element_q::array_type> > buffer_q (_count_by_type[geo_element::q]);
238
vector<size_type> last_by_type (geo_element::enum_type_max, 0);
239
for (size_type ie = 0; ie < _x.size(); ie++) {
240
const geo_element& K = _x[ie];
241
size_type ibuf = last_by_type[K.type()];
242
last_by_type[K.type()]++;
247
case geo_element::t: {
248
buffer_t[ibuf].first = ie;
249
dump (_x[ie], buffer_t[ibuf].second);
255
case geo_element::q: {
256
buffer_q[ibuf].first = ie;
257
dump (_x[ie], buffer_q[ibuf].second);
261
error_macro ("unexpected element " << geo_element::tab_name[K.type()]);
268
if (count_tag_pair[geo_element::t].first != 0) {
270
count_tag_pair[geo_element::t].second,
271
buffer_t.begin().operator->(),
272
count_tag_pair[geo_element::t].first);
277
if (count_tag_pair[geo_element::q].first != 0) {
279
count_tag_pair[geo_element::q].second,
280
buffer_q.begin().operator->(),
281
count_tag_pair[geo_element::q].first);
283
} else if (_comm.rank() == 1) {
284
_comm.recv (0, tag_count, count_tag_pair, size_type(geo_element::enum_type_max));
285
vector<pair<size_type,geo_element_t::array_type> > buffer_t (count_tag_pair[geo_element::t].first);
286
vector<pair<size_type,geo_element_q::array_type> > buffer_q (count_tag_pair[geo_element::q].first);
287
size_type total_size = 0;
288
for (size_type i = 0; i < size_type(geo_element::enum_type_max); i++) {
289
_count_by_type[i] = count_tag_pair [i].first;
290
total_size += _count_by_type[i];
292
_x.reserve (total_size);
295
_x.resize (total_size);
297
for (size_type j = 0; j < total_size; j++) {
298
_x.push_back (new geo_element_t);
304
if (count_tag_pair[geo_element::t].first != 0) {
306
count_tag_pair[geo_element::t].second,
307
buffer_t.begin().operator->(),
308
count_tag_pair[geo_element::t].first);
309
for (size_type ibuf = 0; ibuf < buffer_t.size(); ibuf++) {
310
size_type ie = buffer_t[ibuf].first;
311
//_x.insert (_x.begin()+ie, new geo_element_t (buffer_t[ibuf].second));
312
//warning_macro ("replace["<<ie<<"]="<<buffer_t[ibuf].second);
313
check_macro (!_x.is_null(ie), "is_null "<<ie);
314
_x.replace (_x.begin()+ie, new geo_element_t (buffer_t[ibuf].second));
320
if (count_tag_pair[geo_element::q].first != 0) {
322
count_tag_pair[geo_element::q].second,
323
buffer_q.begin().operator->(),
324
count_tag_pair[geo_element::q].first);
325
for (size_type ibuf = 0; ibuf < buffer_q.size(); ibuf++) {
326
size_type ie = buffer_q[ibuf].first;
327
//_x.insert (_x.begin()+ie, new geo_element_q (buffer_q[ibuf].second));
328
//warning_macro ("replace["<<ie<<"]="<<buffer_q[ibuf].second);
329
check_macro (!_x.is_null(ie), "is_null "<<ie);
330
_x.replace (_x.begin()+ie, new geo_element_q(buffer_q[ibuf].second));
337
boost::ptr_vector<geo_element> _x;
338
mpi::communicator _comm;
339
size_type _count_by_type [geo_element::enum_type_max];
341
int main(int argc, char**argv) {
342
environment distributed(argc, argv);
343
mpi::communicator comm;
344
if (comm.size() == 1) {
345
cerr << "not sequential : use mpirun -np 2 !" << endl;
348
my_polymorphic_geo omega;
351
#endif // _RHEOLEF_HAVE_MPI