Rheolef  7.2
an efficient C++ finite element environment
geo_mpi_get.cc
Go to the documentation of this file.
1 #include "rheolef/config.h"
22 #ifdef _RHEOLEF_HAVE_MPI
23 #include "rheolef/geo.h"
24 #include "rheolef/geo_domain.h"
25 #include "rheolef/space_numbering.h"
26 #include "rheolef/dis_macros.h"
27 #include "rheolef/rheostream.h"
28 #include "rheolef/iorheo.h"
29 #include "rheolef/index_set.h"
30 
31 namespace rheolef {
32 
33 extern
34 disarray<size_t>
36  const std::array<hack_array<geo_element_hack>,reference_element::max_variant>&
37  ios_geo_element,
38  const distributor& ownership_by_dimension,
39  size_t map_dim,
40  size_t dis_nv);
41 
42 // --------------------------------------------------------------------------
43 // utility for geo get
44 // --------------------------------------------------------------------------
45 static
46 distributor
47 build_true_ios_ge_ownership_by_dimension (
48  const std::array<hack_array<geo_element_hack>,reference_element::max_variant>&
49  ios_geo_element,
50  size_t side_dim)
51 {
52  using namespace std;
56  if (first_variant >= last_variant) return distributor();
57  const communicator& comm = ios_geo_element [first_variant].ownership().comm();
58 
59  size_type nge = 0;
60  size_type dis_nge = 0;
63  nge += ios_geo_element [variant].size();
64  dis_nge += ios_geo_element [variant].dis_size();
65  }
66  return distributor (dis_nge, comm, nge);
67 }
68 static
69 void
70 build_apparent_ios_ownership(
71 // input:
72  const std::array<hack_array<geo_element_hack>,reference_element::max_variant>&
73  ios_geo_element,
74  size_t side_dim,
75 // output:
76  distributor& ios_ownership,
77  distributor ios_ownership_by_variant [reference_element::max_variant])
78 {
79  using namespace std;
83  if (first_variant >= last_variant) return;
84  const communicator& comm = ios_geo_element [first_variant].ownership().comm();
85 
86  // 1) build ios_ownership = ios_geo_element ownership by dimension
87  size_type dis_nge = 0;
90  dis_nge += ios_geo_element [variant].dis_size();
91  }
92  ios_ownership = distributor (dis_nge, comm, distributor::decide);
93 
94  // 2) build ios_ownership_by_variant as if it was readed in sequence, by dimension
95  // Note: used by P1d and P2 element numbering, for output of results in the same
96  // vertex, edges, faces & volume as these entities was readed
97  size_type first_dis_v = 0;
100 
101  size_type dis_ngev = ios_geo_element [variant].dis_size();
102  size_type last_dis_v = first_dis_v + dis_ngev;
103  size_type first_ios_dis_nge = ios_ownership.first_index();
104  size_type last_ios_dis_nge = ios_ownership. last_index();
105  size_type first_ios_dis_ngev = min (max (first_ios_dis_nge, first_dis_v), last_ios_dis_nge);
106  size_type last_ios_dis_ngev = max (min ( last_ios_dis_nge, last_dis_v), first_ios_dis_nge);
107  size_type ios_ngev = last_ios_dis_ngev - first_ios_dis_ngev;
108  ios_ownership_by_variant [variant] = distributor (dis_ngev, comm, ios_ngev);
109  first_dis_v = last_dis_v;
110  }
111 }
112 // ----------------------------------------------------------------------------
113 // new renumbering:
114 // - a vertex belongs to the same proc as at least an edge that contains this vertex
115 // - an edge belongs to the same proc as at least a face that contains this edge
116 // - a face belongs to the same proc as at least a volume that contains this face
117 // => a side S belongs to the same proc as at least a super-side K that contains it
118 // ----------------------------------------------------------------------------
119 void
121 // input:
123  ios_geo_element,
124  const geo_size& ios_gs, // TODO: not used...
125  size_t S_dim,
126 // output:
127  std::array<std::vector<size_t>, 4>& massive_partition_by_dimension,
128  std::array<disarray<size_t>, reference_element::max_variant>& partition_by_variant)
129 {
130  typedef size_t size_type;
131  distributor ios_vertex_ownership = ios_geo_element [reference_element::p].ownership();
132  size_type dis_nv = ios_vertex_ownership.dis_size();
133  size_type first_ios_dis_iv = ios_vertex_ownership.first_index();
134  // ------------------------------------------------------------------------
135  // 1) K_ball(X) := { K; X is a vertex of K }
136  // ------------------------------------------------------------------------
137  index_set empty_set; // TODO: add a global allocator to empty_set
138  disarray<index_set,distributed> K_ball (ios_vertex_ownership, empty_set);
139  size_type K_dim = S_dim + 1;
140  size_type K_ios_ige = 0;
141  distributor true_K_ios_ge_ownership = build_true_ios_ge_ownership_by_dimension (ios_geo_element, K_dim);
142  size_type first_K_ios_dis_ige = true_K_ios_ge_ownership.first_index();
144  K_variant < reference_element:: last_variant_by_dimension(K_dim); K_variant++) {
145  distributor K_ios_gev_ownership = ios_geo_element [K_variant].ownership();
146  for (size_type K_ios_igev = 0, K_ios_ngev = K_ios_gev_ownership.size(); K_ios_igev < K_ios_ngev; K_ios_igev++, K_ios_ige++) {
147  const geo_element& K = ios_geo_element [K_variant] [K_ios_igev];
148  size_type K_ios_dis_ige = first_K_ios_dis_ige + K_ios_ige;
149  for (size_type iloc = 0, nloc = K.size(); iloc < nloc; iloc++) {
150  size_type ios_dis_iv = K[iloc];
151  assert_macro (ios_dis_iv < dis_nv, "K={"<<K<<"}: "<<iloc<<"-vertex index " << ios_dis_iv << " out of range [0:"<<dis_nv<<"[");
152  if (ios_vertex_ownership.is_owned(ios_dis_iv)) {
153  size_type ios_iv = ios_dis_iv - first_ios_dis_iv;
154  K_ball[ios_iv] += K_ios_dis_ige;
155  } else {
156  index_set K_ios_dis_ige_set;
157  K_ios_dis_ige_set += K_ios_dis_ige;
158  K_ball.dis_entry (ios_dis_iv) += K_ios_dis_ige_set; // not so efficient: union with {dis_iegv}
159  }
160  }
161  }
162  }
163  K_ball.dis_entry_assembly();
164  // ------------------------------------------------------------------------
165  // 2) import ball[ios_dis_iv] when dis_iv is referenced by a side S
166  // ------------------------------------------------------------------------
167  index_set ext_ios_dis_iv;
169  S_variant < reference_element:: last_variant_by_dimension(S_dim); S_variant++) {
170  distributor ios_gev_ownership = ios_geo_element [S_variant].ownership();
171  for (size_type ios_igev = 0, ios_ngev = ios_gev_ownership.size(); ios_igev < ios_ngev; ios_igev++) {
172  const geo_element& S = ios_geo_element [S_variant] [ios_igev];
173  for (size_type iloc = 0, nloc = S.size(); iloc < nloc; iloc++) {
174  size_type ios_dis_iv = S[iloc];
175  if (! ios_vertex_ownership.is_owned (ios_dis_iv)) {
176  ext_ios_dis_iv += ios_dis_iv;
177  }
178  }
179  }
180  }
181  K_ball.set_dis_indexes (ext_ios_dis_iv);
182  // ------------------------------------------------------------------------
183  // 3) owner(S) := max { owner(K); K is a super-subgeo containing S }
184  // ------------------------------------------------------------------------
185  distributor true_S_ios_ge_ownership = build_true_ios_ge_ownership_by_dimension (ios_geo_element, S_dim);
186  size_type S_dis_nge = true_S_ios_ge_ownership.dis_size();
187  size_type first_S_ios_dis_ige = true_S_ios_ge_ownership.first_index();
188  std::vector<size_type> tmp_S_massive_partition (S_dis_nge, 0); // TODO: massive memory area
189  size_type S_ios_ige = 0;
191  S_variant < reference_element:: last_variant_by_dimension(S_dim); S_variant++) {
192  distributor ios_gev_ownership = ios_geo_element [S_variant].ownership();
193  size_type first_ios_dis_igev = ios_gev_ownership.first_index();
194  for (size_type ios_igev = 0, ios_ngev = ios_gev_ownership.size(); ios_igev < ios_ngev; ios_igev++, S_ios_ige++) {
195  const geo_element& S = ios_geo_element [S_variant] [ios_igev];
196  index_set K_ios_ige_set = K_ball.dis_at (S[0]);
197  for (size_type iloc = 0, nloc = S.size(); iloc < nloc; iloc++) {
198  K_ios_ige_set.inplace_intersection (K_ball.dis_at(S[iloc]));
199  }
200  check_macro (K_ios_ige_set.size() > 0, "connectivity: S={"<<S<<"} not found in the side set");
201  size_type S_owner = 0;
202  for (index_set::const_iterator iter = K_ios_ige_set.begin(), last = K_ios_ige_set.end(); iter != last; iter++) {
203  size_type K_ios_ige = *iter;
204  S_owner = std::max(S_owner, massive_partition_by_dimension[K_dim][K_ios_ige]);
205  }
206  size_type S_ios_dis_ige = first_S_ios_dis_ige + S_ios_ige;
207  tmp_S_massive_partition [S_ios_dis_ige] = S_owner;
208  }
209  }
210  // ------------------------------------------------------------------------
211  // 4) all_reduce: TODO: massive memory area comms
212  // ------------------------------------------------------------------------
213  massive_partition_by_dimension[S_dim].resize (tmp_S_massive_partition.size(), 0);
214  communicator comm = ios_vertex_ownership.comm();
215  mpi::all_reduce (
216  comm,
217  tmp_S_massive_partition.begin().operator->(),
218  tmp_S_massive_partition.size(),
219  massive_partition_by_dimension[S_dim].begin().operator->(),
220  mpi::maximum<size_type>());
221  // ------------------------------------------------------------------------
222  // 5) copy the massive_partition_by_dimension into a distributed disarray "partition", variant by variant
223  // ------------------------------------------------------------------------
224  size_type S_ios_dis_ige = first_S_ios_dis_ige;
226  S_variant < reference_element:: last_variant_by_dimension(S_dim); S_variant++) {
227  partition_by_variant [S_variant].resize (ios_geo_element [S_variant].ownership());
228  for (size_type S_ios_igev = 0, S_ios_negv = partition_by_variant [S_variant].size();
229  S_ios_igev < S_ios_negv; S_ios_igev++, S_ios_dis_ige++) {
230  partition_by_variant [S_variant][S_ios_igev] = massive_partition_by_dimension[S_dim] [S_ios_dis_ige];
231  }
232  }
233 }
234 // --------------------------------------------------------------------------
235 // edges & faces renumbering subroutine
236 // --------------------------------------------------------------------------
237 void
239  // input:
241  ios_geo_element,
242  const geo_size& ios_gs,
243  size_t dis_nv,
244  size_t side_dim,
245  // output:
247  geo_element,
248  geo_size& gs,
250  igev2ios_dis_igev,
252  ios_igev2dis_igev,
253  std::array<disarray<size_t>,4>& ios_ige2dis_ige,
254  // tmp:
256  partition_by_variant)
257 {
259  typedef hack_array<geo_element_hack>::iterator iterator_by_variant;
260  typedef hack_array<geo_element_hack>::const_iterator const_iterator_by_variant;
261 
262  communicator comm = ios_geo_element[0].ownership().comm();
263  //
264  // 3) build geo_elemen [variant]:
265  //
266  // MERGE: could be done from here:
267  size_type nge = 0;
270 
271  ios_geo_element [variant].repartition (
272  partition_by_variant [variant],
274  igev2ios_dis_igev [variant],
275  ios_igev2dis_igev [variant]);
276 
277  gs.ownership_by_variant [variant] = geo_element [variant].ownership();
278  nge += geo_element [variant].size();
279  }
280  gs.ownership_by_dimension [side_dim] = distributor (distributor::decide, comm, nge);
281  //
282  // 4) build first_by_variant [variant]
283  //
284  {
285  size_type first_v = 0;
288 
290  first_v += geo_element [variant].size();
291  }
292  }
293  //
294  // 5) set element number
295  // & build ios_ige2dis_ige[map_dim] from ios_igev2dis_igev[variant]
296  // TODO: a way to build directly ios_ige2dis_ige without assembly (and many comms)
297  //
298  ios_ige2dis_ige [side_dim].resize (ios_gs.ownership_by_dimension [side_dim]); // OK
299  {
300  size_type first_dis_ige = gs.ownership_by_dimension [side_dim].first_index();
301  size_type ige = 0;
304  size_type first_v = gs.first_by_variant [variant].size();
305  for (size_type igev = 0, ngev = geo_element [variant].size(); igev < ngev; igev++, ige++) {
306  ::rheolef::geo_element& S = geo_element [variant] [igev]; // GNU C++ 4.5 BUG : add ::rheolef::
307  size_type dis_ige = first_dis_ige + ige;
308  S.set_dis_ie (dis_ige);
309  size_type ios_dis_ige = S.ios_dis_ie();
310  ios_ige2dis_ige [side_dim].dis_entry (ios_dis_ige) = dis_ige;
311  }
312  }
313  ios_ige2dis_ige [side_dim].dis_entry_assembly();
314  }
315 }
316 void
318 // input:
319  const std::vector<geo_element::size_type>& new_global_node_num,
320  size_t dis_nnod,
321 // modified:
323 {
324  using namespace std;
326  //
327  // vertices S[iloc] of new numbered element table still have ios numbering: fix it
328  //
329  // TODO: iterator loop on ge instead of gev
330  size_type first_dis_igev = gev.ownership().first_index();
331  for (size_type igev = 0, ngev = gev.size(); igev < ngev; igev++) {
332  geo_element& S = gev [igev];
333  for (size_type iloc = 0, nloc = S.n_node(); iloc < nloc; iloc++) {
334  assert_macro (S[iloc] < dis_nnod, "node index "<<S[iloc]<<" out of range [0:"<<dis_nnod<<"[");
335  assert_macro (new_global_node_num[S[iloc]] < dis_nnod, "new node index "<<new_global_node_num[S[iloc]] <<" out of range [0:"<<dis_nnod<<"[");
336  S[iloc] = new_global_node_num [S[iloc]];
337  }
338  }
339 }
347 template <class T>
348 void
350 {
351  distributor vertex_ownership = base::_geo_element[reference_element::p].ownership();
352  size_type first_dis_iv = vertex_ownership.first_index();
353  size_type last_dis_iv = vertex_ownership.last_index();
354  size_type dis_nv = vertex_ownership.dis_size();
355 
356  distributor node_ownership = base::_node.ownership();
357  size_type first_dis_inod = node_ownership.first_index();
358  size_type last_dis_inod = node_ownership.last_index();
359  size_type dis_nnod = node_ownership.dis_size();
360 
361  // 1a) list external vertex & nodes indexes from internal elements
362  std::set<size_type> ext_vertex_set;
363  std::set<size_type> ext_node_set;
364  std::vector<size_type> dis_inod1;
365  for (size_type dim = 1; dim <= base::_gs._map_dimension; dim++) {
366  // loop on elements
367  for (size_type ige = 0, nge = base::_gs.ownership_by_dimension[dim].size(); ige < nge; ige++) {
368  const geo_element& K = get_geo_element(dim,ige);
369  space_numbering::dis_idof (base::_piola_basis, base::_gs, K, dis_inod1);
370  for (size_type loc_inod = 0, loc_nnod = dis_inod1.size(); loc_inod < loc_nnod; loc_inod++) {
371  size_type dis_inod = dis_inod1 [loc_inod];
372  assert_macro (dis_inod < dis_nnod, "node index "<< dis_inod <<" out of range [0:"<<dis_nnod<<"[");
373  if (node_ownership.is_owned (dis_inod)) continue;
374  ext_node_set.insert (dis_inod);
375  if (loc_inod >= K.size()) continue;
376  // then reports vertex to node: same owner
377  size_type dis_iv = base::dis_inod2dis_iv (dis_inod);
378  check_macro (dis_iv < dis_nv, "vertex index "<< dis_iv <<" out of range [0:"<<dis_nv<<"[");
379  check_macro (!vertex_ownership.is_owned (dis_iv), "strange bug: not owned (nod) but is_owned(ver)");
380  ext_vertex_set.insert (dis_iv);
381  }
382  }
383  }
384  // 1b) pull external vertices & nodes:
385  base::_node.append_dis_indexes (ext_node_set);
386  base::_geo_element [reference_element::p].append_dis_indexes (ext_vertex_set);
387 
388  // 2) K.edge(i) and K.face(i) have been completed by set set_element_side_index
389  // but not propagated to external elements : update them by refreshing the external data
391  variant < reference_element:: last_variant_by_dimension (base::_gs._map_dimension); ++variant) {
392  const std::map<size_type,geo_element_auto<>>& ext_gev = base::_geo_element [variant].get_dis_map_entries();
393  index_set ext_dis_ie_set;
394  for (auto i: ext_gev) { ext_dis_ie_set.insert (i.first); }
395  base::_geo_element [variant].set_dis_indexes (ext_dis_ie_set);
396  }
397  // 3a) list external vertex indexes from external elements
398  std::array<index_set,reference_element::max_variant> ext_dis_igev_set;
399  for (size_type dim = base::_gs._map_dimension; dim >= 1; dim--) {
402  for (auto x : base::_geo_element[variant].get_dis_map_entries()) {
403  const geo_element& K = x.second;
404  for (size_type subgeo_dim = 0; subgeo_dim < K.dimension(); ++subgeo_dim) {
405  for (size_type loc_is = 0, loc_ns = K.n_subgeo(subgeo_dim); loc_is < loc_ns; ++loc_is) {
406  size_type dis_ige = (subgeo_dim == 0) ? base::dis_inod2dis_iv(K[loc_is]) : (subgeo_dim == 1) ? K.edge(loc_is) : K.face(loc_is);
407  check_macro(dis_ige != std::numeric_limits<size_type>::max(), "invalid external subgeo dis_index");
408  if (base::sizes().ownership_by_dimension [subgeo_dim].is_owned (dis_ige)) continue;
409  // this subgeo is external: add it to ext_dis_igev_set[variant] :
410  size_type dis_size = base::sizes().ownership_by_dimension [subgeo_dim].dis_size();
411  check_macro(dis_ige < dis_size, "invalid external "<<subgeo_dim<<"d subgeo dis_index = "<<dis_ige<<" out of range [0:"<<dis_size<<"[");
412  // convert dis_ige to dis_igev and get its variant
414  size_type dis_igev = base::sizes().dis_ige2dis_igev_by_dimension (subgeo_dim, dis_ige, variant);
415  ext_dis_igev_set [variant].insert (dis_igev);
416  }
417  }
418  }
419  }
420  }
421  // 3b) append external subgeo entities from all external elements
423  variant < reference_element:: last_variant_by_dimension (base::_gs._map_dimension); ++variant) {
424  base::_geo_element [variant].append_dis_indexes (ext_dis_igev_set [variant]);
425  }
426  // 4a) list external nodes from all external entities, based on dis_idof(), for high order meshes
427  for (size_type dim = base::_gs._map_dimension; dim >= 1; dim--) {
430  for (auto x : base::_geo_element[variant].get_dis_map_entries()) {
431  const geo_element& K = x.second;
432  space_numbering::dis_idof (base::_piola_basis, base::_gs, K, dis_inod1);
433  for (size_type loc_inod = 0, loc_nnod = dis_inod1.size(); loc_inod < loc_nnod; loc_inod++) {
434  size_type dis_inod = dis_inod1 [loc_inod];
435  assert_macro (dis_inod < dis_nnod, "node index "<< dis_inod <<" out of range [0:"<<dis_nnod<<"[");
436  if (node_ownership.is_owned (dis_inod)) continue;
437  ext_node_set.insert (dis_inod);
438  }
439  }
440  }
441  }
442  // 4b) pull external nodes:
443  base::_node.set_dis_indexes (ext_node_set);
444 }
449 template <class T>
450 void
452 {
453  distributor vertex_ownership = base::_gs.ownership_by_dimension [0];
454  distributor node_ownership = base::_node.ownership();
455  size_type nv = vertex_ownership.size();
456  size_type first_dis_iv = vertex_ownership.first_index();
457  size_type last_dis_iv = vertex_ownership. last_index();
458  size_type dis_nnod = node_ownership.dis_size(); // for bound checks
459  // ------------------------------------------------------------------------
460  // 0) build external vertices index set
461  // ------------------------------------------------------------------------
462  index_set ext_iv_set; // size=O((N/nproc)^((d-1)/d))
463  for (size_type dim = side_dim; dim <= base::_gs._map_dimension; dim++) {
466  for (size_type igev = 0, ngev = base::_geo_element[var].size(); igev < ngev; igev++) {
467  const geo_element& K = base::_geo_element [var] [igev];
468  for (size_type iloc = 0, nloc = K.size(); iloc < nloc; iloc++) {
469  size_type dis_inod = K[iloc];
470  if (! node_ownership.is_owned(dis_inod)) { // vertex ownership follows node ownership
471  size_type dis_iv = base::dis_inod2dis_iv (dis_inod);
472  ext_iv_set.insert (dis_iv);
473  }
474  }
475  }
476  }
477  }
478  // ------------------------------------------------------------------------
479  // 1) ball(X) := { E; X is a vertex of E }
480  // ------------------------------------------------------------------------
481  index_set empty_set; // TODO: add a global allocator to empty_set
485  ball [variant].resize (vertex_ownership, empty_set);
486  distributor gev_ownership = base::_gs.ownership_by_variant [variant];
487  size_type first_dis_igev = gev_ownership.first_index();
488  for (size_type igev = 0, ngev = base::_geo_element [variant].size(); igev < ngev; igev++) {
489  const geo_element& S = base::_geo_element [variant] [igev];
490  size_type dis_igev = first_dis_igev + igev;
491  for (size_type iloc = 0, nloc = S.size(); iloc < nloc; iloc++) {
492  size_type dis_inod = S[iloc];
493  assert_macro (dis_inod < dis_nnod, "S={"<<S<<"}: "<<iloc<<"-node index " << dis_inod << " out of range [0:"<<dis_nnod<<"[");
494  size_type dis_iv = base::dis_inod2dis_iv (dis_inod);
495  if (vertex_ownership.is_owned(dis_iv)) {
496  size_type iv = dis_iv - first_dis_iv;
497  ball [variant][iv] += dis_igev;
498  } else {
499  index_set dis_igev_set;
500  dis_igev_set += dis_igev;
501  ball [variant].dis_entry (dis_iv) += dis_igev_set; // not so efficient: union with {dis_iegv}
502  }
503  }
504  }
505  ball [variant].dis_entry_assembly();
506  // ------------------------------------------------------------------------
507  // for all the dis_iv that are not handled by the current process
508  // but are referenced by at least a side, get ext_ball[dis_iv]
509  // ------------------------------------------------------------------------
510  // Question: faudra-t'il inclure d'autres sommets dans ext_iv_set ?
511  // -> ceux issus des triangles, tetra, ect, et externes a la partition ?
512  // Question : est-ce que ca en ajouterait ? reponse : OUI (teste')
513  // mais c'est pas utile pour l'instant : ball sert juste aux aretes
514  ball [variant].set_dis_indexes (ext_iv_set);
515  }
516  // ------------------------------------------------------------------------
517  // 2) on parcourt chaque dis_E de ball(iv) et ext_ball(dis_iv) :
518  // si dis_E n'est pas local, on le met dans une liste ext_isid_set
519  // et on importe l'arete en tant que geo_element
520  // ------------------------------------------------------------------------
521  // scan ball(iv) for external sides
524 
525  // 2.1) scan ball(iv) for external sides
526  std::set<size_type> ext_igev_set; // size=O((N/nproc)^((d-1)/d))
527  distributor gev_ownership = base::_gs.ownership_by_variant [variant];
528  size_type dis_ngev = gev_ownership.dis_size();
529  for (size_type iv = 0, nv = vertex_ownership.size(); iv < nv; iv++) {
530 
531  const index_set& ball_iv = ball [variant] [iv];
532  for (index_set::const_iterator iter = ball_iv.begin(), last = ball_iv.end(); iter != last; iter++) {
533  size_type dis_igev = *iter;
534  assert_macro (dis_igev < dis_ngev, "index "<<dis_igev<<" of element variant="<<variant<<" is out of range [0:"<<dis_ngev<<"[");
535  if (! gev_ownership.is_owned (dis_igev)) {
536  ext_igev_set.insert (dis_igev);
537  }
538  }
539  }
540  // 2.2) scan ball(dis_iv) for external sides
541  typedef disarray<index_set>::scatter_map_type map_type;
542  const map_type& ball_dis = ball [variant].get_dis_map_entries();
543  for (typename map_type::const_iterator iter_b = ball_dis.begin(), last_b = ball_dis.end(); iter_b != last_b; iter_b++) {
544  size_type dis_iv = (*iter_b).first;
545  const index_set& ball_dis_iv = (*iter_b).second;
546  for (index_set::const_iterator iter = ball_dis_iv.begin(), last = ball_dis_iv.end(); iter != last; iter++) {
547  size_type dis_igev = *iter;
548  assert_macro (dis_igev < dis_ngev, "index "<<dis_igev<<" of element variant="<<variant<<" is out of range [0:"<<dis_ngev<<"[");
549  if (! gev_ownership.is_owned (dis_igev)) {
550  ext_igev_set.insert (dis_igev);
551  }
552  }
553  }
554  // 2.3) import external sides
555  base::_geo_element[variant].append_dis_indexes (ext_igev_set);
556  }
557  // ------------------------------------------------------------------------
558  // 3) pour K dans partition(iproc)
559  // pour (dis_A,dis_B) arete de K
560  // set = dis_ball(dis_A) inter dis_ball(dis_B) = {dis_iedg}
561  // E = dis_edges(dis_iedg)
562  // => on numerote dis_iedg cette arete dans le geo_element K
563  // et on indique son orient en comparant a E, arete qui definit l'orient
564  // ------------------------------------------------------------------------
565  for (size_type dim = side_dim+1; dim <= base::_gs._map_dimension; dim++) {
568  for (size_type igev = 0, ngev = base::_geo_element [var].size(); igev < ngev; igev++) {
569  geo_element& K = base::_geo_element [var] [igev];
570  size_type S_iv [4];
571  size_type S_inod[4];
572  for (size_type loc_isid = 0, loc_nsid = K.n_subgeo(side_dim); loc_isid < loc_nsid; loc_isid++) {
573  size_type S_size = K.subgeo_size (side_dim, loc_isid);
574  size_type S_variant = reference_element::variant (S_size, side_dim);
575  size_type loc_jv0 = K.subgeo_local_vertex (side_dim, loc_isid, 0);
576  S_inod [0] = K[loc_jv0];
577  S_iv [0] = base::dis_inod2dis_iv (S_inod[0]);
578  const disarray<index_set,distributed>& ball_S_variant = ball [S_variant];
579  index_set igev_set = ball_S_variant.dis_at (S_iv[0]);
580  for (size_type sid_jloc = 1, sid_nloc = S_size; sid_jloc < sid_nloc; sid_jloc++) {
581  size_type loc_jv = K.subgeo_local_vertex (side_dim, loc_isid, sid_jloc);
582  S_inod [sid_jloc] = K[loc_jv];
583  S_iv [sid_jloc] = base::dis_inod2dis_iv (S_inod[sid_jloc]);
584  const index_set& ball_jv = ball_S_variant.dis_at (S_iv[sid_jloc]);
585  igev_set.inplace_intersection (ball_jv);
586  }
587  check_macro (igev_set.size() > 0, "connectivity: "<<S_size<<"-side ("
588  <<S_iv[0]<<","<<S_iv[1]<<","<<S_iv[2]<<","<<S_iv[3]<<") not found in the side set");
589  check_macro (igev_set.size() == 1, "connectivity: the same side is multiply represented");
590  size_type dis_igev = *(igev_set.begin());
591  const geo_element& S = base::_geo_element[S_variant].dis_at(dis_igev);
592  size_type dis_isid = S.dis_ie();
593  if (side_dim == 1) {
594  // side: edge
595  geo_element::orientation_type orient = S.get_edge_orientation (S_inod[0], S_inod[1]);
596  K.edge_indirect (loc_isid).set (orient, dis_isid);
597  } else { // side_dim == 2
600  if (K.subgeo_size (side_dim, loc_isid) == 3) {
601  // side: triangle
602  S.get_orientation_and_shift (S_inod[0], S_inod[1], S_inod[2], orient, shift);
603  } else {
604  // side: quadrangle
605  S.get_orientation_and_shift (S_inod[0], S_inod[1], S_inod[2], S_inod[3], orient, shift);
606  }
607  K.face_indirect (loc_isid).set (orient, dis_isid, shift);
608  }
609  }
610  }
611  }
612  }
613 }
614 // --------------------------------------------------------------------------
615 // set permutation for nodes: ios_inod2dis_inod & inod2ios_dis_inod
616 // and redistribute ios_node[] into _node[]
617 // --------------------------------------------------------------------------
618 template <class T>
619 void
621 {
622  space_numbering::generic_set_ios_permutation (base::get_piola_basis(), map_dimension(), base::sizes(), _igev2ios_dis_igev, idof2ios_dis_idof);
623 }
624 template <class T>
625 void
627 {
628  std::array<size_type,reference_element::max_variant> loc_ndof_by_variant;
630  set_ios_permutation (_inod2ios_dis_inod);
631 }
632 // --------------------------------------------------------------------------
633 // get geo
634 // --------------------------------------------------------------------------
635 template <class T>
638 {
639  using namespace std;
640  check_macro (ips.good(), "bad input stream for geo.");
641  communicator comm = base::_geo_element[reference_element::p].ownership().comm();
642 
643  size_type io_proc = idiststream::io_proc();
644  size_type my_proc = comm.rank();
645  // ------------------------------------------------------------------------
646  // 1) read file
647  // ------------------------------------------------------------------------
648  //
649  // 1.1) get header
650  //
651  check_macro (dis_scatch(ips, ips.comm(), "\nmesh"), "input stream does not contains a geo.");
652  ips >> base::_version;
653  check_macro (base::_version == 4, "geo version < 4 not supported (HINT: see geo -upgrade)");
654 
655  geo_header hdr;
656  ips >> hdr;
657  check_macro (! hdr.need_upgrade(),
658  "unsupported geo without connectivity in the distributed version: HINT: use geo_upgrade");
659  base::_have_connectivity = true;
660  base::_dimension = hdr.dimension;
661  base::_gs._map_dimension = hdr.map_dimension;
662  base::_sys_coord = hdr.sys_coord;
663  base::_name = "unnamed";
664  base::_piola_basis.reset_family_index (hdr.order);
666  size_type dis_nedg = hdr.dis_size_by_dimension [1];
667  size_type dis_nfac = hdr.dis_size_by_dimension [2];
668  size_type dis_ne = hdr.dis_size_by_dimension [base::_gs._map_dimension];
669  //
670  // 1.2) get node coordinates
671  //
672  size_type ios_size_by_variant [reference_element::max_variant];
673  std::fill (ios_size_by_variant, ios_size_by_variant+reference_element::max_variant, 0);
674  disarray<node_type> ios_node (dis_nnod);
675  ios_node.get_values (ips, _point_get<T>(base::_dimension));
676  check_macro (ips.good(), "bad input stream for geo.");
677  //
678  // 1.3) get elements
679  //
680  std::array<hack_array<geo_element_hack>, reference_element::max_variant> ios_geo_element;
681  size_type ios_nv = 0;
682  if (base::_gs._map_dimension == 0) {
683  ios_nv = ios_node.size();
684  } else {
685  // set elt ios index and compute map_dim & ios_nv (ios_nv < ios_nnod when order > 1)
686  size_type ios_ne = 0;
687  size_type dis_ne = 0;
688  for (size_type variant = reference_element::first_variant_by_dimension(base::_gs._map_dimension);
689  variant < reference_element:: last_variant_by_dimension(base::_gs._map_dimension); variant++) {
691  ios_geo_element [variant].resize (hdr.dis_size_by_variant [variant], param);
692  ios_geo_element [variant].get_values (ips);
693  _ios_gs.first_by_variant [variant] = distributor (distributor::decide, base::comm(), ios_ne);
694  ios_ne += ios_geo_element [variant].size();
695  dis_ne += ios_geo_element [variant].dis_size();
696  }
697  build_apparent_ios_ownership(
698  ios_geo_element,
699  base::_gs._map_dimension,
700  _ios_gs.ownership_by_dimension [base::_gs._map_dimension],
701  _ios_gs.ownership_by_variant);
702 
703  vector<size_type> local_is_vertex (dis_nnod, 0);
704  for (size_type variant = reference_element::first_variant_by_dimension(base::_gs._map_dimension);
705  variant < reference_element:: last_variant_by_dimension(base::_gs._map_dimension); variant++) {
706  size_type first_ios_dis_v = _ios_gs.first_by_variant [variant].dis_size();
707  size_type first_ios_dis_igev = ios_geo_element [variant].ownership().first_index();
708  size_type ios_igev = 0;
709  for (iterator_by_variant iter = ios_geo_element [variant].begin(), last = ios_geo_element [variant].end();
710  iter != last; iter++, ios_igev++) {
711  geo_element& K = *iter;
712  size_type ios_dis_ie = first_ios_dis_v + first_ios_dis_igev + ios_igev;
713  K.set_ios_dis_ie (ios_dis_ie); // OK
714  ios_size_by_variant [K.variant()]++;
715  if (base::order() > 1) {
716  for (size_type iloc = 0, nloc = K.size(); iloc < nloc; iloc++) {
717  local_is_vertex [K[iloc]] = 1;
718  }
719  }
720  }
721  }
722  if (base::order() == 1) {
723  ios_nv = ios_node.size();
724  } else {
725  vector<size_type> global_is_vertex (dis_nnod, 0);
726  mpi::all_reduce (
727  comm,
728  local_is_vertex.begin().operator->(),
729  local_is_vertex.size(),
730  global_is_vertex.begin().operator->(),
731  mpi::maximum<size_type>());
732  ios_nv = accumulate (global_is_vertex.begin() + ios_node.ownership().first_index(),
733  global_is_vertex.begin() + ios_node.ownership().last_index(), 0);
734  }
735  }
736  distributor ios_vertex_ownership;
737  if (base::order() == 1) {
738  ios_vertex_ownership = ios_node.ownership();
739  } else {
740  ios_vertex_ownership = distributor (distributor::decide, base::comm(), ios_nv); // not sure...
741  }
742  size_type dis_nv = ios_vertex_ownership.dis_size();
743  //
744  // 1.4) create 0d vertex-elements
745  //
746  // set ios_dis_iv index as fisrt field of the idx_vertex pair:
747  // # of node that are vertices:
748  {
750  ios_geo_element [reference_element::p].resize (ios_vertex_ownership, param);
751  _ios_gs.ownership_by_variant [reference_element::p] = ios_vertex_ownership;
752  _ios_gs.ownership_by_dimension [0] = ios_vertex_ownership;
753  size_type first_ios_dis_iv = ios_vertex_ownership.first_index();
754  for (size_type ios_iv = 0, ios_nv = ios_vertex_ownership.size(); ios_iv < ios_nv; ios_iv++) {
755  geo_element& P = ios_geo_element [reference_element::p] [ios_iv];
756  size_type ios_dis_iv = first_ios_dis_iv + ios_iv;
757  P [0] = ios_dis_iv;
758  P.set_ios_dis_ie (ios_dis_iv);
759  ios_size_by_variant [P.variant()]++;
760  }
761  }
762  //
763  // 1.5) get faces & edges
764  //
765  if (base::_gs._map_dimension > 0) {
766  for (size_type side_dim = base::_gs._map_dimension - 1; side_dim >= 1; side_dim--) {
767  size_type ios_ngev = 0;
768  size_type dis_ngev = 0;
772  ios_geo_element [variant].resize (hdr.dis_size_by_variant [variant], param);
773  ios_geo_element [variant].get_values (ips);
774  _ios_gs.first_by_variant [variant] = distributor (distributor::decide, base::comm(), ios_ngev);
775  ios_ngev += ios_geo_element [variant].size();
776  dis_ngev += ios_geo_element [variant].dis_size();
777  }
778  build_apparent_ios_ownership(
779  ios_geo_element,
780  side_dim,
781  _ios_gs.ownership_by_dimension [side_dim],
782  _ios_gs.ownership_by_variant);
783 
786  size_type ios_igev = 0;
787  size_type first_dis_v = _ios_gs.first_by_variant [variant].dis_size();
788  size_type first_ios_dis_igev = ios_geo_element [variant].ownership().first_index();
789  for (iterator_by_variant iter = ios_geo_element [variant].begin(), last = ios_geo_element [variant].end();
790  iter != last; iter++, ios_igev++) {
791  geo_element& S = *iter;
792  size_type ios_dis_igev = first_dis_v + first_ios_dis_igev + ios_igev;
793  S.set_ios_dis_ie (ios_dis_igev); // OK
794  ios_size_by_variant [S.variant()]++;
795  }
796  }
797  }
798  }
799  // ------------------------------------------------------------------------
800  // 2) mesh partition & element renumbering
801  // ------------------------------------------------------------------------
802  distributor true_ios_ownership_by_dimension [4];
803  true_ios_ownership_by_dimension [base::_gs._map_dimension]
804  = build_true_ios_ge_ownership_by_dimension (ios_geo_element, base::_gs._map_dimension);
805 
807  ios_geo_element,
808  true_ios_ownership_by_dimension [base::_gs._map_dimension],
809  base::_gs._map_dimension,
810  dis_nv);
811 
812  // copy partition into partition_by_variant[]:
813  std::array<disarray<size_t>, reference_element::max_variant> partition_by_variant;
814  {
815  typename disarray<size_type>::const_iterator iter = partition.begin();
816  for (size_type variant = reference_element::first_variant_by_dimension(base::_gs._map_dimension);
817  variant < reference_element:: last_variant_by_dimension(base::_gs._map_dimension); variant++) {
818  partition_by_variant [variant].resize (ios_geo_element [variant].ownership());
819  for (typename disarray<size_type>::iterator iter_by_var = partition_by_variant [variant].begin(),
820  last_by_var = partition_by_variant [variant].end();
821  iter_by_var != last_by_var; iter_by_var++, iter++) {
822  *iter_by_var = *iter;
823  }
824  }
825  }
827  ios_geo_element,
828  _ios_gs,
829  dis_nv,
830  base::_gs._map_dimension,
831  base::_geo_element,
832  base::_gs,
833  _igev2ios_dis_igev,
834  _ios_igev2dis_igev,
835  _ios_ige2dis_ige,
836  partition_by_variant);
837 
838 
839  // copy partition into massive_partition_by_dimension[map_dim]:
840  std::array<std::vector<size_t>, 4> massive_partition_by_dimension;
841  {
842  std::vector<size_t> tmp_massive_partition (dis_ne, 0);
843  size_type true_first_dis_ige = true_ios_ownership_by_dimension [base::_gs._map_dimension].first_index();
844  for (size_type ios_ie = 0, ios_ne = partition.size(); ios_ie < ios_ne; ios_ie++) {
845  size_type ios_dis_ie = true_first_dis_ige + ios_ie;
846  tmp_massive_partition [ios_dis_ie] = partition [ios_ie];
847  }
848  massive_partition_by_dimension [base::_gs._map_dimension].resize (dis_ne);
849  mpi::all_reduce (
850  comm,
851  tmp_massive_partition.begin().operator->(),
852  tmp_massive_partition.size(),
853  massive_partition_by_dimension[base::_gs._map_dimension].begin().operator->(),
854  mpi::maximum<size_type>());
855  }
856  // propagate partition to subgeo : faces, edges & vertices
857  for (size_type supergeo_dim = base::_gs.map_dimension(); supergeo_dim > 0; supergeo_dim--) {
859  ios_geo_element,
860  _ios_gs,
861  supergeo_dim-1,
862  massive_partition_by_dimension,
863  partition_by_variant);
864  }
865  // ------------------------------------------------------------------------
866  // 3) vertices renumbering
867  // ------------------------------------------------------------------------
868  //
869  // 3.1) redistribute the _geo_element[p] vertices
870  //
871  partition_by_variant [reference_element::p].resize (ios_vertex_ownership);
872  size_type first_ios_dis_iv = ios_vertex_ownership.first_index();
873  for (size_type ios_iv = 0, ios_nv = ios_vertex_ownership.size(); ios_iv < ios_nv; ios_iv++) {
874  size_type ios_dis_iv = first_ios_dis_iv + ios_iv;
875  partition_by_variant [reference_element::p] [ios_iv] = massive_partition_by_dimension[0] [ios_dis_iv];
876  }
877  disarray<size_type> iv2ios_dis_iv;
878  ios_geo_element [reference_element::p].repartition (
879  partition_by_variant [reference_element::p],
880  base::_geo_element [reference_element::p],
881  iv2ios_dis_iv,
882  _ios_ige2dis_ige[0]);
883 
884  distributor vertex_ownership = base::_geo_element[reference_element::p].ownership();
885  base::_gs.ownership_by_dimension [0] = vertex_ownership;
886  base::_gs.ownership_by_variant [reference_element::p] = vertex_ownership;
887  base::_gs.first_by_variant [reference_element::p] = distributor (0, base::comm(), 0);
888  //
889  // 3.2) set the element[0] disarray
890  //
891  size_type first_dis_iv = vertex_ownership.first_index();
892  size_type last_dis_iv = vertex_ownership.last_index();
893  _igev2ios_dis_igev [reference_element::p].resize (vertex_ownership);
894  for (size_type iv = 0, nv = base::_geo_element[reference_element::p].size(); iv < nv; iv++) {
895  geo_element& P = base::_geo_element[reference_element::p] [iv];
896  size_type dis_iv = first_dis_iv + iv;
897  P[0] = dis_iv;
898  P.set_dis_ie (dis_iv);
899  _igev2ios_dis_igev [reference_element::p] [iv] = P.ios_dis_ie();
900  }
901  // ------------------------------------------------------------------------
902  // 4) edge & face renumbering
903  // ------------------------------------------------------------------------
904  if (base::_gs._map_dimension > 0) {
905  for (size_type side_dim = base::_gs._map_dimension-1; side_dim > 0; side_dim--) {
906 
908  ios_geo_element,
909  _ios_gs,
910  dis_nv,
911  side_dim,
912  base::_geo_element,
913  base::_gs,
914  _igev2ios_dis_igev,
915  _ios_igev2dis_igev,
916  _ios_ige2dis_ige,
917  partition_by_variant);
918  }
919  }
920  // ------------------------------------------------------------------------
921  // 5) get domain, until end-of-file (requires ios_ige2dis_ige renumbering)
922  // ------------------------------------------------------------------------
923  do {
925  bool status = dom.get (ips, *this);
926  if (!status) break;
927  base::_domains.push_back (dom);
928  } while (true);
929  // ------------------------------------------------------------------------
930  // 6) renumbering ios_nodes[]: set permutations inod2ios_dis_inod[]
931  // ------------------------------------------------------------------------
932  node_renumbering (ios_node.ownership());
933  distributor node_ownership = _inod2ios_dis_inod.ownership();
934  base::_gs.node_ownership = node_ownership;
935  // ------------------------------------------------------------------------
936  // 7) redistribute the nodes : from ios_node[] to node() disarrays
937  // ------------------------------------------------------------------------
938  _ios_inod2dis_inod.resize (ios_node.ownership(), std::numeric_limits<size_type>::max());
939  _inod2ios_dis_inod.reverse_permutation (_ios_inod2dis_inod);
940 
941  // ------------------------------------------------------------------------
942  // 8) propagate new node numbering
943  // ------------------------------------------------------------------------
944  // 8.1) build new node disarray: base::_node
945  base::_node.resize (node_ownership);
946  ios_node.permutation_apply (_ios_inod2dis_inod, base::_node);
947  //
948  // 8.2) global table of node renumbering
949  //
950  vector<size_type> new_local_node_num (dis_nnod, 0);
951  size_type first_ios_inod = _ios_inod2dis_inod.ownership().first_index();
952  size_type last_ios_inod = _ios_inod2dis_inod.ownership(). last_index();
953  for (size_type dis_ios_inod = first_ios_inod; dis_ios_inod < last_ios_inod; dis_ios_inod++) {
954  size_type ios_inod = dis_ios_inod - first_ios_inod;
955  new_local_node_num [dis_ios_inod] = _ios_inod2dis_inod[ios_inod];
956  }
957  vector<size_type> new_global_node_num (dis_nnod, 0);
958  mpi::all_reduce (
959  comm,
960  new_local_node_num.begin().operator->(),
961  new_local_node_num.size(),
962  new_global_node_num.begin().operator->(),
963  mpi::maximum<size_type>());
964  //
965  // 8.3) propagate the new node numbering into geo_elements:
966  // vertices K[iloc] of new numbered element table K still have ios numbering: fix it
967  //
968  for (size_type dim = base::_gs._map_dimension; dim > 0; dim--) {
972  new_global_node_num,
973  dis_nnod,
974  base::_geo_element [variant]);
975  }
976  }
977  // ------------------------------------------------------------------------
978  // 9) set indexes on faces and edges of elements, for P2 approx
979  // ------------------------------------------------------------------------
980  for (size_type dim = base::_gs._map_dimension - 1; base::_gs._map_dimension > 0 && dim > 0; dim--) {
981  set_element_side_index (dim);
982  }
983  // ------------------------------------------------------------------------
984  // 10) set external entities, at partition boundaries
985  // ------------------------------------------------------------------------
986  build_external_entities ();
987  // ------------------------------------------------------------------------
988  // 11) bounding box: _xmin, _xmax
989  // ------------------------------------------------------------------------
991  return ips;
992 }
993 // ----------------------------------------------------------------------------
994 // read from file
995 // ----------------------------------------------------------------------------
996 template <class T>
997 void
999  std::string filename,
1000  const communicator& comm)
1001 {
1002  idiststream ips;
1003  ips.open (filename, "geo", comm);
1004  check_macro(ips.good(), "\"" << filename << "[.geo[.gz]]\" not found.");
1005  get (ips);
1006  std::string root_name = delete_suffix (delete_suffix(filename, "gz"), "geo");
1007  std::string name = get_basename (root_name);
1008  base::_name = name;
1009 }
1010 // ----------------------------------------------------------------------------
1011 // instanciation in library
1012 // ----------------------------------------------------------------------------
1013 template class geo_rep<Float,distributed>;
1014 
1015 } // namespace rheolef
1016 #endif // _RHEOLEF_HAVE_MPI
field::size_type size_type
Definition: branch.cc:430
see the distributor page for the full documentation
Definition: distributor.h:69
size_type last_index(size_type iproc) const
Definition: distributor.h:164
void resize(size_type dis_size=0, const communicator_type &c=communicator_type(), size_type loc_size=decide)
Definition: distributor.cc:30
size_type dis_size() const
global and local sizes
Definition: distributor.h:214
size_type size(size_type iproc) const
Definition: distributor.h:170
size_type first_index(size_type iproc) const
global index range and local size owned by ip-th process
Definition: distributor.h:158
bool is_owned(size_type dis_i, size_type iproc) const
true when dis_i in [first_index(iproc):last_index(iproc)[
Definition: distributor.h:220
static const size_type decide
Definition: distributor.h:83
const communicator_type & comm() const
Definition: distributor.h:152
idiststream & get(idiststream &ips, const geo_rep< T, distributed > &omega)
geo_element_hack::size_type size_type
Definition: geo.h:260
hack_array< geo_element_hack >::iterator iterator_by_variant
Definition: geo.h:269
void set(orientation_type orient, size_type ige, size_type shift=0)
see the geo_element page for the full documentation
Definition: geo_element.h:102
geo_element_indirect::orientation_type orientation_type
Definition: geo_element.h:134
bool get_orientation_and_shift(const geo_element &S, orientation_type &orient, shift_type &shift) const
return orientation and shift between *this element and S
Definition: geo_element.cc:114
size_type edge(size_type i) const
Definition: geo_element.h:209
size_type face(size_type i) const
Definition: geo_element.h:210
size_type n_node() const
Definition: geo_element.h:170
size_type subgeo_local_vertex(size_type subgeo_dim, size_type i_subgeo, size_type i_subgeo_vertex) const
Definition: geo_element.h:223
size_type size() const
Definition: geo_element.h:168
reference_element::size_type size_type
Definition: geo_element.h:125
void set_ios_dis_ie(size_type ios_dis_ie)
Definition: geo_element.h:173
size_type dimension() const
Definition: geo_element.h:167
size_type ios_dis_ie() const
Definition: geo_element.h:164
size_type subgeo_size(size_type subgeo_dim, size_type loc_isid) const
Definition: geo_element.h:221
variant_type variant() const
Definition: geo_element.h:161
orientation_type get_edge_orientation(size_type dis_iv0, size_type dis_iv1) const
Definition: geo_element.cc:155
geo_element_indirect::shift_type shift_type
Definition: geo_element.h:135
size_type n_subgeo(size_type subgeo_dim) const
Definition: geo_element.h:212
const geo_element_indirect & face_indirect(size_type i) const
Definition: geo_element.h:197
size_type dis_ie() const
Definition: geo_element.h:163
const geo_element_indirect & edge_indirect(size_type i) const
Definition: geo_element.h:193
void set_dis_ie(size_type dis_ie)
Definition: geo_element.h:172
sequential mesh representation
Definition: geo.h:778
std::vector< T, A >::iterator iterator
Definition: hack_array.h:350
std::vector< T, A >::const_iterator const_iterator
Definition: hack_array.h:351
idiststream: see the diststream page for the full documentation
Definition: diststream.h:336
static size_type io_proc()
This routine returns the rank of a process that can perform i/o.
Definition: diststream.cc:64
void open(std::string filename, std::string suffix="", const communicator &comm=communicator())
This routine opens a physical input file.
Definition: diststream.cc:85
bool good() const
Definition: diststream.cc:124
const communicator & comm() const
Definition: diststream.h:356
void inplace_intersection(const index_set &b)
void insert(size_type dis_i)
static const variant_type max_variant
static void init_local_nnode_by_variant(size_type order, std::array< size_type, reference_element::max_variant > &loc_nnod_by_variant)
static variant_type last_variant_by_dimension(size_type dim)
static variant_type first_variant_by_dimension(size_type dim)
static const variant_type p
variant_type variant() const
static std::set< size_t > empty_set
Definition: space_seq.cc:59
size_t size_type
Definition: basis_get.cc:76
#define assert_macro(ok_condition, message)
Definition: dis_macros.h:113
check_macro(expr1.have_homogeneous_space(Xh1), "dual(expr1,expr2); expr1 should have homogeneous space. HINT: use dual(interpolate(Xh, expr1),expr2)")
void generic_set_ios_permutation(const basis_basic< T > &b, size_t map_d, const geo_size &gs, const std::array< disarray< size_t, distributed >, reference_element::max_variant > &igev2ios_dis_igev, disarray< size_t, distributed > &idof2ios_dis_idof)
void dis_idof(const basis_basic< T > &b, const geo_size &gs, const geo_element &K, typename std::vector< size_type >::iterator dis_idof_tab)
void dis_inod(const basis_basic< T > &b, const geo_size &gs, const geo_element &K, typename std::vector< size_type >::iterator dis_inod_tab)
size_type dis_nnod(const basis_basic< T > &b, const geo_size &gs, size_type map_dim)
This file is part of Rheolef.
void compute_bbox(const geo_base_rep< T, M > &omega, const geo_element &K, point_basic< T > &xmin, point_basic< T > &xmax)
Definition: geo_locate.cc:50
string delete_suffix(const string &name, const string &suffix)
delete_suffix: see the rheostream page for the full documentation
Definition: rheostream.cc:226
void geo_element_renumbering_part2(const std::array< hack_array< geo_element_hack >, reference_element::max_variant > &ios_geo_element, const geo_size &ios_gs, size_t dis_nv, size_t side_dim, std::array< hack_array< geo_element_hack >, reference_element::max_variant > &geo_element, geo_size &gs, std::array< disarray< size_t >, reference_element::max_variant > &igev2ios_dis_igev, std::array< disarray< size_t >, reference_element::max_variant > &ios_igev2dis_igev, std::array< disarray< size_t >, 4 > &ios_ige2dis_ige, std::array< disarray< size_t >, reference_element::max_variant > &partition_by_variant)
Definition: geo_mpi_get.cc:238
string get_basename(const string &name)
get_basename: see the rheostream page for the full documentation
Definition: rheostream.cc:258
void geo_element_renumbering_propagate(const std::vector< geo_element::size_type > &new_global_node_num, size_t dis_nnod, hack_array< geo_element_hack > &gev)
Definition: geo_mpi_get.cc:317
disarray< size_t > geo_mpi_partition(const std::array< hack_array< geo_element_hack >, reference_element::max_variant > &ios_geo_element, const distributor &ownership_by_dimension, size_t map_dim, size_t dis_nv)
void geo_element_renumbering_part1_new(const std::array< hack_array< geo_element_hack >, reference_element::max_variant > &ios_geo_element, const geo_size &ios_gs, size_t S_dim, std::array< std::vector< size_t >, 4 > &massive_partition_by_dimension, std::array< disarray< size_t >, reference_element::max_variant > &partition_by_variant)
Definition: geo_mpi_get.cc:120
bool dis_scatch(idiststream &ips, const communicator &comm, std::string ch)
distributed version of scatch(istream&,string)
Definition: diststream.cc:44
void load(idiststream &in, Float &p, field &uh)
point input helper
Definition: geo.h:155
bool need_upgrade() const
Definition: geo_header.cc:79
size_type map_dimension
Definition: geo_header.h:40
size_type dis_size_by_dimension[4]
Definition: geo_header.h:44
coordinate_type sys_coord
Definition: geo_header.h:41
size_type dimension
Definition: geo_header.h:39
size_type dis_size_by_variant[reference_element::max_variant]
Definition: geo_header.h:43
distributor ownership_by_variant[reference_element::max_variant]
Definition: geo_size.h:64
distributor ownership_by_dimension[4]
Definition: geo_size.h:63
distributor first_by_variant[reference_element::max_variant]
Definition: geo_size.h:66