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

« back to all changes in this revision

Viewing changes to nfem/plib/geo_mpi.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:
21
21
#include "rheolef/config.h"
22
22
#ifdef _RHEOLEF_HAVE_MPI
23
23
#include "rheolef/geo.h"
24
 
#include "rheolef/geo_domain.h"
25
 
#include "rheolef/dis_macros.h"
26
 
#include "rheolef/rheostream.h"
27
 
#include "rheolef/index_set.h"
28
24
 
29
25
namespace rheolef {
30
26
 
31
 
extern
32
 
array<polymorphic_array<geo_element>::size_type>
33
 
geo_partition (const polymorphic_array<geo_element>& elts, size_t dis_nv, size_t map_dim);
34
 
 
35
 
// --------------------------------------------------------------------------
36
 
// edges & faces renumbering subroutine 
37
 
// --------------------------------------------------------------------------
38
 
template <class PolymorphicArray>
39
 
void
40
 
geo_element_renumbering (
41
 
    const std::vector<geo_element::size_type>& new_global_vertex_owner,
42
 
    const std::vector<geo_element::size_type>& global_new_num_vert,
43
 
    const PolymorphicArray&                    ios_ge,
44
 
          size_t                               dis_nv,
45
 
          PolymorphicArray&                    ge,
46
 
          array<geo_element::size_type>&       ios_ige2dis_ige
47
 
    )
48
 
{
49
 
    using namespace std;
50
 
    typedef typename geo_element::size_type size_type;
51
 
 
52
 
    communicator comm = ios_ge.ownership().comm();
53
 
    size_type dis_nge = ios_ge.dis_size();
54
 
    vector<size_type> new_local_ge_owner (dis_nge, 0);
55
 
 
56
 
    //
57
 
    // 1) global all_reduce
58
 
    // TODO: not balanced: ge nums
59
 
    // TODO: also, not optimal: O(N) in communication, memory & CPU, instead of O(N/nproc)
60
 
    //
61
 
    for (size_type ige = 0, nge = ios_ge.size(); ige < nge; ige++) {
62
 
      const geo_element& S = ios_ge [ige];
63
 
      size_type ios_dis_ige = S.ios_dis_ie();
64
 
      size_type owner = 0;
65
 
      for (size_type iloc = 0; iloc < S.size(); iloc++) {
66
 
        size_type ios_dis_iv = S [iloc];
67
 
        assert_macro (ios_dis_iv < dis_nv, "vertex index "<<ios_dis_iv<<" is out of range [0:"<<dis_nv<<"[");
68
 
        size_type iproc = new_global_vertex_owner [ios_dis_iv];
69
 
        owner = std::max (owner,iproc);
70
 
      }
71
 
      new_local_ge_owner [ios_dis_ige] = owner;
72
 
    }
73
 
    vector<size_type> new_global_ge_owner (dis_nge, 0);
74
 
    mpi::all_reduce (
75
 
        comm,
76
 
        new_local_ge_owner.begin().operator->(),
77
 
        dis_nge,
78
 
        new_global_ge_owner.begin().operator->(),
79
 
        mpi::maximum<size_type>());
80
 
  
81
 
    distributor ios_ge_ownership = ios_ge.ownership();
82
 
    //
83
 
    // 2) redistribute the vertex partition
84
 
    //
85
 
    array<size_type> ge_partition (ios_ge_ownership);
86
 
    for (size_type ios_dis_ige = ge_partition.ownership().first_index(); ios_dis_ige < ge_partition.ownership().last_index(); ios_dis_ige++) {
87
 
      ge_partition.dis_entry (ios_dis_ige) = new_global_ge_owner[ios_dis_ige];
88
 
    }
89
 
    ge_partition.dis_entry_assembly();
90
 
 
91
 
    array<size_type>  ige2ios_dis_ige;
92
 
    ios_ge.repartition (
93
 
        ge_partition,
94
 
        ge,
95
 
        ige2ios_dis_ige,
96
 
        ios_ige2dis_ige);
97
 
  
98
 
    //
99
 
    // 3) vertices S[iloc] of new numbered element table still have ios numbering: fix it
100
 
    //
101
 
    size_type first_dis_ige = ge.ownership().first_index();
102
 
    for (size_type ige = 0, nge = ge.size(); ige < nge; ige++) {
103
 
      geo_element& S = ge [ige];
104
 
      S.set_dis_ie (first_dis_ige + ige);
105
 
      for (size_type iloc = 0, nloc = S.size(); iloc < nloc; iloc++) {
106
 
        assert_macro (S[iloc] < dis_nv, "vertex index "<<S[iloc]<<" out of range [0:"<<dis_nv<<"[");
107
 
        assert_macro (global_new_num_vert[S[iloc]] < dis_nv, "new vertex index "<<global_new_num_vert[S[iloc]] <<" out of range [0:"<<dis_nv<<"[");
108
 
        S[iloc] = global_new_num_vert [S[iloc]];
109
 
      }
110
 
    }
111
 
}
112
 
// --------------------------------------------------------------------------
113
 
// io for geo
114
 
// --------------------------------------------------------------------------
115
 
template <class T>
116
 
idiststream&
117
 
geo_rep<T,distributed>::get (idiststream& ips)
118
 
{
119
 
  using namespace std;
120
 
  check_macro (ips.good(), "bad input stream for geo.");
121
 
  communicator comm = base::_geo_element[0].ownership().comm();
122
 
 
123
 
  size_type io_proc = idiststream::io_proc();
124
 
  size_type my_proc = comm.rank();
125
 
  size_type nproc   = comm.size();
126
 
  if (my_proc == io_proc && !scatch(ips.is(),"\nmesh"))
127
 
    error_macro("input stream does not contains a geo.");
128
 
  // ------------------------------------------------------------------------
129
 
  // 1) read file
130
 
  // ------------------------------------------------------------------------
131
 
  //
132
 
  // 1.1) get header
133
 
  //
134
 
  size_type dis_nv;
135
 
  size_type dis_ne;
136
 
  size_type dis_nedg = 0;
137
 
  size_type dis_n_fac = 0;
138
 
 
139
 
  base::_name = "unnamed";
140
 
 
141
 
  ips >> base::_version
142
 
      >> base::_dimension
143
 
      >> dis_nv
144
 
      >> dis_ne;
145
 
 
146
 
  if (base::_version < 2) {
147
 
    warning_macro ("mesh version < 2 no more supported in distributed version");
148
 
  } else {
149
 
    if (base::_dimension >= 3) {
150
 
      ips >> dis_n_fac;
151
 
    }
152
 
    if (base::_dimension >= 2) {
153
 
      ips >> dis_nedg;
154
 
    }
155
 
  }
156
 
  std::fill (_ios_size_by_variant, _ios_size_by_variant+reference_element::max_size, 0);
157
 
  //
158
 
  // 1.2) get coordinates
159
 
  //
160
 
  array<vertex_type> ios_vertex (dis_nv);
161
 
  ios_vertex.get_values (ips, _point_get<T>(base::_dimension));
162
 
  check_macro (ips.good(), "bad input stream for geo.");
163
 
  // set ios_dis_iv index as fisrt field of the idx_vertex pair:
164
 
  distributor ios_vertex_ownership = ios_vertex.ownership();
165
 
  polymorphic_array<geo_element> ios_geo_element_p (ios_vertex_ownership);
166
 
  size_type first_ios_dis_iv = ios_vertex.ownership().first_index();
167
 
  for (size_type ios_iv = 0, ios_nv = ios_vertex.size(); ios_iv < ios_nv; ios_iv++) {
168
 
    size_type ios_dis_iv = first_ios_dis_iv + ios_iv;
169
 
    ios_geo_element_p[ios_iv] = geo_element_p(ios_dis_iv);
170
 
    geo_element& P = ios_geo_element_p[ios_iv];
171
 
    P.set_ios_dis_ie (ios_dis_iv);
172
 
    _ios_size_by_variant [P.variant()]++;
173
 
  }
174
 
  //
175
 
  // 1.3) get elements
176
 
  //
177
 
  polymorphic_array<geo_element> ios_elts (dis_ne);
178
 
  ios_elts.get_values (ips);
179
 
  size_type ios_dis_ie_start = ios_elts.ownership().first_index();
180
 
  base::_map_dimension = 0;
181
 
  for (size_type ie = 0, ne = ios_elts.size(); ie < ne; ie++) {
182
 
    geo_element& K = ios_elts [ie];
183
 
    base::_map_dimension = std::max (K.dimension(), base::_map_dimension);
184
 
    K.set_ios_dis_ie (ios_dis_ie_start + ie);
185
 
    if (K.dimension() > 0) { // point already counted; used when dim>0 and map_dim=0
186
 
      _ios_size_by_variant [K.variant()]++;
187
 
    }
188
 
  }
189
 
  // merge:  when np > n_element, map_dim=0 on some procs without any elts...
190
 
  base::_map_dimension = mpi::all_reduce (comm, base::_map_dimension, mpi::maximum<size_type>());
191
 
  //
192
 
  // 1.4) get faces & edges
193
 
  //
194
 
  polymorphic_array<geo_element,distributed> ios_faces;
195
 
  if   (base::_version  >= 2 && base::_dimension >= 3) {
196
 
      ios_faces.resize (dis_n_fac);
197
 
      ios_faces.get_values (ips);
198
 
      size_type ios_dis_ifac_start = ios_faces.ownership().first_index();
199
 
      for (size_type ifac = 0, nfac = ios_faces.size(); ifac < nfac; ifac++) {
200
 
        geo_element& F = ios_faces [ifac];
201
 
        F.set_ios_dis_ie (ios_dis_ifac_start + ifac);
202
 
        _ios_size_by_variant [F.variant()]++;
203
 
      }
204
 
  }
205
 
  polymorphic_array<geo_element,distributed> ios_edges;
206
 
  if   (base::_version  >= 2 && base::_dimension >= 2) {
207
 
      ios_edges.resize (dis_nedg);
208
 
      ios_edges.get_values (ips);
209
 
      size_type ios_dis_iedg_start = ios_edges.ownership().first_index();
210
 
      for (size_type iedg = 0, nedg = ios_edges.size(); iedg < nedg; iedg++) {
211
 
        geo_element& E = ios_edges [iedg];
212
 
        E.set_ios_dis_ie (ios_dis_iedg_start + iedg);
213
 
        _ios_size_by_variant [E.variant()]++;
214
 
      }
215
 
  }
216
 
  // ------------------------------------------------------------------------
217
 
  // 2) mesh partition & element renumbering
218
 
  // ------------------------------------------------------------------------
219
 
  array<size_type> partition = geo_partition (ios_elts, dis_nv, map_dimension());
220
 
  //
221
 
  // 2.1) elements renumbering
222
 
  //
223
 
  array<size_type> ie2ios_dis_ie; // no more used
224
 
  ios_elts.repartition (
225
 
        partition,
226
 
        base::_geo_element[base::_map_dimension],
227
 
        ie2ios_dis_ie,
228
 
        _ios_ige2dis_ige[base::_map_dimension]);
229
 
 
230
 
  size_type first_dis_ie = base::_geo_element[base::_map_dimension].ownership().first_index();
231
 
  for (size_type ie = 0, ne = size(); ie < ne; ie++) {
232
 
    geo_element& K = operator[] (ie);
233
 
    K.set_dis_ie (first_dis_ie + ie);
234
 
  }
235
 
  // ------------------------------------------------------------------------
236
 
  // 3) vertices renumbering 
237
 
  // ------------------------------------------------------------------------
238
 
  // 3.1) global all_reduce
239
 
  // TODO: not balanced: vertex nums
240
 
  // TODO: also, not optimal: O(N) in communication, memory & CPU, instead of O(N/nproc)
241
 
  //
242
 
  vector<size_type> new_local_vertex_owner (dis_nv, 0);
243
 
  for (size_type ie = 0, ne = size(); ie < ne; ie++) {
244
 
    const geo_element& K = operator[] (ie);
245
 
    for (size_type iloc = 0; iloc < K.size(); iloc++) {
246
 
      new_local_vertex_owner [K[iloc]] = my_proc;
247
 
    }
248
 
  }
249
 
  vector<size_type> new_global_vertex_owner (dis_nv, 0);
250
 
  mpi::all_reduce (
251
 
        comm,
252
 
        new_local_vertex_owner.begin().operator->(),
253
 
        dis_nv,
254
 
        new_global_vertex_owner.begin().operator->(),
255
 
        mpi::maximum<size_type>());
256
 
 
257
 
  // 3.2) redistribute the vertex partition
258
 
  array<size_type> vertex_partition (ios_vertex.ownership());
259
 
  for (size_type ios_dis_iv = vertex_partition.ownership().first_index(); ios_dis_iv < vertex_partition.ownership().last_index(); ios_dis_iv++) {
260
 
      vertex_partition.dis_entry (ios_dis_iv) = new_global_vertex_owner[ios_dis_iv];
261
 
  }
262
 
  vertex_partition.dis_entry_assembly();
263
 
 
264
 
  array<size_type>       iv2ios_dis_iv;
265
 
  ios_geo_element_p.repartition (
266
 
        vertex_partition,
267
 
        base::_geo_element[0],
268
 
        iv2ios_dis_iv,
269
 
        _ios_ige2dis_ige[0]);
270
 
 
271
 
  distributor vertex_ownership = base::_geo_element[0].ownership();
272
 
  base::_vertex.resize (vertex_ownership);
273
 
  ios_vertex.permutation_apply (
274
 
        _ios_ige2dis_ige[0],
275
 
        base::_vertex);
276
 
 
277
 
  // 3.3) set the element[0] array 
278
 
  base::_geo_element[0].resize (vertex_ownership);
279
 
  size_type first_dis_iv = vertex_ownership.first_index();
280
 
  size_type  last_dis_iv = vertex_ownership.last_index();
281
 
  for (size_type iv = 0, nv = base::_geo_element[0].size(); iv < nv; iv++) {
282
 
    geo_element& P = base::_geo_element [0][iv];
283
 
    P[0] = first_dis_iv + iv;
284
 
    P.set_dis_ie (first_dis_iv + iv);
285
 
  }
286
 
  //
287
 
  // 3.3) vertices K[iloc] of new numbered element table K still have ios numbering: fix it
288
 
  //
289
 
  vector<size_type> local_new_num_vert (dis_nv, 0);
290
 
  for (size_type dis_iv = _ios_ige2dis_ige[0].ownership().first_index(),
291
 
                 dis_nv = _ios_ige2dis_ige[0].ownership().last_index(); 
292
 
                 dis_iv < dis_nv; dis_iv++) {
293
 
     size_type iv = dis_iv - _ios_ige2dis_ige[0].ownership().first_index();
294
 
     local_new_num_vert [dis_iv] = _ios_ige2dis_ige[0][iv];
295
 
  }
296
 
  vector<size_type> global_new_num_vert (dis_nv, 0);
297
 
  mpi::all_reduce (
298
 
        comm,
299
 
        local_new_num_vert.begin().operator->(),
300
 
        dis_nv,
301
 
        global_new_num_vert.begin().operator->(),
302
 
        mpi::maximum<size_type>());
303
 
 
304
 
  for (size_type ie = 0; ie < size(); ie++) {
305
 
    geo_element& K = operator[] (ie);
306
 
    for (size_type iloc = 0, nloc = K.size(); iloc < nloc; iloc++) {
307
 
      assert_macro (K[iloc] < dis_nv, "vertex index "<<K[iloc]<<" out of range [0:"<<dis_nv<<"[");
308
 
      assert_macro (global_new_num_vert[K[iloc]] < dis_nv, "new vertex index "<<global_new_num_vert[K[iloc]] <<" out of range [0:"<<dis_nv<<"[");
309
 
      K[iloc] = global_new_num_vert [K[iloc]];
310
 
    }
311
 
  }
312
 
  // ------------------------------------------------------------------------
313
 
  // 4) edge & face renumbering 
314
 
  // ------------------------------------------------------------------------
315
 
  if (base::_version >= 2 && base::_map_dimension >= 2) {
316
 
    geo_element_renumbering (
317
 
        new_global_vertex_owner,
318
 
        global_new_num_vert,
319
 
        ios_edges,
320
 
        dis_nv,
321
 
        base::_geo_element[1],
322
 
        _ios_ige2dis_ige[1]);
323
 
  }
324
 
  if (base::_version >= 2 && base::_map_dimension >= 3) {
325
 
    geo_element_renumbering (
326
 
        new_global_vertex_owner,
327
 
        global_new_num_vert,
328
 
        ios_faces,
329
 
        dis_nv,
330
 
        base::_geo_element[2],
331
 
        _ios_ige2dis_ige[2]);
332
 
  }
333
 
  // ------------------------------------------------------------------------
334
 
  // 6) get domain, until end-of-file (requires ios_ige2dis_ige renumbering)
335
 
  // ------------------------------------------------------------------------
336
 
  do {
337
 
    domain_indirect_basic<distributed> dom;
338
 
    bool status = dom.get (ips, *this);
339
 
    if (!status) break;
340
 
    base::_domains.push_back (dom);
341
 
  } while (true);
342
 
  // ------------------------------------------------------------------------
343
 
  // 7) external entities
344
 
  // ------------------------------------------------------------------------
345
 
  reset_size_by ();
346
 
  build_external_entities ();
347
 
  set_element_edge_index();
348
 
  set_element_face_index();
349
 
 
350
 
  /** TODO: autres champs a initialiser :
351
 
 
352
 
         _geo_element [dim]   : pour dim=1,..,map_dim-1
353
 
 
354
 
   et distributed :
355
 
        _ios_ige2dis_ige[dim] : pour dim=1,..,map_dim
356
 
   */
357
 
 
358
 
  return ips;
359
 
}
360
 
template <class T>
361
 
void
362
 
geo_rep<T,distributed>::reset_size_by ()
363
 
{
364
 
  // _ios_size_by_variant[] may also be set !
365
 
  geo_base_rep<T,distributed>::reset_size_by();
366
 
  std::fill (_ios_size_by_dimension,   _ios_size_by_dimension+4, 0);
367
 
  std::fill (_dis_size_by_dimension,   _dis_size_by_dimension+4, 0);
368
 
  std::fill (_dis_size_by_variant,     _dis_size_by_variant+reference_element::max_size, 0);
369
 
  for (size_type dim = 0; dim <= base::_map_dimension; dim++) {
370
 
    _ios_size_by_dimension [dim] = geo_element_ios_ownership(dim).size();
371
 
    _dis_size_by_dimension [dim] = base::_geo_element [dim].ownership().dis_size();
372
 
  }
373
 
  mpi::all_reduce (base::comm(), base::_size_by_variant, reference_element::max_size, _dis_size_by_variant, std::plus<size_type>());
374
 
}
375
 
/** ------------------------------------------------------------------------
376
 
 * loop on geo_element (edges, faces, etc):
377
 
 *       identify some vertices, that are referenced
378
 
 *       by locally-managed geo_elements, but these vertices are managed
379
 
 *       by another processor: e.g. vertices at a partition boundary.
380
 
 * ------------------------------------------------------------------------
381
 
 */
382
 
template <class T>
383
 
void
384
 
geo_rep<T,distributed>::build_external_entities ()
385
 
{
386
 
  distributor vertex_ownership = base::_geo_element[0].ownership();
387
 
  size_type first_dis_iv = vertex_ownership.first_index();
388
 
  size_type  last_dis_iv = vertex_ownership.last_index();
389
 
  size_type       dis_nv = vertex_ownership.dis_size();
390
 
 
391
 
  // 1) list external vertex indexes:
392
 
  std::set<size_type> ext_vertex_set;
393
 
  for (size_type dim = 1; dim <= base::_map_dimension; dim++) {
394
 
    for (size_type ige = 0, nge = base::_geo_element[dim].size(); ige < nge; ige++) {
395
 
      const geo_element& K = base::_geo_element[dim][ige];
396
 
      for (size_type iloc = 0, nloc = K.size(); iloc < nloc; iloc++) {
397
 
        assert_macro (K[iloc] < dis_nv, "vertex index "<<K[iloc]<<" out of range [0:"<<dis_nv<<"[");
398
 
        size_type dis_iv = K [iloc];
399
 
        if (dis_iv >= first_dis_iv && dis_iv < last_dis_iv) continue;
400
 
        ext_vertex_set.insert (dis_iv);
401
 
      }
402
 
    }
403
 
  }
404
 
  warning_macro ("external: ext_iv_set.size="<<ext_vertex_set.size());
405
 
  // 2) get external vertices:
406
 
  base::_vertex.get_dis_entry (
407
 
        ext_vertex_set,
408
 
        _ext_vertex);
409
 
 
410
 
  base::_geo_element[0].get_dis_entry (
411
 
        ext_vertex_set,
412
 
        _ext_geo_element_0);
413
 
}
414
 
#ifdef TO_CLEAN
415
 
// ----------------------------------------------------------
416
 
// this paradigm appears very often: x[dis_i]
417
 
// TODO: embed it directly in array<T,distributed>
418
 
// ----------------------------------------------------------
419
 
template<class T, class M>
420
 
class ext_array {};
421
 
 
422
 
template<class T>
423
 
class ext_array<T,distributed> : public array<T,distributed> {
424
 
public:
425
 
// typedef:
426
 
