ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/element/element.hpp
Go to the documentation of this file.
00001 #ifndef VIENNAGRID_ELEMENT_HPP
00002 #define VIENNAGRID_ELEMENT_HPP
00003 
00004 /* =======================================================================
00005    Copyright (c) 2011-2014, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008 
00009                             -----------------
00010                      ViennaGrid - The Vienna Grid Library
00011                             -----------------
00012 
00013    License:      MIT (X11), see file LICENSE in the base directory
00014 ======================================================================= */
00015 
00016 
00017 #include "viennagrid/forwards.hpp"
00018 #include "viennagrid/point.hpp"
00019 #include "viennagrid/meta/typelist.hpp"
00020 #include "viennagrid/meta/algorithm.hpp"
00021 
00022 #include "viennagrid/storage/collection.hpp"
00023 #include "viennagrid/storage/range.hpp"
00024 
00025 #include "viennagrid/topology/simplex.hpp"
00026 #include "viennagrid/element/element_orientation.hpp"
00027 
00028 #include "viennagrid/config/element_config.hpp"
00029 
00034 namespace viennagrid
00035 {
00040   template<typename element_tag, typename boundary_config_typemap>
00041   class boundary_element_layer;
00042 
00044   template<typename element_tag, typename bnd_cell_container_type_, typename orientation_container_type_, typename tail>
00045   class boundary_element_layer<element_tag, viennagrid::typelist< viennagrid::static_pair<bnd_cell_container_type_, orientation_container_type_>, tail > > :
00046       public boundary_element_layer<element_tag, tail>
00047   {
00048   public:
00049     typedef boundary_element_layer<element_tag, tail> base;
00050 
00051     typedef bnd_cell_container_type_                            bnd_cell_container_type;
00052     typedef typename bnd_cell_container_type::value_type        bnd_cell_type;
00053     typedef typename bnd_cell_container_type::handle_type       bnd_cell_handle_type;
00054     typedef typename bnd_cell_container_type::const_handle_type bnd_cell_const_handle_type;
00055 
00056     typedef typename bnd_cell_type::tag bnd_cell_tag;
00057     static const int dim = bnd_cell_tag::dim;
00058 
00059     typedef orientation_container_type_ orientation_container_type;
00060     typedef typename orientation_container_type::value_type orientation_type;
00061 
00062     boundary_element_layer() {}
00063 
00064     boundary_element_layer( const boundary_element_layer & llh) : base(llh), elements_(llh.elements_), orientations_(llh.orientations_) {}
00065 
00066     template<typename container_typelist>
00067     void set_container( viennagrid::collection<container_typelist> & container_collection )
00068     {
00069       elements_.set_base_container( viennagrid::get<bnd_cell_type>(container_collection) );
00070       base::set_container( container_collection );
00071     }
00072 
00073     template<typename element_type, typename inserter_type>
00074     void create_boundary_elements(element_type & element, inserter_type & inserter)
00075     {
00076       detail::boundary_element_generator<element_tag, bnd_cell_tag, bnd_cell_type>::create_boundary_elements(element, inserter);
00077       base::create_boundary_elements(element, inserter);
00078     }
00079 
00080 
00081     using base::container;
00082     using base::set_boundary_element;
00083     using base::add_boundary_element;
00084     using base::dereference_handle;
00085     using base::handle;
00086     using base::global_to_local_orientation;
00087 
00088 
00089     bnd_cell_type & dereference_handle(bnd_cell_handle_type handle)
00090     { return elements_.dereference_handle(handle); }
00091 
00092     const bnd_cell_type & dereference_handle(bnd_cell_const_handle_type handle) const
00093     { return elements_.dereference_handle(handle); }
00094 
00095 
00096 
00097     bnd_cell_handle_type handle(bnd_cell_type & boundary_element)
00098     { return elements_.handle(boundary_element); }
00099 
00100     bnd_cell_const_handle_type handle(bnd_cell_type const & boundary_element) const
00101     { return elements_.handle(boundary_element); }
00102 
00103 
00104 
00105           bnd_cell_container_type & container(bnd_cell_tag)       { return elements_; }
00106     const bnd_cell_container_type & container(bnd_cell_tag) const { return elements_; }
00107 
00108           bnd_cell_container_type & container(dimension_tag<dim>)       { return elements_; }
00109     const bnd_cell_container_type & container(dimension_tag<dim>) const { return elements_; }
00110 
00111 
00112 
00113     template<typename handle_type>
00114     void set_boundary_element(const bnd_cell_type & to_insert, std::pair<handle_type, bool> inserted, std::size_t pos)
00115     {
00116         elements_.set_handle(inserted.first, pos);
00117         orientations_.resize(pos+1);
00118 
00119         if (inserted.second)
00120             orientations_[pos].setDefaultOrientation();
00121         else
00122         {
00123           typedef typename result_of::const_element_range<bnd_cell_type, vertex_tag>::type   VertexOnElementConstRange;
00124           typedef typename result_of::const_iterator<VertexOnElementConstRange>::type        VertexOnElementConstIterator;
00125 
00126           typedef typename result_of::element_range<bnd_cell_type, vertex_tag>::type         VertexOnElementRange;
00127           typedef typename result_of::iterator<VertexOnElementRange>::type                   VertexOnElementIterator;
00128 
00129           long i=0; dim_type j=0;
00130 
00131           //set orientation:
00132           VertexOnElementRange vertices_on_element = elements<vertex_tag>( elements_[pos] );
00133           for (VertexOnElementIterator voeit = vertices_on_element.begin();
00134                   voeit != vertices_on_element.end();
00135                   ++voeit, ++i)
00136           {
00137             VertexOnElementConstRange vertices_on_element_2 = elements<vertex_tag>( to_insert );
00138             for (VertexOnElementConstIterator voeit2 = vertices_on_element_2.begin();
00139                     voeit2 != vertices_on_element_2.end();
00140                     ++voeit2, ++j)
00141             {
00142               if (voeit.handle() == voeit2.handle())
00143               {
00144                 orientations_[pos].setPermutation(j,static_cast<dim_type>(i));
00145                 break;
00146               }
00147             }
00148             j=0;
00149           }
00150         }
00151     }
00152 
00153     template<typename handle_type>
00154     void add_boundary_element(const bnd_cell_type & to_insert, std::pair<handle_type, bool> inserted)
00155     { set_boundary_element(to_insert, inserted, elements_.size()); }
00156 
00157 
00159   std::size_t global_to_local_orientation(bnd_cell_handle_type const & el, std::size_t index) const
00160   {
00161     for (std::size_t i=0; i<elements_.size(); ++i)
00162     {
00163       if (elements_.handle_at(i) == el)
00164         return orientations_[i](index);
00165     }
00166     assert(false && "Provided k-cell is not a boundary element of the hosting n-cell!");
00167     return static_cast<std::size_t>(index);
00168   }
00169 
00170 
00171     static void print_class()
00172     {
00173       std::cout << "  [ + + ]  " << bnd_cell_tag::name() << std::endl;
00174       base::print_class();
00175     }
00176 
00177     void print_orientation()
00178     {
00179       std::cout << "  [ + + ]  " << bnd_cell_tag::name() << std::endl;
00180       for (std::size_t i = 0; i < orientations_.size(); ++i)
00181           std::cout << "  " << orientations_[i] << std::endl;
00182       base::print_orientation();
00183     }
00184 
00185   private:
00186 
00187     bnd_cell_container_type elements_;
00188     orientation_container_type orientations_;
00189   };
00190 
00191 
00192   template<typename element_tag, typename bnd_cell_container_type_, typename tail>
00193   class boundary_element_layer<element_tag, viennagrid::typelist< viennagrid::static_pair<bnd_cell_container_type_, viennagrid::null_type>, tail > > :
00194       public boundary_element_layer<element_tag, tail>
00195   {
00196   public:
00197     typedef boundary_element_layer<element_tag, tail> base;
00198 
00199     typedef bnd_cell_container_type_                             bnd_cell_container_type;
00200     typedef typename bnd_cell_container_type::value_type         bnd_cell_type;
00201     typedef typename bnd_cell_container_type::handle_type        bnd_cell_handle_type;
00202     typedef typename bnd_cell_container_type::const_handle_type  bnd_cell_const_handle_type;
00203 
00204     typedef typename bnd_cell_type::tag bnd_cell_tag;
00205     static const int dim = bnd_cell_tag::dim;
00206 
00207     boundary_element_layer() {}
00208 
00209     boundary_element_layer( const boundary_element_layer & llh) : base(llh), elements_(llh.elements_) {}
00210 
00211     template<typename container_typelist>
00212     void set_container( viennagrid::collection<container_typelist> & container_collection )
00213     {
00214       elements_.set_base_container( viennagrid::get<bnd_cell_type>(container_collection) );
00215       base::set_container( container_collection );
00216     }
00217 
00218     template<typename element_type, typename inserter_type>
00219     void create_boundary_elements(element_type & element, inserter_type & inserter)
00220     {
00221       detail::boundary_element_generator<element_tag, bnd_cell_tag, bnd_cell_type>::create_boundary_elements(element, inserter);
00222       base::create_boundary_elements(element, inserter);
00223     }
00224 
00225     using base::container;
00226     using base::set_boundary_element;
00227     using base::add_boundary_element;
00228     using base::dereference_handle;
00229     using base::handle;
00230 
00231 
00232     bnd_cell_type & dereference_handle(bnd_cell_handle_type handle)
00233     { return elements_.dereference_handle(handle); }
00234 
00235     const bnd_cell_type & dereference_handle(bnd_cell_const_handle_type handle) const
00236     { return elements_.dereference_handle(handle); }
00237 
00238 
00239 
00240     bnd_cell_handle_type handle(bnd_cell_type & boundary_element)
00241     { return elements_.handle(boundary_element); }
00242 
00243     bnd_cell_const_handle_type handle(bnd_cell_type const & boundary_element) const
00244     { return elements_.handle(boundary_element); }
00245 
00246 
00247 
00248           bnd_cell_container_type & container(bnd_cell_tag)       { return elements_; }
00249     const bnd_cell_container_type & container(bnd_cell_tag) const { return elements_; }
00250 
00251           bnd_cell_container_type & container(dimension_tag<dim>)       { return elements_; }
00252     const bnd_cell_container_type & container(dimension_tag<dim>) const {  return elements_; }
00253 
00254 
00255 
00256     template<typename handle_type>
00257     void set_boundary_element(const bnd_cell_type &, std::pair<handle_type, bool> inserted, unsigned int pos)
00258     { elements_.set_handle(inserted.first, pos); }
00259 
00260     template<typename handle_type>
00261     void add_boundary_element(const bnd_cell_type & to_insert, std::pair<handle_type, bool> inserted)
00262     { set_boundary_element(to_insert, inserted, elements_.size()); }
00263 
00264     static void print_class()
00265     {
00266       std::cout << "  [ + - ]  " << bnd_cell_tag::name() << std::endl;
00267       base::print_class();
00268     }
00269 
00270     void print_orientation()
00271     {
00272       std::cout << "  [ - - ]  " << bnd_cell_tag::name() << std::endl;
00273       base::print_orientation();
00274     }
00275 
00276   private:
00277     bnd_cell_container_type elements_;
00278   };
00279 
00280   template<typename element_tag>
00281   class boundary_element_layer<element_tag, viennagrid::null_type >
00282   {
00283   public:
00284 
00285     boundary_element_layer() {}
00286 
00287     template<typename container_typelist>
00288     void set_container( viennagrid::collection<container_typelist> & ) {}
00289 
00290     template<typename element_type, typename inserter_type>
00291     void create_boundary_elements(element_type &, inserter_type &) {}
00292 
00293     static void print_class() {}
00294     void print_orientation() {}
00295 
00296     void container();
00297     void set_boundary_element();
00298     void add_boundary_element();
00299     void dereference_handle();
00300     void handle();
00301     void global_to_local_orientation();
00302 
00303   private:
00304   };
00308   namespace result_of
00309   {
00314     template<typename bnd_cell_typelist>
00315     struct boundary_element_typelist;
00316 
00318     template<>
00319     struct boundary_element_typelist<viennagrid::null_type>
00320     {
00321       typedef viennagrid::null_type type;
00322     };
00323 
00324     template<typename boundary_cell_container_type, typename orientation_container_type, typename tail>
00325     struct boundary_element_typelist< viennagrid::typelist<viennagrid::static_pair<boundary_cell_container_type, orientation_container_type>, tail > >
00326     {
00327       typedef viennagrid::typelist<
00328           typename boundary_cell_container_type::value_type,
00329           typename boundary_element_typelist<tail>::type
00330       > type;
00331     };
00332 
00333     template<typename element_tag, typename WrappedConfigType>
00334     struct boundary_element_typelist< viennagrid::element<element_tag, WrappedConfigType> >
00335     {
00336       typedef typename boundary_element_typelist<typename viennagrid::element<element_tag, WrappedConfigType>::bnd_cell_container_typelist>::type type;
00337     };
00345     template<typename bnd_cell_typelist>
00346     struct boundary_element_taglist {};
00347 
00349     template<>
00350     struct boundary_element_taglist<viennagrid::null_type>
00351     {
00352       typedef viennagrid::null_type type;
00353     };
00354 
00355     template<typename boundary_cell_container_type, typename orientation_container_type, typename tail>
00356     struct boundary_element_taglist< viennagrid::typelist<viennagrid::static_pair<boundary_cell_container_type, orientation_container_type>, tail > >
00357     {
00358       typedef viennagrid::typelist<
00359           typename boundary_cell_container_type::value_type::tag,
00360           typename boundary_element_taglist<tail>::type
00361       > type;
00362     };
00363 
00364     template<typename element_tag, typename WrappedConfigType>
00365     struct boundary_element_taglist< viennagrid::element<element_tag, WrappedConfigType> >
00366     {
00367       typedef typename boundary_element_taglist< typename viennagrid::element<element_tag, WrappedConfigType>::bnd_cell_container_typelist >::type type;
00368     };
00369 
00370 
00371 
00372 
00373 
00374     template<typename typelist, typename tag>
00375     struct container_of_tag_for_element;
00376 
00377     template<typename tag>
00378     struct container_of_tag_for_element< viennagrid::null_type, tag >
00379     {
00380       typedef viennagrid::null_type type;
00381     };
00382 
00383     template<typename container_pair, typename tail, typename tag>
00384     struct container_of_tag_for_element< viennagrid::typelist<container_pair, tail>, tag >
00385     {
00386       typedef typename container_pair::first container_type;
00387       typedef typename container_type::value_type value_type;
00388 
00389       typedef typename viennagrid::detail::IF<
00390           viennagrid::detail::EQUAL<typename value_type::tag, tag>::value,
00391           container_type,
00392           typename container_of_tag_for_element<tail, tag>::type
00393       >::type type;
00394     };
00395 
00396 
00397 
00398 
00399 
00400     template<typename typelist, int dim>
00401     struct container_of_dimension_for_element;
00402 
00403     template<int dim>
00404     struct container_of_dimension_for_element< viennagrid::null_type, dim >
00405     {
00406       typedef viennagrid::null_type type;
00407     };
00408 
00409     template<typename container_pair, typename tail, int dim>
00410     struct container_of_dimension_for_element< viennagrid::typelist<container_pair, tail>, dim >
00411     {
00412       typedef typename container_pair::first container_type;
00413       typedef typename container_type::value_type value_type;
00414 
00415       typedef typename viennagrid::detail::IF<
00416           value_type::tag::dim == dim,
00417           container_type,
00418           typename container_of_dimension_for_element<tail, dim>::type
00419       >::type type;
00420     };
00421 
00422 
00423 
00424     template<typename container_collection_typemap, typename element_tag>
00425     struct container_of_tag_for_collection;
00426 
00427     template<typename element_tag>
00428     struct container_of_tag_for_collection<viennagrid::null_type, element_tag>
00429     {
00430       typedef viennagrid::null_type type;
00431     };
00432 
00433     template<typename element_type, typename container_type, typename tail, typename element_tag>
00434     struct container_of_tag_for_collection<viennagrid::typelist< viennagrid::static_pair<element_type, container_type>, tail >, element_tag>
00435     {
00436       typedef typename viennagrid::detail::IF<
00437           viennagrid::detail::EQUAL<typename element_type::tag, element_tag>::value,
00438           container_type,
00439           typename container_of_tag_for_collection<tail, element_tag>::type
00440       >::type type;
00441     };
00442 
00443 
00444 
00445     template<typename container_collection_typemap, int dim>
00446     struct container_of_dimension_for_collection;
00447 
00448     template<int dim>
00449     struct container_of_dimension_for_collection<viennagrid::null_type, dim>
00450     {
00451       typedef viennagrid::null_type type;
00452     };
00453 
00454     template<typename element_type, typename container_type, typename tail, int dim>
00455     struct container_of_dimension_for_collection<viennagrid::typelist< viennagrid::static_pair<element_type, container_type>, tail >, dim>
00456     {
00457       typedef typename viennagrid::detail::IF<
00458           element_type::tag::dim == dim,
00459           container_type,
00460           typename container_of_dimension_for_collection<tail, dim>::type
00461       >::type type;
00462     };
00463 
00464 
00465 
00466 
00467     template<typename element_or_collection, typename tag>
00468     struct container_of_tag;
00469 
00470     template<typename container_collection_typemap, typename tag>
00471     struct container_of_tag< collection<container_collection_typemap>, tag >
00472     {
00473       typedef typename container_of_tag_for_collection<container_collection_typemap, tag>::type type;
00474     };
00475 
00476     template<typename element_tag, typename WrappedConfigType, typename tag>
00477     struct container_of_tag< viennagrid::element<element_tag, WrappedConfigType>, tag >
00478     {
00479       typedef typename container_of_tag_for_element<typename viennagrid::element<element_tag, WrappedConfigType>::bnd_cell_container_typelist, tag>::type type;
00480     };
00481 
00482     template<typename element_or_collection, long dim>
00483     struct container_of_dimension;
00484 
00485     template<typename container_collection_typemap, long dim>
00486     struct container_of_dimension< collection<container_collection_typemap>, dim >
00487     {
00488       typedef typename container_of_dimension_for_collection<container_collection_typemap, dim>::type type;
00489     };
00490 
00491     template<typename element_tag, typename WrappedConfigType, long dim>
00492     struct container_of_dimension< viennagrid::element<element_tag, WrappedConfigType>, dim >
00493     {
00494       typedef typename container_of_dimension_for_element<typename viennagrid::element<element_tag, WrappedConfigType>::bnd_cell_container_typelist, dim>::type type;
00495     };
00498 }
00499 
00500 
00501 
00502   namespace config
00503   {
00505     template<typename bnd_cell_container_typelist_, typename id_tag_, typename appendix_type_>
00506     struct element_config_wrapper_t
00507     {
00508       typedef bnd_cell_container_typelist_ bnd_cell_container_typelist;
00509       typedef id_tag_ id_tag;
00510       typedef appendix_type_ appendix_type;
00511     };
00513   }
00514 
00515 
00516 
00522   template<typename ElementTagT>
00523   class element_extension {};
00524 
00530   template<typename ElementTag, typename WrappedConfigType>
00531   class element :
00532       public boundary_element_layer<ElementTag, typename config::result_of::element_boundary_element_container_typelist<WrappedConfigType, ElementTag>::type>,
00533       public viennagrid::detail::id_handler<
00534                   typename viennagrid::detail::result_of::make_id<
00535                     viennagrid::element<
00536                       ElementTag,
00537                       WrappedConfigType
00538                     >,
00539                     typename config::result_of::query_element_id_tag<WrappedConfigType, ElementTag>::type
00540                   >::type
00541               >,
00542       public element_extension<ElementTag>
00543   {
00544   public:
00545 
00546     typedef viennagrid::detail::id_handler<
00547                   typename viennagrid::detail::result_of::make_id<
00548                     viennagrid::element<
00549                       ElementTag,
00550                       WrappedConfigType
00551                     >,
00552                     typename config::result_of::query_element_id_tag<WrappedConfigType, ElementTag>::type
00553                   >::type
00554               > id_handler_type;
00555 
00556     typedef ElementTag tag;
00557 
00558     typedef typename config::result_of::element_boundary_element_container_typelist<WrappedConfigType, ElementTag>::type     bnd_cell_container_typelist;
00559     typedef typename config::result_of::query_element_id_tag<WrappedConfigType, ElementTag>::type                            id_tag;
00560     typedef typename config::result_of::query_appendix_type<WrappedConfigType, ElementTag>::type                             appendix_type;
00561 
00562     typedef boundary_element_layer<ElementTag, bnd_cell_container_typelist>                                              base;
00563 
00564     typedef typename result_of::boundary_element_typelist<bnd_cell_container_typelist>::type                             boundary_cell_typelist;
00565 
00566     typedef typename viennagrid::detail::result_of::make_id< viennagrid::element<ElementTag, WrappedConfigType>, id_tag>::type    id_type;
00567     typedef typename viennagrid::detail::result_of::const_id<id_type>::type                                             const_id_type;
00568 
00569     template<typename container_typelist>
00570     element( viennagrid::collection<container_typelist> & container_collection )
00571     {
00572         base::set_container(container_collection);
00573     }
00574 
00575     template<typename inserter_type>
00576     void insert_callback( inserter_type & inserter, bool inserted )
00577     {
00578         if (inserted)
00579         {
00580             base::create_boundary_elements(*this, inserter);
00581         }
00582     }
00583 
00584     static void print_class()
00585     {
00586         std::cout << ElementTag::name() << std::endl;
00587         base::print_class();
00588     }
00589 
00590     void print_orientation()
00591     {
00592         std::cout << ElementTag::name() << std::endl;
00593         base::print_orientation();
00594     }
00595 
00596 
00597     typedef typename result_of::container_of_dimension_for_element< bnd_cell_container_typelist, 0>::type::handle_type vertex_handle_type;
00598     void set_vertex( const vertex_handle_type & vertex, unsigned int pos )
00599     {
00600         this->container(viennagrid::dimension_tag<0>()).set_handle( vertex, pos );
00601     }
00602 
00603     appendix_type & appendix() { return appendix_; }
00604     appendix_type const & appendix() const { return appendix_; }
00605 
00606   private:
00607     appendix_type appendix_;
00608   };
00609 
00610 
00611   // separate specialization for vertices at the moment
00613   template<typename WrappedConfigType>
00614   class element<vertex_tag, WrappedConfigType> :
00615       public viennagrid::detail::id_handler<
00616                   typename viennagrid::detail::result_of::make_id<
00617                     viennagrid::element<
00618                       vertex_tag,
00619                       WrappedConfigType
00620                     >,
00621                     typename config::result_of::query_element_id_tag<WrappedConfigType, vertex_tag>::type
00622                   >::type
00623               >,
00624       public element_extension<vertex_tag>
00625   {
00626   public:
00627 
00628     typedef viennagrid::detail::id_handler<
00629                   typename viennagrid::detail::result_of::make_id<
00630                     viennagrid::element<
00631                       vertex_tag,
00632                       WrappedConfigType
00633                     >,
00634                     typename config::result_of::query_element_id_tag<WrappedConfigType, vertex_tag>::type
00635                   >::type
00636               > id_handler_type;
00637 
00638     typedef vertex_tag tag;
00639 
00640     typedef typename config::result_of::element_boundary_element_container_typelist<WrappedConfigType, vertex_tag>::type   bnd_cell_container_typelist;
00641     typedef typename config::result_of::query_element_id_tag<WrappedConfigType, vertex_tag>::type                          id_tag;
00642     typedef typename config::result_of::query_appendix_type<WrappedConfigType, vertex_tag>::type                           appendix_type;
00643 
00644     typedef viennagrid::element<vertex_tag, WrappedConfigType>            self_type;
00645 
00646     element() {}
00647 
00648     template<typename container_typelist>
00649     element( viennagrid::collection<container_typelist> & ) {}
00650 
00651     typedef typename result_of::boundary_element_typelist<bnd_cell_container_typelist>::type                            boundary_cell_typelist;
00652     typedef typename viennagrid::detail::result_of::make_id< viennagrid::element<vertex_tag, WrappedConfigType>, id_tag>::type   id_type;
00653     typedef typename viennagrid::detail::result_of::const_id<id_type>::type                                            const_id_type;
00654 
00655     template<typename inserter_type>
00656     void insert_callback( inserter_type &, bool ) {}
00657 
00658     void print_orientation()
00659     {
00660       std::cout << vertex_tag::name() << std::endl;
00661     }
00662 
00663     static void print_class()
00664     {
00665       std::cout << vertex_tag::name() << std::endl;
00666     }
00667 
00668     appendix_type       & appendix()       { return appendix_; }
00669     appendix_type const & appendix() const { return appendix_; }
00670 
00671   private:
00672     appendix_type appendix_;
00673   };
00678   namespace result_of
00679   {
00681       template<typename element_type_or_tag>
00682       struct topologic_dimension
00683       {
00684           static const int value = element_tag<element_type_or_tag>::type::dim;
00685       };
00686 
00687 
00693       template<typename element_type, typename boundary_cell_type_or_tag>
00694       struct has_boundary
00695       {};
00696 
00698       template<typename element_tag_, typename WrappedConfigType, typename boundary_cell_type_or_tag>
00699       struct has_boundary< viennagrid::element<element_tag_, WrappedConfigType>, boundary_cell_type_or_tag >
00700       {
00701           typedef typename element_tag<boundary_cell_type_or_tag>::type boundary_cell_tag;
00702 
00703           const static bool value =
00704           !viennagrid::detail::EQUAL<
00705               typename container_of_tag< viennagrid::element<element_tag_, WrappedConfigType>, boundary_cell_tag >::type,
00706               viennagrid::null_type>::value;
00707       };
00708 
00709 
00710 
00711 
00712       // Defines a SUB-ELEMENT from an ELEMENT using SUB-ELEMENT TYPE or TAG
00713       template<typename element_tag_, typename WrappedConfigType, typename sub_element_type_or_tag>
00714       struct element< viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag >
00715       {
00716           typedef typename viennagrid::element<element_tag_, WrappedConfigType>::bnd_cell_container_typelist boundary_cell_container_typelist;
00717           typedef typename element_tag<sub_element_type_or_tag>::type sub_element_tag;
00718           typedef typename container_of_tag_for_element<boundary_cell_container_typelist , sub_element_tag >::type::value_type type;
00719       };
00720 
00721       template<typename element_tag_, typename WrappedConfigType, typename sub_element_type_or_tag>
00722       struct element< const viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag >
00723       {
00724           typedef typename viennagrid::element<element_tag_, WrappedConfigType>::bnd_cell_container_typelist boundary_cell_container_typelist;
00725           typedef typename element_tag<sub_element_type_or_tag>::type sub_element_tag;
00726           typedef const typename container_of_tag_for_element< boundary_cell_container_typelist, sub_element_tag >::type::value_type type;
00727       };
00728 
00729       // Defines a HOOK TO a SUB-ELEMENT from an ELEMENT using SUB-ELEMENT TYPE or TAG
00730       template<typename element_tag_, typename WrappedConfigType, typename sub_element_type_or_tag>
00731       struct handle< viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag >
00732       {
00733           typedef typename viennagrid::element<element_tag_, WrappedConfigType>::bnd_cell_container_typelist boundary_cell_container_typelist;
00734           typedef typename element_tag<sub_element_type_or_tag>::type sub_element_tag;
00735           typedef typename container_of_tag_for_element< boundary_cell_container_typelist, sub_element_tag >::type::handle_type type;
00736       };
00737 
00738       // Defines a const HOOK TO a SUB-ELEMENT from an ELEMENT using SUB-ELEMENT TYPE or TAG
00739       template<typename element_tag_, typename WrappedConfigType, typename sub_element_type_or_tag>
00740       struct const_handle< viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag >
00741       {
00742           typedef typename viennagrid::element<element_tag_, WrappedConfigType>::bnd_cell_container_typelist boundary_cell_container_typelist;
00743           typedef typename element_tag<sub_element_type_or_tag>::type sub_element_tag;
00744           typedef typename container_of_tag_for_element< boundary_cell_container_typelist, sub_element_tag >::type::const_handle_type type;
00745       };
00746 
00747 
00748       template<typename element_tag_, typename WrappedConfigType, typename sub_element_type_or_tag>
00749       struct element_range< viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag >
00750       {
00751           typedef typename viennagrid::element<element_tag_, WrappedConfigType>::bnd_cell_container_typelist boundary_cell_container_typelist;
00752           typedef typename element< viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag>::type sub_element_type;
00753           typedef viennagrid::detail::container_range_wrapper< typename container_of_tag_for_element<boundary_cell_container_typelist, typename sub_element_type::tag>::type > type;
00754       };
00755 
00756       template<typename element_tag_, typename WrappedConfigType, typename sub_element_type_or_tag>
00757       struct const_element_range< viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag >
00758       {
00759           typedef typename viennagrid::element<element_tag_, WrappedConfigType>::bnd_cell_container_typelist boundary_cell_container_typelist;
00760           typedef typename element< viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag>::type sub_element_type;
00761           typedef viennagrid::detail::container_range_wrapper< const typename container_of_tag_for_element<boundary_cell_container_typelist, typename sub_element_type::tag>::type > type;
00762       };
00763 
00764       template<typename element_tag_, typename WrappedConfigType, typename sub_element_type_or_tag>
00765       struct element_range< const viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag >
00766       {
00767           typedef typename const_element_range< viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag >::type type;
00768       };
00769 
00770       template<typename element_tag_, typename WrappedConfigType, typename sub_element_type_or_tag>
00771       struct const_element_range< const viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag >
00772       {
00773           typedef typename const_element_range< viennagrid::element<element_tag_, WrappedConfigType>, sub_element_type_or_tag >::type type;
00774       };
00775 
00776 
00777 
00778       template<typename container_collection_typemap, typename element_type_or_tag>
00779       struct element<viennagrid::collection<container_collection_typemap>, element_type_or_tag>
00780       {
00781           typedef typename element_tag<element_type_or_tag>::type element_tag;
00782           typedef typename container_of_tag_for_collection<container_collection_typemap, element_tag>::type::value_type type;
00783       };
00784 
00785       template<typename container_collection_typemap, typename element_type_or_tag>
00786       struct handle<viennagrid::collection<container_collection_typemap>, element_type_or_tag>
00787       {
00788           typedef typename element_tag<element_type_or_tag>::type element_tag;
00789 
00790           // Error in line below possibly means that there is no element_type_or_tag in
00791           typedef typename container_of_tag_for_collection<container_collection_typemap, element_tag>::type::handle_type type;
00792       };
00793 
00794       template<typename container_collection_typemap, typename element_type_or_tag>
00795       struct const_handle<viennagrid::collection<container_collection_typemap>, element_type_or_tag>
00796       {
00797           typedef typename element_tag<element_type_or_tag>::type element_tag;
00798           typedef typename container_of_tag_for_collection<container_collection_typemap, element_tag>::type::const_handle_type type;
00799       };
00800 
00801 
00802       template<typename container_collection_typemap, typename element_type_or_tag>
00803       struct element_range<viennagrid::collection<container_collection_typemap>, element_type_or_tag>
00804       {
00805           typedef typename element_tag<element_type_or_tag>::type element_tag_;
00806           typedef viennagrid::detail::container_range_wrapper< typename container_of_tag_for_collection<container_collection_typemap, element_tag_>::type > type;
00807       };
00808 
00809       template<typename container_collection_typemap, typename element_type_or_tag>
00810       struct const_element_range<viennagrid::collection<container_collection_typemap>, element_type_or_tag>
00811       {
00812           typedef typename element_tag<element_type_or_tag>::type element_tag_;
00813           typedef viennagrid::detail::container_range_wrapper< const typename container_of_tag_for_collection<container_collection_typemap, element_tag_>::type > type;
00814       };
00815 
00816       template<typename container_collection_typemap, typename element_type_or_tag>
00817       struct element_range< const viennagrid::collection<container_collection_typemap>, element_type_or_tag>
00818       {
00819           typedef typename const_element_range<viennagrid::collection<container_collection_typemap>, element_type_or_tag>::type type;
00820       };
00821 
00822       template<typename container_collection_typemap, typename element_type_or_tag>
00823       struct const_element_range< const viennagrid::collection<container_collection_typemap>, element_type_or_tag>
00824       {
00825           typedef typename const_element_range<viennagrid::collection<container_collection_typemap>, element_type_or_tag>::type type;
00826       };
00828   }
00829 
00830 
00831 
00832   // doxygen docu in forwards.hpp
00833   template<typename sub_element_type_or_tag, typename element_tag, typename WrappedConfigType>
00834   typename result_of::element_range<viennagrid::element<element_tag, WrappedConfigType>, sub_element_type_or_tag>::type
00835   elements( viennagrid::element<element_tag, WrappedConfigType> & element)
00836   {
00837       typedef typename result_of::element<viennagrid::element<element_tag, WrappedConfigType>, sub_element_type_or_tag>::type sub_element_type;
00838       return typename result_of::element_range<viennagrid::element<element_tag, WrappedConfigType>, sub_element_type_or_tag>::type( element.container( typename sub_element_type::tag() ) );
00839   }
00840 
00841   // doxygen docu in forwards.hpp
00842   template<typename sub_element_type_or_tag, typename element_tag, typename WrappedConfigType>
00843   typename result_of::const_element_range<viennagrid::element<element_tag, WrappedConfigType>, sub_element_type_or_tag>::type
00844   elements( const viennagrid::element<element_tag, WrappedConfigType> & element)
00845   {
00846       typedef typename result_of::element<viennagrid::element<element_tag, WrappedConfigType>, sub_element_type_or_tag>::type sub_element_type;
00847       return typename result_of::const_element_range<viennagrid::element<element_tag, WrappedConfigType>, sub_element_type_or_tag>::type( element.container( typename sub_element_type::tag() ) );
00848   }
00849 
00850 
00851 
00858   template<typename element_tag, typename WrappedConfigType, typename handle_type>
00859   typename detail::result_of::value_type<handle_type>::type & dereference_handle( viennagrid::element<element_tag, WrappedConfigType> & element, handle_type const & handle)
00860   {
00861       return element.dereference_handle(handle);
00862   }
00863 
00870   template<typename element_tag, typename WrappedConfigType, typename handle_type>
00871   const typename detail::result_of::value_type<handle_type>::type & dereference_handle( viennagrid::element<element_tag, WrappedConfigType> const & element, handle_type const & handle)
00872   {
00873       return element.dereference_handle(handle);
00874   }
00875 
00876 
00878   template<typename ElementTag1, typename WrappedConfigType1, typename ElementTag2, typename WrappedConfigType2>
00879   typename result_of::handle<viennagrid::element<ElementTag1, WrappedConfigType1>, viennagrid::element<ElementTag2, WrappedConfigType2> >::type
00880   handle( viennagrid::element<ElementTag1, WrappedConfigType1> & element, viennagrid::element<ElementTag2, WrappedConfigType2> & boundary_element )
00881   {
00882       return element.handle(boundary_element);
00883   }
00884 
00886   template<typename ElementTag1, typename WrappedConfigType1, typename ElementTag2, typename WrappedConfigType2>
00887   typename result_of::const_handle<viennagrid::element<ElementTag1, WrappedConfigType1>, viennagrid::element<ElementTag2, WrappedConfigType2> >::type
00888   handle( viennagrid::element<ElementTag1, WrappedConfigType1> const & element, viennagrid::element<ElementTag2, WrappedConfigType2> const & boundary_element )
00889   {
00890       return element.handle(boundary_element);
00891   }
00892 
00893 
00894 
00895 
00903   template<typename element_type_or_tag, typename container_collection_typemap>
00904   typename result_of::element_range<collection<container_collection_typemap>, element_type_or_tag>::type elements( collection<container_collection_typemap> & collection)
00905   {
00906       typedef typename result_of::element<viennagrid::collection<container_collection_typemap>, element_type_or_tag>::type element_type;
00907       return typename result_of::element_range<viennagrid::collection<container_collection_typemap>, element_type_or_tag>::type( get<element_type>(collection) );
00908   }
00909 
00917   template<typename element_type_or_tag, typename container_collection_typemap>
00918   typename result_of::const_element_range<collection<container_collection_typemap>, element_type_or_tag>::type elements( const collection<container_collection_typemap> & collection)
00919   {
00920       typedef typename result_of::element<viennagrid::collection<container_collection_typemap>, element_type_or_tag>::type element_type;
00921       return typename result_of::const_element_range<viennagrid::collection<container_collection_typemap>, element_type_or_tag>::type( get<element_type>(collection) );
00922   }
00923 
00924 
00925 
00926 
00927   namespace detail
00928   {
00929 
00931     template<typename ElementT, typename FunctorT>
00932     struct for_each_boundary_element_functor
00933     {
00934     public:
00935 
00936       for_each_boundary_element_functor( ElementT & element_, FunctorT functor_ ) : element(element_), functor(functor_) {}
00937 
00938       template<typename boundary_cell_type>
00939       void operator()( viennagrid::detail::tag<boundary_cell_type> )
00940       {
00941         typedef typename viennagrid::result_of::element_range<ElementT, boundary_cell_type>::type    boundary_cell_range_type;
00942         typedef typename viennagrid::result_of::iterator<boundary_cell_range_type>::type                 boundary_cell_iterator_type;
00943 
00944         boundary_cell_range_type range = viennagrid::elements<boundary_cell_type>( element );
00945         for (boundary_cell_iterator_type it = range.begin(); it != range.end(); ++it)
00946           functor(*it);
00947       }
00948 
00949     private:
00950       ElementT & element;
00951       FunctorT functor;
00952     };
00953 
00954   } // namespace detail
00955 
00957   template<typename BoundaryElementTypelistT, typename ElementT, typename FunctorT>
00958   void for_each_boundary_element( ElementT & element, FunctorT functor )
00959   {
00960       detail::for_each_boundary_element_functor<ElementT, FunctorT> for_each_functor( element, functor );
00961 
00962       viennagrid::detail::for_each<BoundaryElementTypelistT>(for_each_functor);
00963   }
00964 
00965   template<typename ElementT, typename FunctorT>
00966   void for_each_boundary_element( ElementT & element, FunctorT functor )
00967   {
00968     for_each_boundary_element<typename ElementT::boundary_cell_typelist>( element, functor  );
00969   }
00970 
00971 
00972 
00973 
00974   inline std::ostream & operator<<(std::ostream & os, viennagrid::null_type) { return os; }
00975 
00976 
00978   template <typename WrappedConfigType>
00979   std::ostream & operator<<(std::ostream & os, viennagrid::element<vertex_tag, WrappedConfigType> const & el)
00980   {
00981       os << "-- Vertex, ID: " << el.id() << " " << el.appendix();
00982 
00983       return os;
00984   }
00985 
00986 
00988   template <typename element_tag, typename WrappedConfigType>
00989   std::ostream & operator<<(std::ostream & os, viennagrid::element<element_tag, WrappedConfigType> const & el)
00990   {
00991       typedef viennagrid::element<element_tag, WrappedConfigType> element_type;
00992       typedef typename viennagrid::result_of::const_element_range< element_type, vertex_tag >::type vertex_range;
00993       typedef typename viennagrid::result_of::const_iterator< vertex_range >::type const_vertex_iterator;
00994 
00995 
00996       os << "-- " << element_tag::name() << ", ID: " << el.id() << " --";
00997       const vertex_range & vertices = elements<vertex_tag>(el);
00998       for (const_vertex_iterator vit  = vertices.begin();
00999                           vit != vertices.end();
01000                       ++vit)
01001       os << std::endl << "  " << *vit;
01002 
01003       return os;
01004   }
01005 
01006 }
01007 
01008 
01009 #endif