ug4
periodic_boundary_manager_impl.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2015: G-CSC, Goethe University Frankfurt
3  * Author: Martin Scherer
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef PERIODIC_IDENTIFIER_IMPL_HPP_
34 #define PERIODIC_IDENTIFIER_IMPL_HPP_
35 
36 // include declarations
40 #include "common/assert.h"
41 #include "common/error.h"
42 #include "pcl/pcl_base.h"
43 
44 #include <boost/mpl/map.hpp>
45 #include <boost/mpl/at.hpp>
46 
47 #include <algorithm>
48 
49 namespace ug {
50 
51 template <class TAAPos>
52 template <class TElem>
53 bool ParallelShiftIdentifier<TAAPos>::match_impl(TElem* e1, TElem* e2) const {
54  if (e1 == e2)
55  return false;
56 
57  AttachmentType c1 = CalculateCenter(e1, m_aaPos),
58  c2 = CalculateCenter(e2, m_aaPos), diff, error;
59  bool result = false;
60 
61  VecSubtract(diff, c1, c2);
62  VecSubtract(error, diff, m_shift);
63  number len = VecLengthSq(error);
64  if (std::abs(len) < 10E-8)
65  result = true;
66  else // check for opposite shift
67  {
68  VecSubtract(error, diff, m_shift_opposite);
69  len = VecLengthSq(error);
70  if (std::abs(len) < 10E-8)
71  result = true;
72  }
73 
74  return result;
75 }
76 
77 template <class TElem>
78 void PeriodicBoundaryManager::identify(TElem* e1, TElem* e2,
79  IIdentifier& ident) {
80  typedef typename
82 
83  // determine masters
84  TElem* m1 = master(e1);
85  TElem* m2 = master(e2);
86 
87  if (m1 || m2) {
88  // if m1 == m2, there's nothing to do
89  if (m1 != m2) {
90  if (!m1) { // m2 is master
91  make_slave(group(m2), e1);
92  } else if (!m2) { // m1 is master
93  make_slave(group(m1), e2);
94  } else if (m1 && m2) { // both are distinct masters
95  merge_groups(group(m1), group(m2));
96  } else {
97  UG_THROW("should never get here")
98  }
99  }
100  } else {
101  // create new group with e1 as master
102  Group<TElem>* g = new Group<TElem>(e1);
103  // set group of master
104  set_group(g, e1);
105  // make e2 slave
106  make_slave(g, e2);
107  }
108 
109  // while elements have sides, recursively identify sub type elements
110  if (TElem::HAS_SIDES) {
111  container sides1, sides2;
112  // collect sides and identify them
113  m_pGrid->associated_elements<TElem>(sides1, e1);
114  m_pGrid->associated_elements<TElem>(sides2, e2);
115  for (size_t i = 0; i < sides1.size(); ++i) {
116  for (size_t j = 0; j < sides2.size(); ++j) {
117  if(ident.match(sides1[i], sides2[j])) {
118  identify(sides1[i], sides2[j], ident);
119  }
120  }
121  }
122  }
123 }
124 
125 // is considered periodic if it is a master or a slave
126 template <class TElem>
128  if(e)
129  return get_periodic_status_accessor<TElem>()[e] != P_NOT_PERIODIC;
130  else
131  UG_THROW("null pointer is never periodic.");
132 }
133 
134 // gets master of e, may be null
135 template <class TElem>
136 TElem* PeriodicBoundaryManager::master(TElem* e) const {
137  if (group(e)) {
138  return group(e)->m_master;
139  }
140  return NULL;
141 }
142 
143 // gets slaves of e
144 template <class TElem>
147  if (group(e)) {
148  return &group(e)->get_slaves();
149  }
150  return NULL;
151 }
152 
153 template <class TElem>
155  typedef typename ElementStorage<TElem>::SectionContainer::iterator Iterator;
156  typedef typename Group<TElem>::SlaveIterator SlaveIter;
157 
158  for (Iterator elem = m_pGrid->begin<TElem>(); elem != m_pGrid->end<TElem>();
159  ++elem) {
160  // log masters and their slaves
161  if (!(master(*elem) == *elem))
162  continue;
163 
164  Group<TElem>* g = group(*elem);
165  UG_ASSERT(g, "group not valid")
166  UG_LOG("group of " << (*elem)->reference_object_id() << "\tlevel: " <<
167  m_pGrid->get_level(*elem) << "\tmaster: " <<
168  GetGridObjectCenter(*m_pGrid, g->m_master) << "\tslaves: ");
169  for (SlaveIter slave = g->get_slaves().begin();
170  slave != g->get_slaves().end(); ++slave) {
171  TElem* e = *slave;
172  UG_LOG(GetGridObjectCenter(*m_pGrid, e) << ", ")
174  "wrong level in group")
175  }
176  UG_LOG(std::endl)
177  }
178 }
179 
186 template <class TElem>
187 void PeriodicBoundaryManager::replace_parent(TElem* e, TElem* pParent) {
188 
189  if (is_master(pParent)) {
190  // if parent is master, set newly created item as new master
191  Group<TElem>* g = group(pParent);
192  g->m_master = e;
193  set_group(g, e);
194  } else if(is_slave(pParent)) { // slave
195  // iterate over parent-groups slave list and replace pointer to parent
196  typename Group<TElem>::SlaveContainer* slaveCon = slaves(pParent);
197  for(typename Group<TElem>::SlaveContainer::iterator i = slaveCon->begin();
198  i != slaveCon->end(); ++i)
199  {
200  if(*i == pParent)
201  *i = e;
202  }
203  set_group(group(pParent), e);
204  }
205 }
206 
207 template <class TElem, class TParent>
208 void PeriodicBoundaryManager::handle_creation(TElem* e, TParent* pParent) {
209 
210  typedef typename Group<TParent>::SlaveContainer ParentSlaveContainer;
211 
212  if (!pParent)
213  return;
214 
215  if (!is_periodic(pParent))
216  return;
217 
219  "PeriodicBoundaryManager has to operate on a grid. No grid assigned.");
220  MultiGrid& mg = *m_pGrid;
221 
222  mg.begin_marking();
223  if(TElem::BASE_OBJECT_ID != VERTEX){
225  mg.associated_elements(vrts, e);
226  for(size_t i = 0; i < vrts.size(); ++i){
227  Group<Vertex>* grp = group(vrts[i]);
228  if(!grp)
229  continue;
230  mg.mark(grp->m_master);
231  mg.mark(grp->get_slaves().begin(), grp->get_slaves().end());
232  }
233  }
234 
235  if (is_master<TParent>(pParent)) {
236  // create new group for e, with e as master
237  Group<TElem>* newGroup = new Group<TElem>(e);
238  UG_ASSERT(group(e) == NULL, "element already has a group.")
239  set_group(newGroup, e);
240 
241  // iterate over slaves of parent
242  ParentSlaveContainer* parentSlaves = slaves(pParent);
243  for (typename ParentSlaveContainer::iterator i_slave =
244  parentSlaves->begin(); i_slave != parentSlaves->end();
245  ++i_slave) {
246  TParent* parentSlave = *i_slave;
247  UG_ASSERT(parentSlave, "parent slave not valid")
248 
249  // iterate over all children of parentSlave and make them slaves of e
250  // only matching children of type TElem are considered.
251  // note that not all children already have to exist at this point.
252  // children which are created later on are handled by the 'else' section.
253  for (size_t i_child = 0;
254  i_child < mg.num_children<TElem>(parentSlave); ++i_child) {
255  TElem* c = mg.get_child<TElem>(parentSlave, i_child);
256  UG_ASSERT(!(e->base_object_id() == VERTEX)
257  || (mg.num_children<TElem>(parentSlave) == 1),
258  "At most one 1 vertex-child is currently allowed");
259  // We use a special case for vertices here, since the position
260  // attachment has not yet been set (this is currently done after
261  // all observers have been informed about the creation of the new
262  // vertex). Note that this is no problem for edges or faces, since
263  // associated vertices have been properly initialized at that time.
264  if((e->base_object_id() == VERTEX)) {
265  make_slave(newGroup, c);
266  } else {
268  mg.associated_elements(vrts, c);
269  bool allMarked = true;
270  for(size_t i = 0; i < vrts.size(); ++i){
271  if(!mg.is_marked(vrts[i])){
272  allMarked = false;
273  break;
274  }
275  }
276 
277  if(allMarked)
278  make_slave(newGroup, c);
279  }
280  }
281  }
282  } else {
283  // find the associated master of e by checking for a matching child
284  // in the set of children of the parents master.
285  // If no appropriate child already exists at this point, no master can
286  // be found. We simply leave the new element as it is, since it will
287  // be found as a slave when the associated master will be created later
288  // on (the 'if(is_master...)' case applies then.
289 
290  // attention: parentGroup may be null
291  Group<TParent>* parentGroup = group<TParent>(pParent);
292 
293  if (parentGroup == NULL) {
294  get_periodic_status_accessor<TElem>()[e] = P_SLAVE_MASTER_UNKNOWN;
295  return;
296  }
297 
298  TParent* parentMaster = parentGroup->m_master;
299  bool master_found = false;
300  for (size_t i_child = 0; i_child < mg.num_children<TElem>(parentMaster);
301  ++i_child) {
302  TElem* c = mg.get_child<TElem>(parentMaster, i_child);
303  UG_ASSERT(!(e->base_object_id() == VERTEX)
304  || (mg.num_children<TElem>(parentMaster) == 1),
305  "At most one 1 vertex-child is currently allowed");
306  // We use a special case for vertices here, since the position
307  // attachment has not yet been set (this is currently done after
308  // all observers have been informed about the creation of the new
309  // vertex). Note that this is no problem for edges or faces, since
310  // associated vertices have been properly initialized at that time.
311  if((e->base_object_id() == VERTEX)) {
312  make_slave(group(c), e);
313  master_found = true;
314  break;
315  } else {
317  mg.associated_elements(vrts, c);
318  bool allMarked = true;
319  for(size_t i = 0; i < vrts.size(); ++i){
320  if(!mg.is_marked(vrts[i])){
321  allMarked = false;
322  break;
323  }
324  }
325 
326  if(allMarked){
327  make_slave(group(c), e);
328  master_found = true;
329  break;
330  }
331  }
332  }
333 
334  // wait until a master for e will be known
335  if (!master_found) {
336  get_periodic_status_accessor<TElem>()[e] = P_SLAVE_MASTER_UNKNOWN;
337  }
338  }
339 
340  mg.end_marking();
341 }
342 
343 template <class TElem>
345  GridObject* pParent, bool replacesParent) {
346  // we can only identify periodic elements, which have a periodic parent
347  if(!pParent)
348  return;
349 
350  if(replacesParent){
351  replace_parent(e, static_cast<TElem*>(pParent));
352  }
353  else{
354  switch (pParent->base_object_id()) {
355  case VERTEX:
356  handle_creation(e, static_cast<Vertex*>(pParent));
357  break;
358  case EDGE:
359  handle_creation(e, static_cast<Edge*>(pParent));
360  break;
361  case FACE:
362  handle_creation(e, static_cast<Face*>(pParent));
363  break;
364  // ignore volumes, as these are not meant to be periodic
365  case VOLUME:
366  break;
367  default:
368  UG_THROW("no handling for parent type: " << pParent->base_object_id())
369  }
370  }
371 }
372 
374 template <class TElem>
375 void PeriodicBoundaryManager::handle_deletion(TElem* e, TElem* replacedBy) {
376  if((!is_periodic(e)) || replacedBy)
377  return;
378 
379  if (is_master(e)) {
380  // delete a master completely...
381  if (replacedBy) {
382  UG_ASSERT(!group(replacedBy),
383  "replacing element is already in group")
384  make_master(group(e), replacedBy);
385  } else {
386  remove_group(group(e));
387  }
388  } else { // slave
389  UG_ASSERT(is_slave(e), "e should be a slave")
390  if(!remove_slave(e))
391  UG_THROW("old slave not removed.")
392  }
393 }
394 
395 template <class TElem>
397  UG_ASSERT(g, "invalid group")
398  UG_ASSERT(slave, "invalid slave")
399  UG_ASSERT(group(slave) != g, "trying to add a duplicate slave!")
401  "level of slave and group mismatch")
402 
403  // if slave is already engrouped, remove it first
404  if(group(slave)) {
405  UG_LOG("slave already engrouped. removing it from former group\n")
406  if(!remove_slave(slave)) {
407  UG_THROW("slave could not be removed")
408  }
409  }
410 
411  // add slave to group and set group attachment/status
412  g->add_slave(slave);
413  set_group(g, slave);
414 }
415 
416 template <class TElem>
418  // group has a master, reset its group
419  if(g->m_master) {
420  set_group<TElem>(NULL, g->m_master);
421  }
422  g->m_master = new_master;
423 }
424 
425 template <class TElem>
427  if (slaves(e)) {
428  typename Group<TElem>::SlaveContainer& s = *slaves(e);
429  typename Group<TElem>::SlaveIterator pos = std::find(s.begin(), s.end(), e);
430  if (pos != s.end()) {
431 // s.erase(pos);
432 // set_group<TElem>(NULL, e);
433 
434  // todo this is the only slave left, remove whole group?!
435  if(s.size() == 1) {
436  UG_LOGN("delete last slave, remove_group")
437  remove_group(group(e));
438  }
439  // todo what if e was the last slave of of group?
440 // if(s.empty()) {
441 // UG_THROW("empty group leftover....")
442 // }
443  return true;
444  }
445  }
446  return false;
447 }
448 
449 template <class TElem>
451  UG_ASSERT(g, "should remove invalid group")
452 
453  // reset group pointers of all group members to NULL
454  set_group<TElem>(NULL, g->m_master);
455  typename Group<TElem>::SlaveContainer& s = g->get_slaves();
456  typename Group<TElem>::SlaveIterator iter;
457  for (iter = s.begin(); iter != s.end(); ++iter) {
458  set_group<TElem>(NULL, *iter);
459  }
460 
461  delete g;
462 }
463 
467 template <class TElem>
469  UG_ASSERT(g0 && g1, "groups not valid")
470  UG_ASSERT(g0 != g1, "groups are equal")
471 
472  typedef typename Group<TElem>::SlaveContainer SlaveContainer;
473  typedef typename Group<TElem>::SlaveIterator SlaveIterator;
474 
475  SlaveContainer& slaves_g1 = g1->get_slaves();
476 
477  // insert slaves of g1 at the end of slaves of g0
478  for (SlaveIterator iter = slaves_g1.begin(); iter != slaves_g1.end();
479  ++iter) {
480  TElem* e = *iter;
481  UG_ASSERT(e, "slave not valid")
482  UG_ASSERT(e != g0->m_master, "slave of g1 is master of g0!")
483  // we do not use make_slave() here, because g1 will be deleted at the end
484  g0->add_slave(e);
485  set_group(g0, e);
486  }
487 
488  // make old master a slave of group g1
489  // we do not use make_slave() here, because g1 will be deleted at the end
490  g0->add_slave(g1->m_master);
491  set_group(g0, g1->m_master);
492 
493  // remove old group
494  delete g1;
495 }
496 
497 template <class TElem>
498 bool PeriodicBoundaryManager::is_slave(TElem* e) const {
499  PeriodicStatus p = get_periodic_status_accessor<TElem>()[e];
500  return (p == P_SLAVE || p == P_SLAVE_MASTER_UNKNOWN);
501 }
502 
503 template <class TElem>
505  return get_periodic_status_accessor<TElem>()[e] == P_MASTER;
506 }
507 
508 template <class TElem>
510  TElem* e) const {
511  UG_ASSERT(e, "element not valid.")
512  return get_group_accessor<TElem>()[e];
513 }
514 
515 template <class TElem>
517  UG_ASSERT(e, "element not valid for attachment access.")
518  // set group pointer of element e
519  get_group_accessor<TElem>()[e] = g;
520 
521  // set periodic status
522  if (g == NULL) {
523  get_periodic_status_accessor<TElem>()[e] = P_NOT_PERIODIC;
524  } else {
525  if (g->m_master == e)
526  get_periodic_status_accessor<TElem>()[e] = P_MASTER;
527  else
528  get_periodic_status_accessor<TElem>()[e] = P_SLAVE;
529  }
530 }
531 
532 template <class TElem, class TIterator>
534  TIterator begin,
535  TIterator end,
536  typename Group<TElem>::unique_pairs& s,
537  ISubsetHandler* sh) {
538 
539  typedef typename Group<TElem>::SlaveContainer Container;
540  typedef typename Group<TElem>::SlaveIterator SlaveIter;
541  typedef typename ElementStorage<TElem>::SectionContainer::const_iterator SecContainerIter;
542 
543  for (SecContainerIter iter = begin; iter != end; ++iter) {
544  TElem* e = *iter;
545  if(! e)
546  continue;
547  if(!is_periodic(e)) {
548  // lookup subset name of element
549  const char* sh_name = "";
550  if(sh) {
551  int element_si = sh->get_subset_index(e);
552  sh_name = sh->get_subset_name(element_si);
553  }
554  UG_THROW("Element in subset '" << sh_name
555  << "' is not periodic after identification: "
556  << GetGridObjectCenter(*get_grid(), e)
557  << "\nCheck your geometry for symmetry!\n")
558  }
559 
560  if (master(e) == e) {
561  Container* _slaves = slaves(e);
562  if(! _slaves)
563  UG_THROW("masters slave storage is not valid.")
564 
565  if(_slaves->empty())
566  UG_THROW("master has no slaves")
567 
568  for (SlaveIter i = _slaves->begin(); i != _slaves->end(); ++i) {
569  TElem* slave = *i;
570  typename Group<TElem>::master_slave_pair p = std::make_pair(e, slave);
571  bool inserted = (s.insert(p)).second;
572  if(! inserted)
573  UG_THROW("master/slave pair already exists.");
574  }
575  }
576  }
577 }
578 
579 template <class TDomain>
580 void IdentifySubsets(TDomain& dom, const char* sName1, const char* sName2) {
581  // get subset handler from domain
582  typedef typename TDomain::subset_handler_type subset_handler_type;
583 
584  subset_handler_type& sh = *dom.subset_handler();
585 
586  int si1 = sh.get_subset_index(sName1);
587  int si2 = sh.get_subset_index(sName2);
588 
589 #ifdef UG_PARALLEL
590  //if(pcl::NumProcs() > 1)
591  // UG_THROW("sorry, in real parallel environment periodic bnds are not impled yet.");
592 #endif
593 
594  if (si1 == -1)
595  UG_THROW("IdentifySubsets: given subset name " << sName1 << " does not exist");
596  if (si2 == -1)
597  UG_THROW("IdentifySubsets: given subset name " << sName2 << " does not exist");
598 
599  IdentifySubsets(dom, si1, si2);
600 }
601 
603 template <class TDomain>
604 void IdentifySubsets(TDomain& dom, int sInd1, int sInd2) {
605 
606 #ifdef UG_PARALLEL
607  //if(pcl::NumProcs() > 1)
608  // UG_THROW("sorry, in real parallel environment periodic bnds are not impled yet.");
609 #endif
610 
611  if (sInd1 == -1 || sInd2 == -1) {
612  UG_THROW("IdentifySubsets: at least one invalid subset given!")
613  }
614 
615  if(sInd1 == sInd2) {
616  UG_THROW("IdentifySubsets: can not identify two identical subsets!")
617  }
618 
619  // ensure grid has support for periodic boundaries
620  if (!dom.grid()->has_periodic_boundaries()) {
621  dom.grid()->set_periodic_boundaries(true);
622  }
623 
624  PeriodicBoundaryManager& pbm = *dom.grid()->periodic_boundary_manager();
625 
626  typedef typename TDomain::position_type position_type;
627  typedef typename TDomain::position_accessor_type position_accessor_type;
628 
629  // get subset handler from domain
630  typedef typename TDomain::subset_handler_type subset_handler_type;
631 
632  subset_handler_type& sh = *dom.subset_handler();
633 
634  // get aaPos from domain
635  position_accessor_type& aaPos = dom.position_accessor();
636 
637  // create parallel shift identifier to match subset elements
639 
640  // shift vector between subsets
641  position_type shift;
642 
643  // collect all geometric objects (even for all levels in case of multi grid)
644  GridObjectCollection goc1 = sh.get_grid_objects_in_subset(sInd1);
645  GridObjectCollection goc2 = sh.get_grid_objects_in_subset(sInd2);
646 
647  if(goc1.num<Vertex>() != goc2.num<Vertex>()) {
648  UG_THROW("IdentifySubsets: Given subsets have different number of vertices."
649  "\nnum# in " << sh.get_subset_name(sInd1) << ": " << goc1.num<Vertex>() <<
650  "\nnum# in " << sh.get_subset_name(sInd2) << ": " << goc2.num<Vertex>())
651  }
652 
653  if(goc1.num<Edge>() != goc2.num<Edge>()) {
654  UG_THROW("IdentifySubsets: Given subsets have different number of edges."
655  "\nnum# in " << sh.get_subset_name(sInd1) << ": " << goc1.num<Edge>() <<
656  "\nnum# in " << sh.get_subset_name(sInd2) << ": " << goc2.num<Edge>())
657  }
658 
659  if(goc1.num<Face>() != goc2.num<Face>()) {
660  UG_THROW("IdentifySubsets: Given subsets have different number of faces."
661  "\nnum# in " << sh.get_subset_name(sInd1) << ": " << goc1.num<Face>() <<
662  "\nnum# in " << sh.get_subset_name(sInd2) << ": " << goc2.num<Face>())
663  }
664 
665  // map start type of recursion dependent to TDomain
666  // in 3d start with faces, in 2d with edges, in 1d with vertices
667  // namespace mpl = boost::mpl;
668  // typedef mpl::map<mpl::pair<Domain1d, Vertex>,
669  // mpl::pair<Domain2d, Edge>,
670  // mpl::pair<Domain3d, Face> > m;
671 
672  // typedef typename mpl::at<m, TDomain>::type TElem;
673  typedef typename grid_dim_traits<TDomain::dim>::side_type TElem;
674  typedef typename ElementStorage<TElem>::SectionContainer::iterator gocIter;
675 
676  // calculate shift vector for top level
677  position_type c1 = CalculateCenter(goc1.begin<TElem>(0), goc1.end<TElem>(0),
678  aaPos);
679  position_type c2 = CalculateCenter(goc2.begin<TElem>(0), goc2.end<TElem>(0),
680  aaPos);
681 
682  VecSubtract(shift, c1, c2);
683  ident.set_shift(shift);
684 
685  // for each level of multi grid. In case of simple grid only one iteration
686  for (size_t lvl = 0; lvl < goc1.num_levels(); lvl++) {
687  // identify corresponding elements for second subset. A element is considered
688  // to have symmetric element in second subset if there exists a shift vector between them.
689  // todo use kd-tree for fast lookup of shifted elements
690  for (gocIter iter1 = goc1.begin<TElem>(lvl);
691  iter1 != goc1.end<TElem>(lvl); ++iter1)
692  for (gocIter iter2 = goc2.begin<TElem>(lvl);
693  iter2 != goc2.end<TElem>(lvl); ++iter2) {
694  if(ident.match(*iter1, *iter2)) {
695  pbm.identify(*iter1, *iter2, ident);
696  }
697  }
698  }
699 
700  // ensure periodic identification has been performed correctly
701  pbm.check_periodicity(goc1, goc2, &sh);
702 }
703 
704 } // end namespace ug
705 
706 #endif /* PERIODIC_IDENTIFIER_IMPL_HPP_ */
parameterString p
parameterString s
A special iterator which allows to iterate over elements in a AttachedElementList.
Definition: attached_list.h:52
A special iterator which allows to iterate over elements in a AttachedElementList.
Definition: attached_list.h:107
Base-class for edges.
Definition: grid_base_objects.h:397
Faces are 2-dimensional objects.
Definition: grid_base_objects.h:510
void end_marking()
ends a marking sequence. Call this method when you're done with marking.
Definition: grid.cpp:1285
bool is_marked(GridObject *obj) const
returns true if the object is marked, false if not.
Definition: grid_impl.hpp:843
void mark(GridObject *obj)
marks the object. Calls are only valid between calls to Grid::begin_marking and Grid::end_marking.
Definition: grid_impl.hpp:773
void begin_marking()
begin marking.
Definition: grid.cpp:1262
void associated_elements(traits< Vertex >::secure_container &elemsOut, TElem *e)
Puts all elements of type TAss which are contained in 'e' or which contain 'e' into elemsOut.
Definition: grid_impl.hpp:466
a helper class that holds a collection of possibly unconnected geometric-objects.
Definition: grid_object_collection.h:96
geometry_traits< TGeomObj >::iterator begin(size_t level=0)
Definition: grid_object_collection_impl.hpp:95
geometry_traits< TGeomObj >::iterator end(size_t level=0)
Definition: grid_object_collection_impl.hpp:106
size_t num() const
Definition: grid_object_collection_impl.hpp:130
size_t num_levels() const
returns the number of levels
Definition: grid_object_collection.h:128
The base class for all geometric objects, such as vertices, edges, faces, volumes,...
Definition: grid_base_objects.h:157
virtual int base_object_id() const =0
Interface to match periodic geometric elements.
Definition: periodic_boundary_manager.h:48
virtual bool match(Vertex *, Vertex *)=0
Definition: subset_handler_interface.h:223
const char * get_subset_name(int subsetIndex) const
returns the name of a subset
Definition: subset_handler_interface.cpp:438
int get_subset_index(GridObject *elem) const
Definition: subset_handler_interface.cpp:560
Definition: multi_grid.h:72
int get_level(TElem *elem) const
Definition: multi_grid.h:206
TChild * get_child(TElem *elem, size_t ind) const
returns the i-th child of the given child-type
Definition: multi_grid.h:268
geometry_traits< TElem >::iterator end(int level)
Definition: multi_grid.h:168
geometry_traits< TElem >::iterator begin(int level)
Definition: multi_grid.h:158
size_t num_children(TElem *elem) const
returns the number of children of the given child-type
Definition: multi_grid.h:225
This class matches geometric elements which are parallel translated.
Definition: periodic_boundary_manager.h:64
TPosAA::ValueType AttachmentType
Definition: periodic_boundary_manager.h:71
void set_shift(AttachmentType &shift)
Definition: periodic_boundary_manager.h:73
virtual bool match(Vertex *v1, Vertex *v2)
Definition: periodic_boundary_manager.h:66
bool match_impl(TElem *, TElem *) const
Definition: periodic_boundary_manager_impl.hpp:53
Definition: periodic_boundary_manager.h:107
TElem * m_master
Definition: periodic_boundary_manager.h:123
std::set< master_slave_pair > unique_pairs
Definition: periodic_boundary_manager.h:113
Container & get_slaves()
Definition: periodic_boundary_manager.h:122
Container SlaveContainer
Definition: periodic_boundary_manager.h:109
Container::iterator SlaveIterator
Definition: periodic_boundary_manager.h:110
std::pair< TElem *, TElem * > master_slave_pair
Definition: periodic_boundary_manager.h:112
void add_slave(TElem *e)
Definition: periodic_boundary_manager.h:117
Definition: periodic_boundary_manager.h:99
void handle_creation_cast_wrapper(TElem *e, GridObject *parent, bool replacesParent)
casts parent pointer to exact type before calling handle_creation
Definition: periodic_boundary_manager_impl.hpp:344
void identify(TElem *e1, TElem *e2, IIdentifier &i)
Definition: periodic_boundary_manager_impl.hpp:78
bool is_master(TElem *) const
Definition: periodic_boundary_manager_impl.hpp:504
void check_elements_periodicity(TIterator begin, TIterator end, typename Group< TElem >::unique_pairs &s, ISubsetHandler *sh)
Definition: periodic_boundary_manager_impl.hpp:533
void remove_group(Group< TElem > *g)
Definition: periodic_boundary_manager_impl.hpp:450
bool is_periodic(TElem *e) const
Definition: periodic_boundary_manager_impl.hpp:127
void make_master(Group< TElem > *g, TElem *e)
Definition: periodic_boundary_manager_impl.hpp:417
Group< TElem >::SlaveContainer * slaves(TElem *e) const
Definition: periodic_boundary_manager_impl.hpp:146
void handle_creation(TElem *e, TParent *pParent)
handles creation of element type
Definition: periodic_boundary_manager_impl.hpp:208
void merge_groups(Group< TElem > *g0, Group< TElem > *g1)
Definition: periodic_boundary_manager_impl.hpp:468
void set_group(Group< TElem > *g, TElem *e)
Definition: periodic_boundary_manager_impl.hpp:516
Group< TElem > * group(TElem *e) const
Definition: periodic_boundary_manager_impl.hpp:509
Grid * get_grid() const
Definition: periodic_boundary_manager.cpp:96
TElem * master(TElem *e) const
Definition: periodic_boundary_manager_impl.hpp:136
bool check_periodicity(const GridObjectCollection &goc1, const GridObjectCollection &goc2, ISubsetHandler *sh=NULL)
checks that all elements of given gocs are periodic (called after identification)
Definition: periodic_boundary_manager.cpp:257
MultiGrid * m_pGrid
grid instance we operate on
Definition: periodic_boundary_manager.h:208
bool is_slave(TElem *) const
Definition: periodic_boundary_manager_impl.hpp:498
PeriodicStatus
Definition: periodic_boundary_manager.h:129
@ P_SLAVE
Definition: periodic_boundary_manager.h:130
@ P_NOT_PERIODIC
Definition: periodic_boundary_manager.h:130
@ P_MASTER
Definition: periodic_boundary_manager.h:130
@ P_SLAVE_MASTER_UNKNOWN
Definition: periodic_boundary_manager.h:130
bool remove_slave(TElem *slave)
Definition: periodic_boundary_manager_impl.hpp:426
void print_identification() const
Definition: periodic_boundary_manager_impl.hpp:154
void make_slave(Group< TElem > *g, TElem *e)
make element e slave of group g
Definition: periodic_boundary_manager_impl.hpp:396
void handle_deletion(TElem *e, TElem *replacedBy)
handles deletion of element type
Definition: periodic_boundary_manager_impl.hpp:375
void replace_parent(TElem *e, TElem *pParent)
replaces all group occurrances of pParent by the specified elem
Definition: periodic_boundary_manager_impl.hpp:187
Container which holds an array of pointers.
Definition: pointer_const_array.h:84
size_t size() const
returns the size of the associated array.
Definition: pointer_const_array_impl.hpp:106
Base-class for all vertex-types.
Definition: grid_base_objects.h:231
vector3 GetGridObjectCenter(Grid &g, TElem *elem)
Returns the center of the given element (SLOW - for debugging only!)
Definition: debug_util_impl.hpp:47
#define UG_ASSERT(expr, msg)
Definition: assert.h:70
#define UG_THROW(msg)
Definition: error.h:57
#define UG_LOG(msg)
Definition: log.h:367
#define UG_LOGN(msg)
Definition: log.h:369
double number
Definition: types.h:124
void CalculateCenter(vector_t &centerOut, const vector_t *pointSet, size_t numPoints)
calculates the center of a point-set
Definition: math_util_impl.hpp:98
void VecSubtract(vector_t &vOut, const vector_t &v1, const vector_t &v2)
subtracts v2 from v1 and stores the result in a vOut
Definition: math_vector_functions_common_impl.hpp:226
vector_t::value_type VecLengthSq(const vector_t &v)
returns the squared length of v. Faster than VecLength.
Definition: math_vector_functions_common_impl.hpp:324
the ug namespace
IndexLayout::Interface::iterator find(IndexLayout::Interface &interface, size_t i)
Definition: parallel_index_layout.h:77
void IdentifySubsets(TDomain &dom, int sInd1, int sInd2)
identifies subset 1 with subset 2. If the grid of given domain has no periodic boundary manager attac...
Definition: periodic_boundary_manager_impl.hpp:604
@ VOLUME
Definition: grid_base_objects.h:63
@ VERTEX
Definition: grid_base_objects.h:60
@ EDGE
Definition: grid_base_objects.h:61
@ FACE
Definition: grid_base_objects.h:62
Definition: grid_dim_traits.h:53