  typedef array<T,distributed>     base;
427
 
  typedef typename base::size_type size_type;
428
 
  typedef std::map<size_type,T>    map_type;
429
 
// allocator:
430
 
  ext_array(const distributor& ownership = distributor(), const T init_val = T())
431
 
   : base(ownership,init_val), _ext_x() {}
432
 
  void resize (const distributor& ownership = distributor(), const T init_val = T()) {
433
 
     base::resize (ownership,init_val);
434
 
     _ext_x.clear();
435
 
  }
436
 
  void set_external_indexes (const std::set<size_type>& ext_ix_set) {
437
 
    _ext_x.clear();
438
 
    base::get_dis_entry (ext_ix_set, _ext_x);
439
 
  }
440
 
// accessor:
441
 
  const T& dis_at (const size_type dis_i) const {
442
 
    if (dis_i >= base::ownership().first_index() && dis_i < base::ownership().last_index()) {
443
 
      size_type i = dis_i - base::ownership().first_index();
444
 
      return base::operator[](i);
445
 
    }
446
 
    typename map_type::const_iterator iter = _ext_x.find (dis_i);
447
 
    check_macro (iter != _ext_x.end(), "unexpected external index="<<dis_i);
448
 
    return (*iter).second;
449
 
  }
450
 
// data:
451
 
protected:
452
 
