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/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;
59
static size_t dummy = size_t(-1);
61
char uu [2] = {'a','b'};
65
typedef std::vector<int>::size_type size_type;
77
static char tab_name [enum_type_max];
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;
86
char geo_element::tab_name [geo_element::enum_type_max] = {'p', 'e', 't', 'q', 'T', 'P', 'H'};
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++) {
93
if (iloc < K.size() - 1) os << " ";
97
class geo_element_t : public geo_element {
99
geo_element_t () : geo_element() {
100
for (size_type iloc = 0; iloc < size(); iloc++) {
101
_vertex[iloc] = std::numeric_limits<size_type>::max();
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];
109
geo_element_t& operator= (const geo_element_t& K) {
110
for (size_type iloc = 0; iloc < size(); iloc++) {
111
_vertex[iloc] = K[iloc];
115
geo_element_t (size_type a, size_type b, size_type c) : geo_element() {
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) {
134
size_type _vertex[3];
136
class geo_element_q : public geo_element {
138
geo_element_q () : geo_element() {
139
for (size_type iloc = 0; iloc < size(); iloc++) {
140
_vertex[iloc] = std::numeric_limits<size_type>::max();
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];
148
geo_element_q& operator= (const geo_element_q& K) {
149
for (size_type iloc = 0; iloc < size(); iloc++) {
150
_vertex[iloc] = K[iloc];
154
geo_element_q (size_type a, size_type b, size_type c, size_type d) : geo_element() {
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) {
175
size_type _vertex[4];
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;
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]);
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];
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]; }
207
cout << "geo " << _x.size() << endl;
208
for (size_t i = 0; i < _x.size(); i++) {
209
const geo_element& K = _x[i];
214
pair<size_type,size_type> count_tag_pair [size_type(geo_element::enum_type_max)];
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);
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);
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;
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];
238
_comm.send (1, i_msg_tag, buffer.begin().operator->(), i_msg_size);
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];
248
_comm.send (1, i_msg_tag, buffer.begin().operator->(), i_msg_size);
252
error_macro ("unexpected element " << geo_element::tab_name[i]);
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);
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;
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]));
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]));
291
error_macro ("unexpected element " << geo_element::tab_name[i]);
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];
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;
311
my_polymorphic_geo omega;
314
#endif // _RHEOLEF_HAVE_MPI