|
ViennaGrid
1.0.1
|
00001 #ifndef VIENNAGRID_ELEMENT_ITERATORS_HPP 00002 #define VIENNAGRID_ELEMENT_ITERATORS_HPP 00003 00004 /* ======================================================================= 00005 Copyright (c) 2011-2012, Institute for Microelectronics, 00006 Institute for Analysis and Scientific Computing, 00007 TU Wien. 00008 00009 ----------------- 00010 ViennaGrid - The Vienna Grid Library 00011 ----------------- 00012 00013 Authors: Karl Rupp rupp@iue.tuwien.ac.at 00014 Josef Weinbub weinbub@iue.tuwien.ac.at 00015 00016 (A list of additional contributors can be found in the PDF manual) 00017 00018 License: MIT (X11), see file LICENSE in the base directory 00019 ======================================================================= */ 00020 00021 00022 #include <vector> 00023 #include <list> 00024 #include <map> 00025 #include <stack> 00026 #include <assert.h> 00027 00028 #include "viennagrid/forwards.h" 00029 #include "viennagrid/detail/domain_iterators.hpp" 00030 #include "viennagrid/detail/segment_iterators.hpp" 00031 00032 #include "viennadata/api.hpp" 00033 00038 namespace viennagrid 00039 { 00040 00041 template <typename ElementType> 00042 class const_on_element_iterator; 00043 00044 //RangeElement-Type prevents abuse, for example: 00045 //A vertex-on-facet-iterator is not equal to a vertex-on-cell-iterator! 00047 template <typename ElementType> 00048 class on_element_iterator : public std::iterator < std::forward_iterator_tag, ElementType > 00049 { 00050 public: 00051 on_element_iterator(ElementType **pp) : pp_(pp) {} 00052 00053 ElementType & operator*() const { return **pp_; } 00054 ElementType * operator->() const { return *pp_; } 00055 00056 on_element_iterator & operator++() { ++pp_; return *this; } 00057 on_element_iterator operator++(int) { on_element_iterator tmp = *this; ++*this; return tmp; } 00058 00059 bool operator==(const on_element_iterator& i) const { return pp_ == i.pp_; } 00060 bool operator==(const const_on_element_iterator<ElementType> & i) const { return pp_ == i.pp_; } 00061 00062 bool operator!=(const on_element_iterator& i) const { return pp_ != i.pp_; } 00063 bool operator!=(const const_on_element_iterator<ElementType> & i) const { return pp_ != i.pp_; } 00064 00065 //support for element-orientation-retrieval: 00066 // long operator-(const ocit & o2) const { return pp_ - o2.pp_; } 00067 00068 template <typename ElementType2> 00069 friend class const_on_element_iterator; //so that a const_on_element iterator can be initialized from an on_element_iterator 00070 00071 private: 00072 ElementType **pp_; 00073 }; 00074 00075 //const-version of above: 00077 template <typename ElementType> 00078 class const_on_element_iterator : public std::iterator < std::forward_iterator_tag, ElementType > 00079 { 00080 typedef ElementType * ElementPtr; 00081 00082 public: 00083 const_on_element_iterator(ElementPtr const * pp) : pp_(pp) {} 00084 const_on_element_iterator(on_element_iterator<ElementType> const & oei) : pp_(oei.pp_) {} 00085 00086 const ElementType & operator*() const { return **pp_; } 00087 const ElementType * operator->() const { return *pp_; } 00088 00089 const_on_element_iterator & operator++() { ++pp_; return *this; } 00090 const_on_element_iterator operator++(int) { const_on_element_iterator tmp = *this; ++*this; return tmp; } 00091 00092 bool operator==(const const_on_element_iterator& i) const { return pp_ == i.pp_; } 00093 bool operator==(const on_element_iterator<ElementType> & i) const { return pp_ == i.pp_; } 00094 00095 bool operator!=(const const_on_element_iterator& i) const { return pp_ != i.pp_; } 00096 bool operator!=(const on_element_iterator<ElementType> & i) const { return pp_ != i.pp_; } 00097 00098 template <typename ElementType2> 00099 friend class on_element_iterator; //so that a on_element iterator can be compared with a const_on_element_iterator 00100 00101 //support for element-orientation-retrieval: 00102 // long operator-(const ocit & o2) const { return pp_ - o2.pp_; } 00103 00104 private: 00105 ElementPtr const * pp_; 00106 }; 00107 00108 00110 00111 00112 //Check availability of iterators: 00114 template <typename ElementTag, 00115 long level, 00116 typename handling_tag = typename topology::bndcells<ElementTag, level>::handling_tag> 00117 struct ElementIteratorChecker 00118 { 00119 enum{ ReturnValue = topology::bndcells<ElementTag, level>::ERROR_ITERATOR_NOT_PROVIDED_AT_THIS_LEVEL }; 00120 }; 00121 00123 template <typename ElementTag, 00124 long level> 00125 struct ElementIteratorChecker< ElementTag, level, full_handling_tag> 00126 { 00127 enum{ ReturnValue = ElementTag::dim - level }; 00128 }; 00129 00130 00132 template <typename ElementType, 00133 long level> 00134 struct IteratorChecker 00135 { 00136 enum{ ReturnValue = ElementType::ERROR_ELEMENT_TYPE_INVALID }; 00137 }; 00138 00140 template <typename Config, 00141 typename ElementTag, 00142 long level> 00143 struct IteratorChecker< element_t<Config, ElementTag>, level> 00144 { 00145 enum{ ReturnValue = ElementIteratorChecker<ElementTag, level>::ReturnValue }; 00146 }; 00147 00148 00149 00150 // non-const: 00157 template <typename config_type, typename tag, long dim> 00158 class ncell_range < element_t<config_type, tag>, dim, false> 00159 { 00160 typedef element_t< config_type, 00161 typename topology::bndcells<tag, dim>::tag 00162 > element_type; 00163 00164 typedef element_t<config_type, tag> host_type; 00165 00166 //typedef std::vector< element_type > container_type; 00167 typedef typename result_of::element_container<host_type, dim, config_type::cell_tag::dim>::type container_type; 00168 00169 public: 00170 //typedef typename container_type::iterator iterator; 00171 typedef on_element_iterator< element_type > iterator; 00172 00173 ncell_range() : cont_(NULL) {}; 00174 00175 ncell_range(ncell_proxy<host_type> const & p) : cont_(p.get().container(dimension_tag<dim>())) {} 00176 00177 ncell_range(host_type & e) : cont_(e.container(dimension_tag<dim>())) {} 00178 00179 ncell_range & operator=(ncell_proxy<host_type> p) 00180 { 00181 cont_ = p.get().container(dimension_tag<dim>()); 00182 return *this; 00183 } 00184 00185 iterator begin() const 00186 { 00187 assert(cont_ != NULL); 00188 return iterator(&(cont_[0])); 00189 } 00190 00191 iterator end() const 00192 { 00193 assert(cont_ != NULL); 00194 return iterator(cont_ + topology::bndcells<tag, dim>::num); 00195 } 00196 00198 element_type & operator[](std::size_t index) const 00199 { 00200 assert(index < size()); 00201 return *(cont_[index]); 00202 } 00203 00205 std::size_t size() const { return topology::bndcells<tag, dim>::num; } 00206 00207 private: 00208 container_type * cont_; 00209 }; 00210 00211 00213 template <long dim, typename Config, typename ElementTag> 00214 typename result_of::ncell_range< element_t<Config, ElementTag>, dim>::type 00215 ncells(element_t<Config, ElementTag> & d) 00216 { 00217 return typename result_of::ncell_range< element_t<Config, ElementTag>, dim>::type(d); 00218 } 00219 00225 template <typename Config, typename ElementTag> 00226 ncell_proxy< element_t<Config, ElementTag> > 00227 ncells(element_t<Config, ElementTag> & d) 00228 { 00229 return ncell_proxy< element_t<Config, ElementTag> >(d); 00230 } 00231 00232 00233 // 00234 // const container: 00235 // 00242 template <typename config_type, typename tag, long dim> 00243 class const_ncell_range < element_t<config_type, tag>, dim, false> 00244 { 00245 typedef element_t< config_type, 00246 typename topology::bndcells<tag, dim>::tag 00247 > element_type; 00248 00249 typedef element_t<config_type, tag> host_type; 00250 00251 //typedef std::vector< element_type > container_type; 00252 typedef typename result_of::element_container<host_type, dim, config_type::cell_tag::dim>::type container_type; 00253 00254 public: 00255 //typedef typename container_type::iterator iterator; 00256 typedef const_on_element_iterator< element_type > iterator; 00257 const_ncell_range() : cont_(NULL) {}; 00258 00259 const_ncell_range(const_ncell_proxy<host_type> const & p) : cont_(p.get().container(dimension_tag<dim>())) {} 00260 00261 const_ncell_range(ncell_proxy<host_type> const & p) : cont_(p.get().container(dimension_tag<dim>())) {} 00262 00263 const_ncell_range(host_type const & e) : cont_(e.container(dimension_tag<dim>())) {} 00264 00265 00266 const_ncell_range & operator=(const_ncell_proxy<host_type> p) 00267 { 00268 cont_ = p.get().container(dimension_tag<dim>()); 00269 return *this; 00270 } 00271 00272 const_ncell_range & operator=(ncell_proxy<host_type> p) 00273 { 00274 cont_ = p.get().container(dimension_tag<dim>()); 00275 return *this; 00276 } 00277 00278 iterator begin() const 00279 { 00280 assert(cont_ != NULL); 00281 return iterator(cont_); 00282 } 00283 00284 iterator end() const 00285 { 00286 assert(cont_ != NULL); 00287 return iterator(cont_ + topology::bndcells<tag, dim>::num); 00288 } 00289 00290 element_type const & operator[](std::size_t index) const 00291 { 00292 assert(index < size()); 00293 return *(cont_[index]); 00294 } 00295 00296 std::size_t size() const { return topology::bndcells<tag, dim>::num; } 00297 00298 private: 00299 const container_type * cont_; 00300 }; 00301 00303 template <long dim, typename Config, typename ElementTag> 00304 typename result_of::const_ncell_range< element_t<Config, ElementTag>, dim>::type 00305 ncells(element_t<Config, ElementTag> const & d) 00306 { 00307 return typename result_of::const_ncell_range< element_t<Config, ElementTag>, dim>::type(d); 00308 } 00309 00315 template <typename Config, typename ElementTag> 00316 const_ncell_proxy< element_t<Config, ElementTag> > 00317 ncells(element_t<Config, ElementTag> const & d) 00318 { 00319 return const_ncell_proxy< element_t<Config, ElementTag> >(d); 00320 } 00321 00322 00323 00324 00325 00326 00328 00329 //helper meta function for selecting const/non-const containers: 00331 template <long dim_start, 00332 long dim_iter, 00333 typename RangeType, 00334 typename KeyType, 00335 typename EnclosingType> 00336 void init_coboundary(KeyType const & key, 00337 EnclosingType const & domain) 00338 { 00339 typedef typename EnclosingType::config_type Config; 00340 typedef typename result_of::ncell<Config, dim_start>::type LowerElementType; 00341 typedef typename result_of::ncell<Config, dim_iter>::type HigherElementType; 00342 00343 typedef typename result_of::const_ncell_range<EnclosingType, dim_iter>::type HigherElementRange; 00344 typedef typename result_of::iterator<HigherElementRange>::type HigherElementIterator; 00345 00346 typedef typename result_of::const_ncell_range<HigherElementType, dim_start>::type LowerOnHigherRange; 00347 typedef typename result_of::iterator<LowerOnHigherRange>::type LowerOnHigherIterator; 00348 00349 00350 HigherElementRange higher_container = ncells<dim_iter>(domain); 00351 for (HigherElementIterator hit = higher_container.begin(); 00352 hit != higher_container.end(); 00353 ++hit) 00354 { 00355 LowerOnHigherRange lower_container = ncells<dim_start>(*hit); 00356 for (LowerOnHigherIterator low = lower_container.begin(); 00357 low != lower_container.end(); 00358 ++low) 00359 { 00360 viennadata::access<KeyType, RangeType>(key)(*low).push_back(const_cast<HigherElementType *>(&(*hit))); 00361 } 00362 } 00363 } 00364 00365 // non-const: 00367 template <typename T, typename U> 00368 class cobnd_proxy 00369 { 00370 public: 00371 cobnd_proxy(T & t_, U & u_) : t(t_), u(u_) {} 00372 00373 T & first() const { return t; } 00374 U & second() const { return u; } 00375 00376 private: 00377 T & t; 00378 U & u; 00379 }; 00380 00382 template <long dim, typename Config, typename ElementTag> 00383 ncell_range < element_t<Config, ElementTag>, dim, true> 00384 ncells(element_t<Config, ElementTag> & e, domain_t<Config> & d) 00385 { 00386 return ncell_range < element_t<Config, ElementTag>, dim, true>(e, d); 00387 } 00388 00398 template <typename Config, typename ElementTag> 00399 cobnd_proxy< element_t<Config, ElementTag>, 00400 domain_t<Config> > 00401 ncells(element_t<Config, ElementTag> & e, domain_t<Config> & d) 00402 { 00403 return cobnd_proxy< element_t<Config, ElementTag>, 00404 domain_t<Config> >(e, d); 00405 } 00406 00407 00417 template <long dim, typename Config, typename ElementTag> 00418 ncell_range < element_t<Config, ElementTag>, dim, true> 00419 ncells(element_t<Config, ElementTag> & e, segment_t<Config> & seg) 00420 { 00421 return ncell_range < element_t<Config, ElementTag>, dim, true>(e, seg); 00422 } 00423 00424 00434 template <typename Config, typename ElementTag> 00435 cobnd_proxy< element_t<Config, ElementTag>, 00436 segment_t<Config> > 00437 ncells(element_t<Config, ElementTag> & e, segment_t<Config> & seg) 00438 { 00439 return cobnd_proxy< element_t<Config, ElementTag>, 00440 segment_t<Config> >(e, seg); 00441 } 00442 00443 00450 template <typename config_type, typename tag, 00451 long dim> 00452 class ncell_range < element_t<config_type, tag>, dim, true> 00453 { 00454 typedef element_t< config_type, 00455 typename topology::bndcells<typename config_type::cell_tag, 00456 dim>::tag 00457 > element_type; 00458 00459 typedef element_t<config_type, tag> host_type; 00460 typedef std::vector<element_type *> viennadata_container_type; 00461 typedef element_type * container_type; 00462 00463 public: 00464 //typedef typename container_type::iterator iterator; 00465 typedef on_element_iterator<element_type> iterator; 00466 00467 ncell_range() : cont_(NULL) {}; 00468 00469 template <typename EnclosingType> //either domain or segment 00470 ncell_range(cobnd_proxy<host_type, EnclosingType> const & p) 00471 { 00472 init(p.first(), p.second()); 00473 } 00474 00475 template <typename EnclosingType> //either domain or segment 00476 ncell_range(host_type const & e, 00477 EnclosingType const & d) 00478 { 00479 //std::cout << "Using non-const!" << std::endl; 00480 init(e, d); 00481 } 00482 00483 template <typename EnclosingType> //either domain or segment 00484 ncell_range & operator=(cobnd_proxy<host_type, EnclosingType> const & p) 00485 { 00486 init(p.first(), p.second()); 00487 return *this; 00488 } 00489 00490 iterator begin() const 00491 { 00492 assert(cont_ != NULL); 00493 return iterator(cont_); 00494 } 00495 00496 iterator end() const 00497 { 00498 assert(cont_ != NULL); 00499 return iterator(cont_ + num); 00500 } 00501 00502 element_type & operator[](std::size_t index) const 00503 { 00504 assert(index < size()); 00505 return *(cont_[index]); 00506 } 00507 00508 std::size_t size() const { return num; } 00509 00510 template <typename element_type, long dim2, bool b2> 00511 friend class const_ncell_range; 00512 00513 private: 00514 template <typename EnclosingType> 00515 void init(host_type const & e, 00516 EnclosingType const & d) 00517 //void init(cobnd_proxy< element<config_type, tag>, 00518 // EnclosingType> const & p) 00519 { 00520 typedef coboundary_key<EnclosingType, dim> CoBoundaryKey; 00521 00522 CoBoundaryKey key(d); 00523 00524 //initialize co-boundary if needed 00525 if (viennadata::find<CoBoundaryKey, 00526 viennadata_container_type >(key)(e) == NULL) 00527 { 00528 init_coboundary< tag::dim, 00529 dim, 00530 viennadata_container_type>(key, d); 00531 } 00532 00533 viennadata_container_type & temp = viennadata::access<CoBoundaryKey, 00534 viennadata_container_type>(key)(e); 00535 cont_ = &(temp[0]); 00536 num = temp.size(); 00537 } 00538 00539 container_type * cont_; 00540 size_t num; 00541 }; 00542 00543 00544 // const: 00546 template <typename T, typename U> 00547 class const_cobnd_proxy 00548 { 00549 public: 00550 const_cobnd_proxy(T const & t_, U const & u_) : t(t_), u(u_) {} 00551 00552 T const & first() const { return t; } 00553 U const & second() const { return u; } 00554 00555 private: 00556 T const & t; 00557 U const & u; 00558 }; 00559 00566 template <typename config_type, typename tag, 00567 long dim> 00568 class const_ncell_range < element_t<config_type, tag>, dim, true> 00569 { 00570 typedef element_t< config_type, 00571 typename topology::bndcells<typename config_type::cell_tag, 00572 dim>::tag 00573 > element_type; 00574 00575 typedef element_t<config_type, tag> host_type; 00576 typedef std::vector<element_type *> viennadata_container_type; 00577 typedef element_type * container_type; 00578 00579 public: 00580 //typedef typename container_type::iterator iterator; 00581 typedef const_on_element_iterator<element_type> iterator; 00582 00583 const_ncell_range() {}; 00584 00585 template <typename EnclosingType> //either domain or segment 00586 const_ncell_range(cobnd_proxy<host_type, EnclosingType> const & p) 00587 { 00588 init(p.first(), p.second()); 00589 } 00590 00591 template <typename EnclosingType> //either domain or segment 00592 const_ncell_range(const_cobnd_proxy<host_type, EnclosingType> const & p) 00593 { 00594 init(p.first(), p.second()); 00595 } 00596 00597 template <typename EnclosingType> //either domain or segment 00598 const_ncell_range(host_type const & e, 00599 EnclosingType const & d) 00600 { 00601 //std::cout << "Using const!" << std::endl; 00602 init(e, d); 00603 } 00604 00605 00606 00607 template <typename EnclosingType> //either domain or segment 00608 const_ncell_range & operator=(cobnd_proxy<host_type, EnclosingType> const & p) 00609 { 00610 init(p.first(), p.second()); 00611 return *this; 00612 } 00613 00614 template <typename EnclosingType> //either domain or segment 00615 const_ncell_range & operator=(const_cobnd_proxy<host_type, EnclosingType> const & p) 00616 { 00617 init(p.first(), p.second()); 00618 return *this; 00619 } 00620 00621 const_ncell_range & operator=(ncell_range<host_type, dim, true > const & other) 00622 { 00623 cont_ = other.cont_; 00624 num = other.num; 00625 return *this; 00626 } 00627 00628 iterator begin() const 00629 { 00630 assert(cont_ != NULL); 00631 return iterator(cont_); 00632 } 00633 00634 iterator end() const 00635 { 00636 assert(cont_ != NULL); 00637 return iterator(cont_ + num); 00638 } 00639 00640 element_type const & operator[](std::size_t index) const 00641 { 00642 assert(index < size()); 00643 return *(cont_[index]); 00644 } 00645 00646 std::size_t size() const { return num; } 00647 00648 private: 00649 00650 template <typename EnclosingType> 00651 void init(host_type const & e, 00652 EnclosingType const & d) 00653 //void init(const_cobnd_proxy< element<config_type, tag>, 00654 // EnclosingType> const & p) 00655 { 00656 typedef coboundary_key<EnclosingType, dim> CoBoundaryKey; 00657 00658 CoBoundaryKey key(d); 00659 00660 //initialize co-boundary if needed 00661 if (viennadata::find<CoBoundaryKey, 00662 viennadata_container_type >(key)(e) == NULL) 00663 { 00664 init_coboundary< tag::dim, 00665 dim, 00666 viennadata_container_type>(key, d); 00667 } 00668 00669 viennadata_container_type & temp = viennadata::access<CoBoundaryKey, 00670 viennadata_container_type>(key)(e); 00671 cont_ = &(temp[0]); 00672 num = temp.size(); 00673 } 00674 00675 const container_type * cont_; 00676 size_t num; 00677 }; 00678 00679 00689 template <long dim, typename Config, typename ElementTag> 00690 const_ncell_range < element_t<Config, ElementTag>, dim, true> 00691 ncells(element_t<Config, ElementTag> const & e, domain_t<Config> const & d) 00692 { 00693 return const_ncell_range < element_t<Config, ElementTag>, dim, true>(e, d); 00694 } 00695 00705 template <typename Config, typename ElementTag> 00706 const_cobnd_proxy< element_t<Config, ElementTag>, 00707 domain_t<Config> > 00708 ncells(element_t<Config, ElementTag> const & e, domain_t<Config> const & d) 00709 { 00710 return const_cobnd_proxy< element_t<Config, ElementTag>, 00711 domain_t<Config> >(e, d); 00712 } 00713 00714 00715 00725 template <long dim, typename Config, typename ElementTag> 00726 const_ncell_range < element_t<Config, ElementTag>, dim, true> 00727 ncells(element_t<Config, ElementTag> const & e, segment_t<Config> const & seg) 00728 { 00729 return const_ncell_range < element_t<Config, ElementTag>, dim, true>(e, seg); 00730 } 00731 00741 template <typename Config, typename ElementTag> 00742 const_cobnd_proxy< element_t<Config, ElementTag>, 00743 segment_t<Config> > 00744 ncells(element_t<Config, ElementTag> const & e, segment_t<Config> const & seg) 00745 { 00746 return const_cobnd_proxy< element_t<Config, ElementTag>, 00747 segment_t<Config> >(e, seg); 00748 } 00749 00750 00751 00752 // 00753 // local vertex orientation: 00754 // 00761 template <typename ConfigType, typename Tag1, typename Tag2> 00762 typename result_of::ncell<ConfigType, 0>::type 00763 local_vertex(element_t<ConfigType, Tag1> const & host_ncell, 00764 element_t<ConfigType, Tag2> const & bnd_kcell, 00765 std::size_t index) 00766 { 00767 //std::cout << host_ncell.global_to_local_orientation(bnd_kcell, index) << std::endl; 00768 return viennagrid::ncells<0>(bnd_kcell)[host_ncell.global_to_local_orientation(bnd_kcell, index)]; 00769 } 00770 00771 00772 00773 00774 // 00775 // Generic layer using metafunctions: 00776 // 00777 namespace result_of 00778 { 00780 template <long a, long b> 00781 struct is_smaller 00782 { 00783 enum { value = (a < b) }; 00784 }; 00785 00787 template <typename Config, typename ElementTag, 00788 long dim> //topological level 00789 struct ncell_range < element_t<Config, ElementTag>, dim > 00790 { 00791 typedef viennagrid::ncell_range<element_t<Config, ElementTag>, 00792 dim, 00793 is_smaller<ElementTag::dim, dim>::value 00794 > 00795 type; 00796 }; 00797 00799 template <typename Config, typename ElementTag, 00800 long dim> //topological level 00801 struct const_ncell_range < element_t<Config, ElementTag>, dim > 00802 { 00803 typedef viennagrid::const_ncell_range<element_t<Config, ElementTag>, 00804 dim, 00805 is_smaller<ElementTag::dim, dim>::value 00806 > 00807 type; 00808 }; 00809 00811 template <typename Config, typename ElementTag, 00812 long dim, 00813 long cell_level /* see forwards.h for default argument */> 00814 struct element_container< element_t<Config, ElementTag>, dim, cell_level > 00815 { 00816 typedef typename result_of::ncell<Config, dim>::type element_type; 00817 00818 typedef element_type * type; 00819 }; 00820 00821 //Iterator types for elements 00823 template <typename config_type, typename tag, long dim> 00824 struct iterator< element_t<config_type, tag>, 00825 dim> 00826 { 00827 /*typedef on_element_iterator< element<Config, ElementTag>, //the host element type 00828 element<Config, //the subcell type 00829 typename subcell_traits<ElementTag, level>::tag> 00830 > type; */ 00831 00832 typedef typename viennagrid::ncell_range < element_t<config_type, tag>, dim>::iterator type; 00833 }; 00834 00835 00836 } 00837 00838 } //namespace viennafem 00839 00840 #endif 00841
1.7.6.1