  map_type               _ext_x;
453
 
};
454
 
#endif // TO_CLEAN
455
 
/** ------------------------------------------------------------------------
456
 
 * on any 2d or 3d geo_element K, set K.dis_iedge(iloc) number
457
 
 * ------------------------------------------------------------------------
458
 
 */
459
 
template <class T>
460
 
void
461
 
geo_rep<T,distributed>::set_element_edge_index()
462
 
{
463
 
  if (map_dimension() < 2) return;
464
 
  warning_macro ("set edge...");
465
 
  size_type           nv   = geo_element_ownership(0).size();
466
 
  size_type first_dis_iv   = geo_element_ownership(0).first_index();
467
 
  size_type  last_dis_iv   = geo_element_ownership(0). last_index();
468
 
  size_type first_dis_iedg = geo_element_ownership(1).first_index();
469
 
 
470
 
  // ------------------------------------------------------------------------
471
 
  // 1) ball(X) := { E; X is a vertex of E }
472
 
  // ------------------------------------------------------------------------
473
 
  warning_macro ("set edge [1]");
474
 
  index_set empty_set; // TODO: add a global allocator to empty_set
475
 
  array<index_set,distributed> ball (geo_element_ownership(0), empty_set);
476
 
  std::set<size_t> ext_iv_set; // size=O((N/nproc)^((d-1)/d))
477
 
  for (size_type iedg = 0, nedg = geo_element_ownership(1).size(); iedg < nedg; iedg++) {
478
 
    const geo_element& E = get_geo_element (1, iedg);
479
 
    size_type dis_iedg = first_dis_iedg + iedg;
480
 
    for (size_type iloc = 0; iloc < 2; iloc++) {
481
 
      size_type dis_iv = E[iloc];
482
 
      if (dis_iv >= first_dis_iv && dis_iv < last_dis_iv) {
483
 
        size_type iv = dis_iv - first_dis_iv;
484
 
        ball [iv] += dis_iedg;
485
 
      } else {
486
 
        index_set dis_iedg_set;
487
 
        dis_iedg_set += dis_iedg;
488
 
        ball.dis_entry (dis_iv) += dis_iedg_set; // not so efficient
489
 
        ext_iv_set.insert (dis_iv);
490
 
      }
491
 
    }
492
 
  }
493
 
  ball.dis_entry_assembly (index_set_add_op<index_set,index_set>());
494
 
  // ------------------------------------------------------------------------
495
 
  // 2) for all the dis_iv that are not handled by the current process
496
 
  //    but are referenced by at least an edge, get ext_ball[dis_iv]
497
 
  // ------------------------------------------------------------------------
498
 
  // Question: faudra-t'il inclure d'autres sommets dans ext_iv_set ?
499
 
  // -> ceux issus des triangles, tetra, ect, et externes a la partition ?
500
 
  // Question : est-ce que ca en ajouterait ? reponse : OUI (teste')
501
 
  // mais c'est pas utile pour l'instant : ball sert juste aux aretes
502
 
  warning_macro ("set edge [2] ext_iv_set.size="<<ext_iv_set.size());
503
 
#ifdef TODO
504
 
  ball.set_dis_indexes (ext_iv_set);
505
 
#endif // TODO
506
 
 
507
 
  warning_macro ("set edge done");
508
 
}
509
 
/** ------------------------------------------------------------------------
510
 
 * on any 3d geo_element K, set K.dis_iface(iloc) number
511
 
 * ------------------------------------------------------------------------
512
 
 */
513
 
template <class T>
514
 
void
515
 
geo_rep<T,distributed>::set_element_face_index()
516
 
{
517
 
  if (map_dimension() < 3) return;
518
 
}
519
 
// ----------------------------------------------------------------------------
520
 
// read from file
521
 
// ----------------------------------------------------------------------------
522
 
template <class T>
523
 
void
524
 
geo_rep<T,distributed>::load (
525
 
  std::string filename, 
526
 
  const communicator& comm)
527
 
{
528
 
  idiststream ips;
529
 
  ips.open (filename, "geo", comm);
530
 
  check_macro(ips.good(), "\"" << filename << "[.geo[.gz]]\" not found.");
531
 
  get (ips);
532
 
  std::string root_name = delete_suffix (delete_suffix(filename, "gz"), "geo");
533
 
  std::string name = get_basename (root_name);
534
 
  base::_name = name;
535
 
}
536
 
// ----------------------------------------------------------------------------
537
 
// output
538
 
// ----------------------------------------------------------------------------
539
 
/// @brief helper permutation class for geo i/o
540
 
template <class V = typename polymorphic_traits<geo_element>::derived_type>
541
 
struct geo_element_perm {
542
 
