domainDecomp.hh

Go to the documentation of this file.
1 
6 #ifndef spcDomainDecomp_hh
7 #define spcDomainDecomp_hh
8 
9 #include "basics/debug.hh"
12 #include "geometry/mesh.hh"
13 #include "space/space.hh"
14 #include "space/spaceSet.hh"
15 #include "toolbox/hashMap.hh"
17 #include "toolbox/sequence.hh"
18 #include "toolbox/set.hh"
19 
20 #define DDSpaceConstr_D 0
21 #define DDSpaceDestr_D 0
22 #define DDSpaceRebuild_D 0
23 #define DDSpaceGetIndices_D 0
24 #define DDSpaceInfoIndices_D 0
25 
26 namespace concepts {
27 
28  // *************************************************************** DDSpace **
29 
30  template<class F>
31  class DDSpace : public Space<F> {
32  public:
34  DDSpace(uint domains = 0) : domains_(domains) {}
35  virtual ~DDSpace() {}
37  const uint domains() const { return domains_; }
39  virtual const Space<F>& space(uint i) const = 0;
41  virtual const Set<IndexRange> indicesI(uint i) const = 0;
43 // virtual const Sequence<Set<IndexRange> >& indicesI() const {
44 // return indicesI_; }
46  virtual const Set<IndexRange> indicesB(uint i) const = 0;
48 // virtual const Sequence<Set<IndexRange> >& indicesB() const {
49 // return indicesB_; }
50  protected:
51  virtual std::ostream& info(std::ostream& os) const;
52 
54  uint domains_;
57  };
58 
59  template<class F>
60  std::ostream& DDSpace<F>::info(std::ostream& os) const {
61  return os << "DDSpace(" << domains_ << " domains)";
62  }
63 
64  // ********************************************************** DomainDecomp **
65 
71  template<class F>
72  class DomainDecomp : public DDSpace<typename F::t_type>, public Subspace {
73  public:
80 
92  template<class G>
93  DomainDecomp(G& prebuild, Sequence<Set<uint> > domains,
94  BoundaryConditions* bc = 0, CellConditions* cc = 0,
95  uint spcNo = 0, uint* offset = 0);
96  virtual ~DomainDecomp();
97 
99  void rebuild();
107  bool available() const;
108 
109  inline virtual uint dim() const;
110  inline virtual uint nelm() const;
111  inline virtual Scan* scan() const;
112 // inline Scan* scan();
113 
115  virtual uint& lastIdx();
117  virtual uint offset() const;
119  virtual const F& space(uint i) const;
120  F& space(uint i);
122  virtual const Set<IndexRange> indicesI(uint i) const;
123 // const Sequence<Set<IndexRange> >& indicesI() const { return indicesI_; }
125  virtual const Set<IndexRange> indicesB(uint i) const;
126 // const Sequence<Set<IndexRange> >& indicesB() const { return indicesB_; }
127  protected:
128  virtual std::ostream& info(std::ostream& os) const;
129  private:
134  uint spcNo_;
141 
144 
152  uint nelm_;
153 
154  uint idx_;
155 
156  template<class G, class H>
157  void getIndices_(const G& prebuild, const H& cntr,
158  Set<IndexRange>& indices);
159  };
160 
161  template<class F>
162  template<class G>
165  uint spcNo, uint* offset) :
166  DDSpace<typename F::t_type>(), spcNo_(spcNo), spcBuild_(0),
167  elm_(0), nelm_(0) {
168  // collect all attributes of coarse mesh
169  Set<uint> attributes, tmp;
170  std::unique_ptr<concepts::Scan2> sc(prebuild.mesh().scan());
171  while (*sc) {
172  const Attribute& attr = (*sc)++.connector().attrib();
173  if (!cc || ((*cc)(attr).type() != CellCondition::INACTIVE))
174  attributes.insert(attr);
175  }
176  tmp = attributes;
177  DEBUGL(DDSpaceConstr_D, "attributes in mesh = " << attributes);
178 
179 
180  // collect all attributes and delete empty domains
181  Sequence<Set<uint> >::iterator i = domains.begin();
182  for (; i != domains.end(); ) {
183  // set difference with valid attributes
184  Set<uint> nonvalid = *i - tmp;
185  // there are only valid attributes given
186  conceptsAssert3(nonvalid.empty(), Assertion(), "non valid attributes " <<
187  nonvalid << " in given domain " << *i);
188 
189  if ((*i).empty())
190  i = domains.erase(i); // delete empty domain
191  else {
192  // contribute to mapping from attribute to domain
193  for(Set<uint>::const_iterator j = (*i).begin(); j != (*i).end(); ++j)
194  attrToDomain_[*j] = this->domains_;
195  tmp = tmp - *i++; // erase attributes from set
196  ++this->domains_; // count non-empty domains
197  }
198  }
199 
200  // rest of attributes to a new domain
201  if (!tmp.empty()) {
202  domains.push_back(tmp);
203  // contribute to mapping from attribute to domain
204  for(Set<uint>::const_iterator j = tmp.begin(); j != tmp.end(); ++j)
205  attrToDomain_[*j] = this->domains_;
206  ++this->domains_;
207  }
208 
209  DEBUGL(DDSpaceConstr_D, "domains = " << domains);
210 
211  // set the number of builds to zero
212  spcBuild_.resize(this->domains_);
213  spcBuild_.zeros();
214 
215  i = domains.begin();
216  for (; i != domains.end(); ) {
217 
218  // create for each domain a entrance
219  cc_.insert(cc_.end(), this->domains_, CellConditions());
220 
221  i = domains.begin();
222  for (Sequence<CellConditions>::iterator j = cc_.begin(); j != cc_.end();
223  ++j, ++i) {
224  // set difference with valid attributes
225  const Set<uint> nonactiv = attributes - *i;
226  for (Set<uint>::const_iterator k = nonactiv.begin();
227  k != nonactiv.end(); ++k)
228  (*j).add(*k, CellCondition::INACTIVE);
229  }
230  }
231  DEBUGL(DDSpaceConstr_D, "cell conditions of domains = " << cc_);
232 
233  // create spaces
234  uint* idx = 0;
235  F* spc;
236  for (Sequence<CellConditions>::iterator j = cc_.begin(); j != cc_.end(); ++j)
237  {
238  spaces_.push_back(spc = new F(prebuild, bc, &*j, spcNo_, offset, idx));
239  idx = &spc->lastIdx();
240  }
241  DEBUGL(DDSpaceConstr_D, "spaces of domains = " << spaces_);
242 
243  // reserve space for index sets for each sub domains
244  this->indicesI_.resize(this->domains_, Set<IndexRange>());
245  this->indicesB_.resize(this->domains_, Set<IndexRange>());
246  }
247 
248  template<class F>
250  // deletes in reverse order, because the first space holds the
251  // pointer to the index
252  uint k = this->domains();
253  typename Sequence<F*>::reverse_iterator i = spaces_.rbegin();
254  for (; i != spaces_.rend(); ++i) {
255  DEBUGL(DDSpaceDestr_D, "Try to delete Space(" << k-- << ") = " << **i);
256  delete *i;
257  }
259  DEBUGL(DDSpaceDestr_D, "done");
260  }
261 
262  template<class F>
263  std::ostream& DomainDecomp<F>::info(std::ostream& os) const {
264  os << "DomainDecomp(" << this->domains_ << " domains, ";
265  if (!available())
266  os << "not built";
267  else {
268  os << "dim = " << dim() << ", nelm = " << nelm() << ", ";
269  for (uint i = 0; i < spaces_.size();) {
270  os << "space(" << i << ") = " << space(i);
271 #if DDSpaceInfoIndices_D
272  os << ", I(" << i << ") = " << indicesI(i)
273  << ", B(" << i << ") = " << indicesB(i);
274 #else
275  os << ", I(" << i << ").dim = " << indicesI(i).dim()
276  << ", B(" << i << ").dim = " << indicesB(i).dim();
277 #endif
278  if (++i < spaces_.size()) os << ", ";
279  }
280  }
281  return os << ")";
282  }
283 
284  template<class F>
286  DEBUGL(DDSpaceRebuild_D, "Start rebuilding");
287  // If nothing to do, do nothing
288  if (available()) {
289  DEBUGL(DDSpaceRebuild_D, "space already built - nothing to do");
290  return;
291  }
292 
293  // Remove old list, but not elements. They are removed in spaces
294  // itself.
296  nelm_ = 0;
297 
298  // Rebuild all spaces, but don't refresh own array of all
299  // elements. That is done in method scan(), because the
300  // rebuild()-method of the spaces could be called also directly.
301  uint k = 0;
302  typename Sequence<F*>::iterator i = spaces_.begin();
303  // reset the index counter (identical for all spaces/domains)
304  (*i)->lastIdx() = (*i)->offset();
305  // clear all indices
306  (*i)->prebuild().clearAllIndices(spcNo_);
307  uint* b = spcBuild_;
308  for (; i != spaces_.end(); ++i) {
309  (*i)->rebuild(true);
310  DEBUGL(DDSpaceRebuild_D, "Space(" << k++ << ") = " << **i);
311  // space should be available now
312  conceptsAssert((*i)->available().first, Assertion());
313  // memorize number of the build
314  *b++ = (*i)->available().second;
315  conceptsAssert(nelm_ == 0 || (*i)->nelm() == nelm_, Assertion());
316  nelm_ = (*i)->nelm();
317  DEBUGL(DDSpaceRebuild_D, "nelm = " << nelm_);
318  }
319 
320  // fill list of elements
321  uint j = 0;
322  std::unique_ptr<typename Space<typename F::t_type>::Scanner> sc(nullptr);
323  for (i = spaces_.begin(); i != spaces_.end(); ++i) {
324  sc.reset((*i)->scan());
325  while (*sc) {
326  Element* elm = &(*sc)++;
327  DEBUGL(DDSpaceRebuild_D, "Element = " << elm);
328  DEBUGL(DDSpaceRebuild_D, "Element = " << *elm);
329  if (elm->T().n() > 0) {
330  DEBUGL(DDSpaceRebuild_D, "Element(" << j << ") = " << *elm);
331  elm_ = new concepts::Joiner<Element*, 1>(elm, elm_);
332  ++j;
333  }
334  }
335  }
336  conceptsAssert(j == nelm_, Assertion());
337 
338  for(uint j = 0; j < this->domains_; ++j) {
339  this->indicesI_[j].clear();
340  this->indicesB_[j].clear();
341  }
342 
343  // collect all index ranges into this set to determine if a index
344  // range occurs at least two times
345  Set<IndexRange> indices;
346  std::unique_ptr<concepts::Scan2> se(spaces_[0]->prebuild().mesh().scan());
347  while (*se)
348  getIndices_(spaces_[0]->prebuild(), (*se)++.connector(), indices);
349 
350 #if DDSpaceRebuild_D
351  for(uint j = 0; j < this->domains_; ++j) {
352  DEBUGL(1, "indicesI_[" << j << "] = " << this->indicesI_[j]);
353  DEBUGL(1, "indicesB_[" << j << "] = " << this->indicesB_[j]);
354  }
355 
356  i = spaces_.begin(); k = 0;
357  for (; i != spaces_.end(); ++i)
358  DEBUGL(1, "Space(" << k++ << ") = " << **i);
359 #endif
360  }
361 
362  template<class F>
364 // uint build;
365  const uint* b = spcBuild_;
366  typename Sequence<F*>::const_iterator i = spaces_.begin();
367  while(i != spaces_.end() && (*i)->available().first &&
368  (*i)->available().second == *b++) ++i;
369  return i == spaces_.end();
370  }
371 
372  template<class F>
373  uint DomainDecomp<F>::dim() const {
374  if (!available())
376  // dimension is for the spaces of all domains the same, they live
377  // on the same index range
378  return (*spaces_.begin())->dim();
379  }
380 
381  template<class F>
382  uint DomainDecomp<F>::nelm() const {
383  if (!available())
385  return nelm_;
386  }
387 
388  template<class F>
390  if (!available())
392  return new concepts::PListScan<Element>(*elm_);
393  }
394 
395  template<class F>
397  return (*spaces_.begin())->lastIdx();
398  }
399 
400  template<class F>
401  uint DomainDecomp<F>::offset() const {
402  return (*spaces_.begin())->offset();
403  }
404 
405  template<class F>
406  const F& DomainDecomp<F>::space(uint i) const {
407  conceptsAssert(i < this->domains_, Assertion());
408  return *spaces_[i];
409  }
410 
411  template<class F>
413  conceptsAssert(i < this->domains_, Assertion());
414  return *spaces_[i];
415  }
416 
417  template<class F>
419  conceptsAssert(i < this->domains_, Assertion());
420  if (!available())
422  return this->indicesI_[i];
423  }
424 
425  template<class F>
427  conceptsAssert(i < this->domains_, Assertion());
428  if (!available())
430  return this->indicesB_[i];
431  }
432 
433  template<class F>
434  template<class G, class H>
435  void DomainDecomp<F>::getIndices_(const G& prebuild, const H& cntr,
436  Set<IndexRange>& indices)
437  {
438  DEBUGL(DDSpaceGetIndices_D, "cntr = " << cntr);
439  HashMap<uint>::const_iterator i = attrToDomain_.find(cntr.attrib());
440  conceptsAssert(i != attrToDomain_.end(), Assertion());
441  // domain
442  uint d = i->second;
443  DEBUGL(DDSpaceGetIndices_D, "domain = " << d);
444 
445  Set<IndexRange> &indicesB = this->indicesB_[d],
446  &indicesI = this->indicesI_[d];
447 
448  uint dim = 0;
449  try {
450  while(1) {
451  // Index ranges of this cell of entities of dimension dim.
452  // Throws an exception if dimension is to high and leaves the
453  // while loop.
454  const Set<IndexRange> idx = prebuild.indices(dim, cntr, spcNo_);
455  if (!idx.empty()) {
457  cntr.key() << " - dim = " << dim << ", idx = " << idx);
458  DEBUGL(DDSpaceGetIndices_D, "indices = " << indices);
459  // Indices, which occur first time or lie the interior this domain.
460  Set<IndexRange> recent = idx - (indices - indicesI);
461  // already occured indices
462  Set<IndexRange> occured = idx - recent;
464  "recent = " << recent << ", occured = " << occured);
465  if (!occured.empty()) {
466  // its on the boundary of this domain
467  indicesB = indicesB || occured;
468  DEBUGL(DDSpaceGetIndices_D, "indicesB = " << indicesB);
469  // Delete it from index set inside other domains, could be
470  // counted there
471  for(uint j = 0; j < this->domains_; ++j)
472  if (j != d) {
473  Set<IndexRange> occuredDomain = occured && this->indicesI_[j];
474  this->indicesI_[j] = this->indicesI_[j] - occuredDomain;
475  this->indicesB_[j] = this->indicesB_[j] || occuredDomain;
476  }
477  }
478  if (!recent.empty()) {
479  indicesI = indicesI || recent;
480  DEBUGL(DDSpaceGetIndices_D, "indicesI = " << indicesI);
481  }
482  indices = indices || idx;
483  // set difference with index ranges at boundary are inside domain
485  "indicesI_[" << d << "] = " << this->indicesI_[d]);
487  "indicesB_[" << d << "] = " << this->indicesB_[d]);
488  } // idx not empty
489  ++dim;
490  DEBUGL(DDSpaceGetIndices_D, "dim = " << dim);
491  } // while (1)
492  }
493  catch (concepts::MissingFeature& e) {}
494 
495  DEBUGL(DDSpaceGetIndices_D, "done for " << cntr);
496  const H* chld = 0;
497  for(uint j = 0; (chld = cntr.child(j)) != 0; ++j)
498  getIndices_(prebuild, *chld, indices);
499  }
500 
501 } // namespace concepts
502 
503 #endif
virtual std::ostream & info(std::ostream &os) const
Returns all index sets for dof at boundary of each domain.
Definition: domainDecomp.hh:60
#define DDSpaceDestr_D
Definition: domainDecomp.hh:21
const uint domains() const
Returns number of domains/spaces.
Definition: domainDecomp.hh:37
An abstract class for an element of a space.
Definition: exceptions.hh:15
virtual std::ostream & info(std::ostream &os) const
Returns all index sets for dof at boundary of each domain.
void rebuild()
Rebuilds the spaces.
virtual uint dim() const
Returns the dimension of the space.
uint attrib() const
Returns the attribute.
Definition: connector.hh:38
#define conceptsException(exc)
Prepares an exception for throwing.
Definition: exceptions.hh:344
#define DDSpaceConstr_D
Definition: domainDecomp.hh:20
Abstract class for a space.
uint domains_
Number of domains/spaces.
Definition: domainDecomp.hh:54
Sequence< Set< IndexRange > > indicesI_
Index sets of dof inside and at the boundary for each domain/space.
Definition: domainDecomp.hh:56
Element< F > type
Definition: space.hh:46
Joiner class with multiple successors, i.e.
DDSpace(uint domains=0)
Constructor.
Definition: domainDecomp.hh:34
#define conceptsAssert(cond, exc)
Assert that a certain condition is fulfilled.
Definition: exceptions.hh:394
virtual const TMatrixBase< F > & T() const =0
Returns the T matrix of the element.
Array< uint > spcBuild_
Array of build number of the spaces at last call of rebuild()
#define DDSpaceGetIndices_D
Definition: domainDecomp.hh:23
bool available() const
Returns true, if space is available, false, if it has to be rebuilt.
virtual const Space< F > & space(uint i) const =0
Returns space belonging to i th domain.
#define DEBUGL(doit, msg)
HashMap< uint > attrToDomain_
Mapping from attribute to domain number.
virtual const Set< IndexRange > indicesI(uint i) const =0
Returns index set for dof inside the i th domain.
virtual ~DDSpace()
Definition: domainDecomp.hh:35
Class for holding an offset of global indices of space.
Definition: space.hh:386
concepts::Element< typename F::t_type > Element
Element type.
Definition: domainDecomp.hh:78
uint nelm_
Number of elements in all spaces.
Exception class for assertions.
Definition: exceptions.hh:258
Sequence< Set< IndexRange > > indicesB_
Definition: domainDecomp.hh:56
void getIndices_(const G &prebuild, const H &cntr, Set< IndexRange > &indices)
virtual Scan * scan() const
Returns a scanner to iterate over the elements of the space.
An abstract class for scanning a mesh (a set of cells) or a space (a set of elements).
virtual uint & lastIdx()
Returns last global index of the space.
Sequence with operations, output operator, and method of the particular element types.
Definition: sequence.hh:39
concepts::Scan< Element > Scan
Definition: domainDecomp.hh:79
virtual const Set< IndexRange > indicesB(uint i) const =0
Returns all index sets for dof inside each domain.
concepts::Joiner< Element *, 1 > * elm_
Array of the elements of all domains.
Indicates that the space on which a function was called was not yet correctly built.
Definition: space.hh:36
void resize(const uint sz)
Resizes the array.
Definition: array.hh:281
Sequence< CellConditions > cc_
Cell conditions for the spaces.
Exception class to express a missing feature.
Definition: exceptions.hh:206
virtual uint nelm() const
Returns the number of elements in the space.
static void destructor(Joiner< T, nlnk > *&j, bool values=true)
Static function to delete the list/tree.
Sequence< F * > spaces_
Spaces belonging to domains.
virtual uint offset() const
Returns the offset, returns 0 if space is not a subspace or first one.
void zeros()
Fills the memory with zeros.
Definition: array.hh:128
#define conceptsAssert3(cond, exc, msg)
Assert that a certain condition is fulfilled.
Definition: exceptions.hh:442
virtual const F & space(uint i) const
Returns space belonging to i th domain.
#define DDSpaceRebuild_D
Definition: domainDecomp.hh:22
DomainDecomp(G &prebuild, Sequence< Set< uint > > domains, BoundaryConditions *bc=0, CellConditions *cc=0, uint spcNo=0, uint *offset=0)
Constructor.
Domain decomposition space.
Definition: domainDecomp.hh:72
virtual const Set< IndexRange > indicesI(uint i) const
Returns index set for dof inside the i th domain.
uint spcNo_
Number for the global indices of the domains, for distinguishing between global indices on same topol...
Attributes for elements of the topology.
Definition: connector.hh:22
Basic namespace for Concepts-2.
Definition: pml_formula.h:16
Scanner for a list of pointers.
virtual const Set< IndexRange > indicesB(uint i) const
Returns index set for dof at the boundary the i th domain.
Page URL: http://wiki.math.ethz.ch/bin/view/Concepts/WebHome
21 August 2020
© 2020 Eidgenössische Technische Hochschule Zürich