rheolef  6.5
space_constitution.cc
Go to the documentation of this file.
1 
2 #include "rheolef/space.h"
3 #include "rheolef/space_mult.h"
4 #include "rheolef/piola.h"
5 #include <sstream>
6 
7 namespace rheolef {
8 
9 template <class T, class M>
11  const geo_basic<T,M>& omega,
12  std::string approx,
13  std::string valued)
14  : _ownership(),
15  _start_by_component(),
16  _valued_tag(space_constant::scalar),
17  _is_hier(false),
18  _scalar_constit(),
19  _hier_constit()
20 {
21  if (valued == "scalar") {
22  _scalar_constit = scalar_type (omega, approx);
23  } else { // multi-valued:
24  _is_hier = true;
25  size_type d = omega.dimension();
27  size_type n_comp = space_constant::n_component (_valued_tag, d, omega.coordinate_system());
28  _hier_constit.resize(n_comp);
29  space_constitution<T,M> x (omega, approx);
30  for (size_type i_comp = 0; i_comp < n_comp; i_comp++) {
31  _hier_constit [i_comp] = x;
32  }
33  }
34  initialize();
35 }
36 template <class T, class M>
38  : _ownership(),
39  _start_by_component(),
40  _valued_tag(space_constant::mixed),
41  _is_hier(true),
42  _scalar_constit(),
43  _hier_constit(expr.size())
44 {
46  for (typename space_mult_list<T,M>::const_iterator iter = expr.begin(), last = expr.end(); iter != last; ++iter, ++iter_constit) {
47  const space_basic<T,M>& Xi = *iter;
48  *iter_constit = Xi.get_constitution();
49  }
50  initialize();
51 }
52 template <class T, class M>
53 void
55 {
56  _ownership = distributor (internal_dis_ndof(), internal_comm(), internal_ndof());
57  init_start_by_component();
58 }
59 template <class T, class M>
60 bool
62 {
63  if (_is_hier != V2._is_hier) return false;
64  if (!_is_hier) return (_scalar_constit == V2._scalar_constit);
65  if (_hier_constit.size() != V2._hier_constit.size()) return false;
66  for (const_iterator iter1 = _hier_constit.begin(), iter2 = V2._hier_constit.begin(), last1 = _hier_constit.end(); iter1 != last1; ++iter1, ++iter2) {
67  if (! (*iter1).data().operator==((*iter2).data())) { // recursive call
68  return false;
69  }
70  }
71  return true;
72 }
73 template <class T, class M>
74 communicator
76 {
77  if (! is_initialized()) { return communicator(); }
78  return get_geo().comm();
79 }
80 template <class T, class M>
81 communicator
83 {
84  if (!_is_hier) {
85  return _scalar_constit.get_geo().comm();
86  }
87  for (const_iterator iter = _hier_constit.begin(), last = _hier_constit.end(); iter != last; ++iter) {
88  const space_constitution<T,M>& constit = *iter;
89  return constit.data().internal_comm(); // recursive call
90  }
91  return communicator();
92 }
93 template <class T, class M>
96 {
97  if (! is_initialized()) { return 0; }
98  return get_numbering().ndof (get_geo().sizes(), get_geo().map_dimension());
99 }
100 template <class T, class M>
103 {
104  if (!_is_hier) {
105  return _scalar_constit.internal_ndof();
106  }
107  size_type ndof = 0;
108  for (const_iterator iter = _hier_constit.begin(), last = _hier_constit.end(); iter != last; ++iter) {
109  const space_constitution<T,M>& constit = *iter;
110  ndof += constit.data().internal_ndof(); // recursive call
111  }
112  return ndof;
113 }
114 template <class T, class M>
117 {
118  if (! is_initialized()) { return 0; }
119  return get_numbering().dis_ndof (get_geo().sizes(), get_geo().map_dimension());
120 }
121 template <class T, class M>
124 {
125  if (!_is_hier) {
126  return _scalar_constit.internal_dis_ndof();
127  }
128  size_type dis_ndof = 0;
129  for (const_iterator iter = _hier_constit.begin(), last = _hier_constit.end(); iter != last; ++iter) {
130  const space_constitution<T,M>& constit = *iter;
131  dis_ndof += constit.data().internal_dis_ndof(); // recursive call
132  }
133  return dis_ndof;
134 }
135 template<class T, class M>
136 std::ostream&
137 put (std::ostream& os, const space_constitution<T,M>& constit, size_t level = 0)
138 {
140  if (! constit.is_hierarchical()) {
141  const space_scalar_constitution<T,M>& scalar_constit = constit.get_scalar();
142  os << scalar_constit.get_numbering().name()
143  << "(" << scalar_constit.get_geo().name() << ")";
144  return os;
145  }
146  if (constit.valued_tag() == space_constant::vector ||
147  constit.valued_tag() == space_constant::tensor ||
149  assert_macro (constit.get_hierarchy().size() >= 1, "invalid space_constitution");
150  const space_constitution<T,M>& base_constit = *(constit.get_hierarchy().begin());
151  std::string spec = space_constant::valued_name (constit.valued_tag());
152  os << spec << "(";
153  put (os, base_constit, level+1);
154  os << ")";
155  return os;
156  }
157  if (level > 0) os << "(";
159  for (size_type i = 0, n = constit.get_hierarchy().size(); i < n; i++) {
160  const space_constitution<T,M>& xi = x[i];
161  put (os, xi, level+1); // recursive call
162  if (i+1 < n) { os << "*"; }
163  }
164  if (level > 0) os << ")";
165  return os;
166 }
167 template<class T, class M>
168 std::ostream&
169 operator<< (std::ostream& os, const space_constitution<T,M>& constit)
170 {
171  return put (os, constit);
172 }
173 template<class T, class M>
174 std::string
176 {
177  std::ostringstream ostrstr;
178  ostrstr << *this;
179  return ostrstr.str ();
180 }
181 template <class T, class M>
182 void
184 {
185  check_macro (!get_numbering().has_compact_support_inside_element(),
186  "try to [un]block domain `" << act.get_domain_name() << "' on discontinuous or bubble space("
187  << get_numbering().name()<<"(" <<_omega.name()<<"))");
188  _acts.push_back (act);
189 }
190 template <class T, class M>
191 void
193 {
195  if (! is_hierarchical()) {
196  space_scalar_constitution<T,M>& scalar_constit = get_scalar();
197  scalar_constit.do_act (act);
198  return;
199  }
200  for (iterator iter = _hier_constit.begin(), last = _hier_constit.end(); iter != last; ++iter) {
201  space_constitution<T,M>& constit = *iter;
202  constit.do_act (act); // recursive call
203  }
204 }
205 template <class T, class M>
206 void
208  array<size_type,M>& blocked_flag, // array<bool,M> not supported
209  const distributor& comp_ownership,
210  const distributor& start_by_component) const
211 {
212  check_macro (get_numbering().name() != "", "space with undefined finite element method cannot be used");
213  std::vector<size_type> comp_dis_idof_t;
214  distributor dof_ownership = blocked_flag.ownership();
215  size_type dis_ndof = dof_ownership.dis_size();
216  bool prev_act = space_act::block;
217  for (const_iterator iter = begin(), last = end(); iter != last; iter++) {
218  typename space_act::act_type act = (*iter).get_act();
219  const std::string& dom_name = (*iter).get_domain_name();
220  if (prev_act != act) {
221  blocked_flag.dis_entry_assembly();
222  prev_act = act;
223  }
224  const domain_indirect_basic<M>& dom = _omega.get_domain_indirect(dom_name);
225  size_type dom_dim = dom.map_dimension();
226  distributor ige_ownership = _omega.geo_element_ownership (dom_dim);
227  size_type first_dis_ige = ige_ownership.first_index();
228  size_type last_dis_ige = ige_ownership.last_index();
229  bool blk = (act == space_act::block) ? true : false;
230  for (size_type ioige = 0, noige = dom.size(); ioige < noige; ioige++) {
231  size_type ige = dom.oige (ioige).index();
232  size_type dis_ige = ige + first_dis_ige;
233  const geo_element& S = _omega.get_geo_element (dom_dim, ige);
234  get_numbering().dis_idof (_omega.sizes(), S, comp_dis_idof_t);
235  for (size_type loc_idof = 0, loc_ndof = comp_dis_idof_t.size(); loc_idof < loc_ndof; loc_idof++) {
236  size_type comp_dis_idof = comp_dis_idof_t [loc_idof];
237  size_type iproc = comp_ownership.find_owner (comp_dis_idof);
238  size_type first_comp_dis_idof = comp_ownership.first_index (iproc);
239  assert_macro (comp_dis_idof >= first_comp_dis_idof, "unexpected comp_dis_idof");
240  size_type comp_idof = comp_dis_idof - first_comp_dis_idof;
241  size_type comp_start_idof = start_by_component.size(iproc);
242  size_type idof = comp_start_idof + comp_idof;
243  size_type first_dis_idof = dof_ownership.first_index(iproc);
244  size_type dis_idof = first_dis_idof + idof;
245  assert_macro (dis_idof < dis_ndof, "unexpected dis_idof");
246  blocked_flag.dis_entry (dis_idof) = blk;
247  }
248  }
249  }
250 }
251 template <class T, class M>
252 void
254  array<size_type,M>& blocked_flag, // array<bool,M> not supported
255  const std::vector<distributor>& start_by_component,
256  size_type& i_comp) const
257 {
258  if (! is_hierarchical()) {
259  const space_scalar_constitution<T,M>& scalar_constit = get_scalar();
260  scalar_constit.data().build_blocked_flag (blocked_flag, ownership(), start_by_component [i_comp]);
261  i_comp++;
262  return;
263  }
264  for (const_iterator iter = _hier_constit.begin(), last = _hier_constit.end(); iter != last; ++iter) {
265  const space_constitution<T,M>& constit = *iter;
266  constit.data().build_blocked_flag_recursive (blocked_flag, start_by_component, i_comp); // recursive call
267  }
268 }
269 template <class T, class M>
272 {
273  array<size_type,M> blocked_flag (ownership(), 0); // array<bool,M> not supported
274  size_type i_comp = 0;
275  build_blocked_flag_recursive (blocked_flag, _start_by_component, i_comp);
276  blocked_flag.dis_entry_assembly();
277  return blocked_flag;
278 }
279 template <class T, class M>
280 const geo_basic<T,M>&
282 {
283  if (! is_hierarchical()) {
284  return get_scalar().get_geo();
285  }
286  check_macro (_valued_tag == space_constant::vector ||
287  _valued_tag == space_constant::tensor ||
288  _valued_tag == space_constant::unsymmetric_tensor,
289  "get_geo: undefined for heterogeneous space products");
290  assert_macro (_hier_constit.size() > 0, "get_geo: empty vectorial/tensorial space product");
291  const_iterator iter = _hier_constit.begin();
292  const space_constitution<T,M>& constit = (*iter);
293  return constit.get_scalar().get_geo();
294 }
295 template <class T, class M>
296 const numbering<T,M>&
298 {
299  if (! is_hierarchical()) {
300  return get_scalar().get_numbering();
301  }
302  check_macro (_valued_tag == space_constant::vector ||
303  _valued_tag == space_constant::tensor ||
304  _valued_tag == space_constant::unsymmetric_tensor,
305  "get_numbering: undefined for heterogeneous space products");
306  assert_macro (_hier_constit.size() > 0, "get_numbering: empty vectorial/tensorial space product");
307  const_iterator iter = _hier_constit.begin();
308  const space_constitution<T,M>& constit = (*iter);
309  return constit.get_scalar().get_numbering();
310 }
311 template <class T, class M>
314 {
315  if (!_is_hier) {
316  communicator comm =_scalar_constit.get_geo().comm();
317  size_type dis_ndof =_scalar_constit.get_numbering().dis_ndof (_scalar_constit.get_geo().sizes(), _scalar_constit.get_geo().map_dimension());
318  distributor ios_ownership (dis_ndof, comm, distributor::decide);
319  return ios_ownership.size();
320  }
321  size_type ios_ndof = 0;
322  for (const_iterator iter = _hier_constit.begin(), last = _hier_constit.end(); iter != last; ++iter) {
323  const space_constitution<T,M>& constit = *iter;
324  ios_ndof += constit.ios_ndof(); // recursive call
325  }
326  return ios_ndof;
327 }
328 template <class T, class M>
329 void
331  array<size_type,M>& idof2ios_dis_idof,
332  size_type& comp_start_idof,
333  size_type& comp_start_dis_idof) const
334 {
335  if (!_is_hier) {
336  array<size_type,M> comp_idof2ios_dis_idof;
337  array<size_type,M> comp_ios_idof2dis_idof;
338  _scalar_constit.get_numbering().set_ios_permutations (_scalar_constit.get_geo(), comp_idof2ios_dis_idof, comp_ios_idof2dis_idof);
339  size_type comp_ndof = comp_idof2ios_dis_idof.size();
340  size_type comp_dis_ndof = comp_idof2ios_dis_idof.dis_size();
341  size_type ndof = idof2ios_dis_idof.size();
342  size_type dis_ndof = idof2ios_dis_idof.dis_size();
343  for (size_type comp_idof = 0; comp_idof < comp_ndof; comp_idof++) {
344  size_type comp_ios_dis_idof = comp_idof2ios_dis_idof [comp_idof];
345  size_type ios_dis_idof = comp_start_dis_idof + comp_ios_dis_idof;
346  size_type idof = comp_start_idof + comp_idof;
347  assert_macro (idof < ndof, "unexpected idof="<<idof<<" out of range [0:"<<ndof<<"[");
348  assert_macro (ios_dis_idof < dis_ndof, "unexpected ios_dis_idof="<<ios_dis_idof<<" out of range [0:"<<dis_ndof<<"[");
349  idof2ios_dis_idof [idof] = ios_dis_idof;
350  }
351  comp_start_idof += comp_ndof;
352  comp_start_dis_idof += comp_dis_ndof;
353  return;
354  }
355  for (const_iterator iter = _hier_constit.begin(), last = _hier_constit.end(); iter != last; ++iter) {
356  const space_constitution<T,M>& constit = *iter;
357  constit.set_ios_permutation_recursion (idof2ios_dis_idof, comp_start_idof, comp_start_dis_idof); // recursive call
358  }
359 }
360 template <class T, class M>
361 void
363  array<size_type,M>& idof2ios_dis_idof,
364  array<size_type,M>& ios_idof2dis_idof) const
365 {
366  if (!_is_hier) {
367  _scalar_constit.get_numbering().set_ios_permutations (_scalar_constit.get_geo(), idof2ios_dis_idof, ios_idof2dis_idof);
368  return;
369  }
370  communicator comm1 = comm();
371  distributor dof_ownership = ownership();
372  size_type ndof1 = dof_ownership.size();
373  size_type dis_ndof1 = dof_ownership.dis_size();
374  idof2ios_dis_idof.resize (dof_ownership, std::numeric_limits<size_type>::max());
375  size_type comp_start_idof = 0;
376  size_type comp_start_dis_idof = 0;
377  set_ios_permutation_recursion (idof2ios_dis_idof, comp_start_idof, comp_start_dis_idof);
378  size_type ios_ndof1 = ios_ndof();
379  distributor ios_dof_ownership (dis_ndof1, idof2ios_dis_idof.comm(), ios_ndof1);
380  ios_idof2dis_idof.resize (ios_dof_ownership, std::numeric_limits<size_type>::max());
381  idof2ios_dis_idof.reverse_permutation (ios_idof2dis_idof);
382 }
383 template <class T, class M>
386 {
387  switch (valued_tag()) {
388  case space_constant::scalar: {
389  return get_numbering().get_basis().size (hat_K);
390  }
394  size_type loc_comp_ndof = get_numbering().get_basis().size (hat_K);
395  size_type n_comp = size();
396  return n_comp*loc_comp_ndof;
397  }
398  default: {
399  fatal_macro ("dis_idof: hybrid multi-component: not yet");
400  return 0; // not reached
401  }
402  }
403 }
404 template <class T, class M>
405 void
406 space_constitution_rep<T,M>::dis_idof (const geo_element& K, std::vector<size_type>& dis_idof_t) const
407 {
408  size_type n_comp = size();
409  switch (valued_tag()) {
410  case space_constant::scalar: {
411  get_numbering().dis_idof (get_geo().sizes(), K, dis_idof_t);
412  return;
413  }
417  assert_macro (_hier_constit.size() > 0, "unexpected empty vector valued");
418  distributor comp_ownership = _hier_constit [0].ownership();
419  size_type comp_dis_ndof = get_numbering().dis_ndof (get_geo().sizes(), get_geo().map_dimension());
420  std::vector<size_type> comp_dis_idof_t;
421  get_numbering().dis_idof (get_geo().sizes(), K, comp_dis_idof_t);
422  size_type loc_ndof = comp_dis_idof_t.size();
423  dis_idof_t.resize (n_comp*loc_ndof);
424  for (size_type loc_idof = 0; loc_idof < loc_ndof; loc_idof++) {
425  size_type comp_dis_idof = comp_dis_idof_t [loc_idof];
426  size_type iproc = comp_ownership.find_owner (comp_dis_idof);
427  size_type comp_first_dis_idof = comp_ownership.first_index(iproc);
428  assert_macro (comp_dis_idof >= comp_first_dis_idof, "unexpected comp_dis_idof");
429  size_type comp_idof = comp_dis_idof - comp_first_dis_idof;
430  size_type first_dis_idof = ownership().first_index(iproc);
431  for (size_type i_comp = 0; i_comp < n_comp; i_comp++) {
432  size_type comp_start_idof = _start_by_component [i_comp].size(iproc);
433  size_type idof = comp_start_idof + comp_idof;
434  size_type dis_idof = first_dis_idof + idof;
435  dis_idof_t [i_comp*loc_ndof + loc_idof] = dis_idof;
436  }
437  }
438  return;
439  }
440  default: {
441  fatal_macro ("dis_idof: hybrid multi-component: not yet");
442  }
443  }
444 }
445 // => build _start_by_component : used by set_external_dof()
446 template <class T, class M>
449 {
450  if (!_is_hier) {
451  return 1;
452  }
453  size_type n_comp = 0;
454  for (const_iterator iter = _hier_constit.begin(), last = _hier_constit.end(); iter != last; ++iter) {
455  n_comp += (*iter).data().n_component_recursive(); // recursive call
456  }
457  return n_comp;
458 }
459 template <class T, class M>
460 void
462  std::vector<distributor>& start_by_component,
463  size_type& i_comp,
464  const communicator& comm,
465  size_type& comp_start_idof,
466  size_type& comp_start_dis_idof) const
467 {
468  if (!_is_hier) {
469  start_by_component [i_comp] = distributor (comp_start_dis_idof, comm, comp_start_idof);
470  i_comp++;
471  comp_start_idof += ndof();
472  comp_start_dis_idof += dis_ndof();
473  return;
474  }
475  for (const_iterator iter = _hier_constit.begin(), last = _hier_constit.end(); iter != last; ++iter) {
476  (*iter).data().init_start_by_component (start_by_component, i_comp, comm,
477  comp_start_idof, comp_start_dis_idof);
478  }
479 }
480 template <class T, class M>
481 void
483 {
484  size_type n_comp_rec = n_component_recursive();
485  _start_by_component.resize (n_comp_rec);
486  size_type i_comp = 0;
487  size_type comp_start_idof = 0;
488  size_type comp_start_dis_idof = 0;
489  init_start_by_component (_start_by_component, i_comp, comm(), comp_start_idof, comp_start_dis_idof);
490 }
491 // get external idofs: used by space<distributed>::freeze
492 template <class T, class M>
493 void
495  const geo_basic<T,M>& dom,
496  std::set<size_type>& ext_dof_set,
497  const distributor& dof_ownership,
498  const distributor& start_by_component) const
499 {
500  distributor comp_ownership = ownership();
501  size_type comp_dis_ndof = comp_ownership.dis_size();
502  std::vector<size_type> comp_dis_idof1;
503  for (size_type ie = 0, ne = dom.size(); ie < ne; ie++) {
504  const geo_element& K = dom [ie];
505  dis_idof (K, comp_dis_idof1);
506  for (size_type loc_idof = 0, loc_ndof = comp_dis_idof1.size(); loc_idof < loc_ndof; loc_idof++) {
507  size_type comp_dis_idof = comp_dis_idof1 [loc_idof];
508  assert_macro (comp_dis_idof < comp_dis_ndof, "idof " << comp_dis_idof1 [loc_idof] << " out of range[0:"<< comp_dis_ndof << "[");
509  if (! comp_ownership.is_owned (comp_dis_idof)) {
510  size_type iproc = comp_ownership.find_owner (comp_dis_idof);
511  size_type comp_first_dis_idof = comp_ownership.first_index(iproc);
512  assert_macro (comp_dis_idof >= comp_first_dis_idof, "unexpected comp_dis_idof");
513  size_type comp_idof = comp_dis_idof - comp_first_dis_idof;
514  size_type comp_start_idof = start_by_component.size(iproc);
515  size_type idof = comp_start_idof + comp_idof;
516  size_type first_dis_idof = dof_ownership.first_index(iproc);
517  size_type dis_idof = first_dis_idof + idof;
518  assert_macro (! dof_ownership.is_owned (dis_idof), "unexpected dis_idof="<<dis_idof<<" in range ["
519  << first_dis_idof << ":" << dof_ownership.last_index() << "[");
520  ext_dof_set.insert (dis_idof);
521  }
522  }
523  }
524 }
525 template <class T, class M>
526 void
528  const geo_basic<T,M>& dom,
529  std::set<size_type>& ext_dof_set,
530  const distributor& dof_ownership,
531  const distributor& start_by_component) const
532 {
533  size_type dim = dom.dimension();
534  size_type map_dim = dom.map_dimension();
535  if (dim > map_dim) {
536  return;
537  }
538  if (dom.name() != dom.get_background_geo().name()) {
539  return;
540  }
541  dom.neighbour_guard(); // uses S.master(i), a neighbour connnectivity
542  if (map_dim == 0) return; // no sides
543  size_type sid_dim = map_dim-1;
544  distributor comp_ownership = ownership();
545  size_type comp_dis_ndof = comp_ownership.dis_size();
546  std::vector<size_type> comp_dis_idof1;
547  for (size_type isid = 0, nsid = dom.size(sid_dim); isid < nsid; isid++) {
548  const geo_element& S = dom.get_geo_element (sid_dim, isid);
549  for (size_type i_master = 0; i_master < 2; i_master++) {
550  size_type dis_ie = S.master(i_master); // two possible Ki such that S is a side of Ki
551  if (dis_ie == std::numeric_limits<size_type>::max()) continue; // S is on the boundary
552  const geo_element& K = dom.dis_get_geo_element (map_dim, dis_ie);
553  dis_idof (K, comp_dis_idof1);
554  for (size_type loc_idof = 0, loc_ndof = comp_dis_idof1.size(); loc_idof < loc_ndof; loc_idof++) {
555  size_type comp_dis_idof = comp_dis_idof1 [loc_idof];
556  assert_macro (comp_dis_idof < comp_dis_ndof, "idof " << comp_dis_idof1 [loc_idof] << " out of range[0:"<< comp_dis_ndof << "[");
557  if (! comp_ownership.is_owned (comp_dis_idof)) {
558  size_type iproc = comp_ownership.find_owner (comp_dis_idof);
559  size_type comp_first_dis_idof = comp_ownership.first_index(iproc);
560  assert_macro (comp_dis_idof >= comp_first_dis_idof, "unexpected comp_dis_idof");
561  size_type comp_idof = comp_dis_idof - comp_first_dis_idof;
562  size_type comp_start_idof = start_by_component.size(iproc);
563  size_type idof = comp_start_idof + comp_idof;
564  size_type first_dis_idof = dof_ownership.first_index(iproc);
565  size_type dis_idof = first_dis_idof + idof;
566  assert_macro (! dof_ownership.is_owned (dis_idof), "unexpected dis_idof="<<dis_idof<<" in range ["
567  << first_dis_idof << ":" << dof_ownership.last_index() << "[");
568  ext_dof_set.insert (dis_idof);
569  }
570  }
571  }
572  }
573 }
574 template <class T, class M>
575 void
577  std::set<size_type>& ext_dof_set,
578  const distributor& dof_ownership,
579  const std::vector<distributor>& start_by_component,
580  size_type& i_comp) const
581 {
582  if (! is_hierarchical()) {
583  const space_scalar_constitution<T,M>& scalar_constit = get_scalar();
584  if (! scalar_constit.get_numbering().has_compact_support_inside_element()) {
585  continuous_append_external_dof (scalar_constit.get_geo(), ext_dof_set, dof_ownership, start_by_component [i_comp]);
586  for (size_type idom = 0, ndom = scalar_constit.get_geo().n_domain(); idom < ndom; idom++) {
587  const geo_basic<T,M>& dom = scalar_constit.get_geo().get_domain (idom);
588  continuous_append_external_dof (dom, ext_dof_set, dof_ownership, start_by_component [i_comp]);
589  }
590  } else {
591  discontinuous_append_external_dof (scalar_constit.get_geo(), ext_dof_set, dof_ownership, start_by_component [i_comp]);
592  }
593  i_comp++;
594  return;
595  }
596  for (const_iterator iter = _hier_constit.begin(), last = _hier_constit.end(); iter != last; ++iter) {
597  (*iter).data().compute_external_dofs (ext_dof_set, dof_ownership, start_by_component, i_comp);
598  }
599 }
600 template <class T, class M>
601 void
603  std::set<size_type>& ext_dof_set) const
604 {
605  ext_dof_set.clear();
606  size_type i_comp = 0;
607  compute_external_dofs (ext_dof_set, ownership(), _start_by_component, i_comp);
608 }
612 template std::ostream& operator<< (std::ostream&, const space_constitution<Float,sequential>&);
613 
614 #ifdef _RHEOLEF_HAVE_MPI
618 template std::ostream& operator<< (std::ostream&, const space_constitution<Float,distributed>&);
619 #endif // _RHEOLEF_HAVE_MPI
620 
621 } // namespace rheolef
622