  typedef geo_element::size_type size_type;
543
 
  geo_element_perm (const polymorphic_array<geo_element,distributed,V>& elts) 
544
 
    : _elts(elts) {}
545
 
  size_type operator[] (size_type ie) const {
546
 
    const geo_element& K = _elts [ie];
547
 
    return K.ios_dis_ie();
548
 
  }
549
 
  const polymorphic_array<geo_element,distributed,V>& _elts;
550
 
};
551
 
template <class T>
552
 
odiststream&
553
 
geo_rep<T,distributed>::put (odiststream& ops)  const
554
 
{
555
 
  using namespace std;
556
 
  communicator comm = base::_geo_element[0].ownership().comm();
557
 
  size_type io_proc = odiststream::io_proc();
558
 
  size_type my_proc = comm.rank();
559
 
  size_type nproc   = comm.size();
560
 
  size_type dis_nv = base::_vertex.dis_size ();
561
 
  size_type dis_ne = base::_geo_element[base::_map_dimension].dis_size ();
562
 
  ops << "#!geo" << endl
563
 
      << endl
564
 
      << "mesh" << endl
565
 
      << base::_version
566
 
      << " " << base::_dimension
567
 
      << " " << dis_nv
568
 
      << " " << dis_ne;
569
 
  if   (base::_version >= 2) {
570
 
    if (base::_dimension >= 3) {
571
 
      ops << " " << base::_geo_element[2].dis_size();
572
 
    }
573
 
    if (base::_dimension >= 2) {
574
 
      ops << " " << base::_geo_element[1].dis_size();
575
 
    }
576
 
  }
577
 
  ops << endl << endl;
578
 
 
579
 
  // build a permutationh array (could be avoided, but requires a template Permutation arg in array::permuted_put
580
 
  array<size_type> iv2ios_dis_iv (base::_vertex.ownership());
581
 
  for (size_type iv = 0, niv = iv2ios_dis_iv.size(); iv < niv; iv++) {
582
 
    const geo_element& P = base::_geo_element[0][iv];
583
 
    iv2ios_dis_iv [iv] = P.ios_dis_ie();
584
 
  }
585
 
  base::_vertex.permuted_put_values (ops, iv2ios_dis_iv, _point_put<T>(base::_dimension));
586
 
  ops << endl;
587
 
 
588
 
  // elements are permuted back to original order and may
589
 
  // refer to original vertices numbering
590
 
  std::vector<size_type> vertex_perm ((my_proc == io_proc) ? dis_nv : 0);
591
 
  size_type tag_gather = distributor::get_new_tag();
592
 
  if (my_proc == io_proc) {
593
 
    size_type i_start = iv2ios_dis_iv.ownership().first_index(my_proc);
594
 
    size_type i_size  = iv2ios_dis_iv.ownership().size       (my_proc);
595
 
    for (size_type i = 0; i < i_size; i++) {
596
 
      vertex_perm [i_start + i] = iv2ios_dis_iv [i];
597
 
    }
598
 
    for (size_type iproc = 0; iproc < nproc; iproc++) {
599
 
      if (iproc == my_proc) continue;
600
 
      size_type i_start = iv2ios_dis_iv.ownership().first_index(iproc);
601
 
      size_type i_size  = iv2ios_dis_iv.ownership().size       (iproc);
602
 
      comm.recv (iproc, tag_gather, vertex_perm.begin().operator->() + i_start, i_size);
603
 
    }
604
 
  } else {
605
 
    comm.send (0, tag_gather, iv2ios_dis_iv.begin().operator->(), iv2ios_dis_iv.size());
606
 
  }
607
 
  geo_element_permuted_put put_element (vertex_perm);
608
 
 
609
 
  base::_geo_element[base::_map_dimension].permuted_put_values (
610
 
        ops, 
611
 
        geo_element_perm<> (base::_geo_element[base::_map_dimension]),
612
 
        put_element);
613
 
  ops << endl;
614
 
  //
615
 
  // put faces & edges
616
 
  //
617
 
  if   (base::_version >= 2 && base::_dimension >= 3) {
618
 
      base::_geo_element[2].permuted_put_values (
619
 
        ops, 
620
 
        geo_element_perm<> (base::_geo_element[2]),
621
 
        put_element);
622
 
  }
623
 
  if   (base::_version >= 2 && base::_dimension >= 2) {
624
 
      base::_geo_element[1].permuted_put_values (
625
 
        ops, 
626
 
        geo_element_perm<> (base::_geo_element[1]),
627
 
        put_element);
628
 
  }
629
 
  //
630
 
  // put domains
631
 
  //
632
 
  for (typename std::vector<domain_indirect_basic<distributed> >::const_iterator
633
 
        iter = base::_domains.begin(),
634
 
        last = base::_domains.end();
635
 
        iter != last; ++iter) {
636
 
    ops << endl;
637
 
    (*iter).put (ops, *this);
638
 
  }
639
 
  return ops;
640
 
}
641
 
template <class T>
642
 
void
643
 
geo_rep<T,distributed>::dump (std::string name)  const {
644
 
  base::_vertex.dump        (name + "-vert");
645
 
  base::_geo_element[base::_map_dimension].dump(name + "-elem");
646
 
}
647
27
// --------------------------------------------------------------------------
648
28
// accessors to distributed data
649
29
// --------------------------------------------------------------------------
650
30
template <class T>
 
31
typename geo_rep<T,distributed>::const_reference  
 
32
geo_rep<T,distributed>::dis_get_geo_element (size_type dim, size_type dis_ige) const
 
33
{
 
34
  if (base::_gs.ownership_by_dimension[dim].is_owned (dis_ige)) {
 
35
    size_type first_dis_ige = base::_gs.ownership_by_dimension[dim].first_index();
 
36
    size_type ige = dis_ige - first_dis_ige;
 
37
    return get_geo_element (dim, ige);
 
38
  }
 
39
  // element is owned by another proc ; get its variant
 
40
  size_type iproc = base::_gs.ownership_by_dimension[dim].find_owner(dis_ige);
 
41
  size_type first_dis_ige = base::_gs.ownership_by_dimension[dim].first_index(iproc);
 
42
  size_type first_dis_v = first_dis_ige;
 
43
  size_type  last_dis_v = first_dis_v;
 
44
  size_type shift = 0;
 
45
  for (size_type variant = reference_element::first_variant_by_dimension(dim);
 
46
                 variant < reference_element:: last_variant_by_dimension(dim); variant++) {
 
47
    last_dis_v += base::_geo_element [variant].ownership().size (iproc);
 
48
    if (dis_ige < last_dis_v)  {
 
49
       assert_macro (dis_ige >= shift, "unexpected index computation");
 
50
       size_type dis_igev = dis_ige - shift;
 
51
       return base::_geo_element [variant].dis_at (dis_igev);
 
52
    }
 
53
    shift += base::_geo_element [variant].ownership().first_index (iproc);
 
54
    first_dis_v = last_dis_v;
 
55
  }
 
56
  error_macro ("geo_element dis_index " << dis_ige 
 
57
        << " cause problem; its range is [0:"<< base::_gs.ownership_by_dimension[dim].dis_size() << "[");
 
58
  return base::_geo_element [0].dis_at(0); // not reached
 
59
}
 
60
template <class T>
651
61
typename geo_rep<T,distributed>::size_type
652
62
geo_rep<T,distributed>::dis_ige2ios_dis_ige (size_type dim, size_type dis_ige) const
653
63
{
654
 
    check_macro (dim == 0, "dimension="<<dim<<": not yet !");
655
 
    if (dis_ige >= vertex_ownership().first_index()
656
 
     && dis_ige <  vertex_ownership().last_index()) {
657
 
        size_type ige = dis_ige - vertex_ownership().first_index();
658
 
        const geo_element& P = base::_geo_element[0][ige];
659
 
        return P.ios_dis_ie();
660
 
    }
661
 
    typename polymorphic_map<geo_element>::const_iterator iter = _ext_geo_element_0.find (dis_ige);
662
 
    check_macro (iter != _ext_geo_element_0.end(), "unexpected vertex index:"<<dis_ige);
663
 
    const geo_element& P = *iter;
664
 
    return P.ios_dis_ie();
665
 
}
666
 
template <class T>
667
 
const typename geo_rep<T,distributed>::vertex_type&
668
 
geo_rep<T,distributed>::dis_vertex (size_type dis_iv) const
669
 
{
670
 
    if (dis_iv >= vertex_ownership().first_index()
671
 
     && dis_iv <  vertex_ownership().last_index()) {
672
 
        size_type iv = dis_iv - vertex_ownership().first_index();
673
 
        return base::_vertex [iv];
674
 
    }
675
 
    // here, dis_iv is not managed by current proc
676
 
    // try on external associative table
677
 
    typename vertex_map_type::const_iterator iter = _ext_vertex.find (dis_iv);
678
 
    check_macro (iter != _ext_vertex.end(), "unexpected vertex index:"<<dis_iv);
679
 
    return (*iter).second;
 
64
    const geo_element& K = dis_get_geo_element(dim,dis_ige);
 
65
    return K.ios_dis_ie();
680
66
}
681
67
// --------------------------------------------------------------------------
682
68
// access by geo_element(dim,idx)
697
83
typename geo_rep<T,distributed>::size_type
698
84
geo_rep<T,distributed>::ige2ios_dis_ige (size_type dim, size_type ige) const
699
85
{
700
 
    const geo_element& K = base::_geo_element[dim][ige];
 
86
    const geo_element& K = get_geo_element(dim,ige);
701
87
    return K.ios_dis_ie();
702
88
}
 
89
/** -------------------------------------------------------------------------
 
90
 * utility: vertex ownership follows node ownership, but dis_numbering differ
 
91
 * for high order > 1 meshes. This function converts numbering.
 
92
 * --------------------------------------------------------------------------
 
93
 */
 
94
template <class T>
 
95
typename geo_rep<T,distributed>::size_type
 
96
geo_rep<T,distributed>::dis_inod2dis_iv (size_type dis_inod) const
 
97
{
 
98
  if (base::order() == 1) return dis_inod;
 
99
  distributor vertex_ownership = geo_element_ownership(0);
 
100
  distributor   node_ownership = base::_node.ownership();
 
101
  size_type iproc          =   node_ownership.find_owner(dis_inod);
 
102
  size_type first_dis_inod =   node_ownership.first_index(iproc);
 
103
  size_type first_dis_iv   = vertex_ownership.first_index(iproc);
 
104
  size_type   inod = dis_inod - first_dis_inod;
 
105
  size_type     iv = inod;
 
106
  size_type dis_iv = first_dis_iv + iv;
 
107
  return dis_iv;
 
108
}
 
109
template <class T>
 
110
typename geo_rep<T,distributed>::size_type
 
111
geo_rep<T,distributed>::dis_iv2dis_inod (size_type dis_iv) const
 
112
{
 
113
  if (base::order() == 1) return dis_iv;
 
114
  distributor vertex_ownership = base::_gs.ownership_by_variant [reference_element::p];
 
115
  distributor   node_ownership = base::_gs.node_ownership;
 
116
  size_type iproc          = vertex_ownership.find_owner(dis_iv);
 
117
  size_type first_dis_iv   = vertex_ownership.first_index(iproc);
 
118
  size_type first_dis_inod =   node_ownership.first_index(iproc);
 
119
  size_type       iv = dis_iv - first_dis_iv;
 
120
  size_type     inod = iv;
 
121
  size_type dis_inod = first_dis_inod + inod;
 
122
  return dis_inod;
 
123
}
703
124
// ----------------------------------------------------------------------------
704
125
// instanciation in library
705
126
// ----------------------------------------------------------------------------
706
127
template class geo_rep<Float,distributed>;
707
 
template geo_basic<Float,distributed> compact (const geo_basic<Float,distributed>&);
708
128
 
709
129
} // namespace rheolef
710
130
#endif // _RHEOLEF_HAVE_MPI