00001 #ifndef VIENNAGRID_ELEMENT_ITERATORS_HPP
00002 #define VIENNAGRID_ELEMENT_ITERATORS_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00031
00032 #include "viennadata/api.hpp"
00033
00038 namespace viennagrid
00039 {
00040
00041 template <typename ElementType>
00042 class const_on_element_iterator;
00043
00044
00045
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
00066
00067
00068 template <typename ElementType2>
00069 friend class const_on_element_iterator;
00070
00071 private:
00072 ElementType **pp_;
00073 };
00074
00075
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;
00100
00101
00102
00103
00104 private:
00105 ElementPtr const * pp_;
00106 };
00107
00108
00110
00111
00112
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
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
00167 typedef typename result_of::element_container<host_type, dim, config_type::cell_tag::dim>::type container_type;
00168
00169 public:
00170
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
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
00252 typedef typename result_of::element_container<host_type, dim, config_type::cell_tag::dim>::type container_type;
00253
00254 public:
00255
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
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
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
00465 typedef on_element_iterator<element_type> iterator;
00466
00467 ncell_range() : cont_(NULL) {};
00468
00469 template <typename EnclosingType>
00470 ncell_range(cobnd_proxy<host_type, EnclosingType> const & p)
00471 {
00472 init(p.first(), p.second());
00473 }
00474
00475 template <typename EnclosingType>
00476 ncell_range(host_type const & e,
00477 EnclosingType const & d)
00478 {
00479
00480 init(e, d);
00481 }
00482
00483 template <typename EnclosingType>
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
00518
00519 {
00520 typedef coboundary_key<EnclosingType, dim> CoBoundaryKey;
00521
00522 CoBoundaryKey key(d);
00523
00524
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
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
00581 typedef const_on_element_iterator<element_type> iterator;
00582
00583 const_ncell_range() {};
00584
00585 template <typename EnclosingType>
00586 const_ncell_range(cobnd_proxy<host_type, EnclosingType> const & p)
00587 {
00588 init(p.first(), p.second());
00589 }
00590
00591 template <typename EnclosingType>
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>
00598 const_ncell_range(host_type const & e,
00599 EnclosingType const & d)
00600 {
00601
00602 init(e, d);
00603 }
00604
00605
00606
00607 template <typename EnclosingType>
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>
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
00654
00655 {
00656 typedef coboundary_key<EnclosingType, dim> CoBoundaryKey;
00657
00658 CoBoundaryKey key(d);
00659
00660
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
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
00768 return viennagrid::ncells<0>(bnd_kcell)[host_ncell.global_to_local_orientation(bnd_kcell, index)];
00769 }
00770
00771
00772
00773
00774
00775
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>
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>
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 >
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
00823 template <typename config_type, typename tag, long dim>
00824 struct iterator< element_t<config_type, tag>,
00825 dim>
00826 {
00827
00828
00829
00830
00831
00832 typedef typename viennagrid::ncell_range < element_t<config_type, tag>, dim>::iterator type;
00833 };
00834
00835
00836 }
00837
00838 }
00839
00840 #endif
00841