ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/mesh/neighbor_iteration.hpp
Go to the documentation of this file.
00001 #ifndef VIENNAGRID_MESH_NEIGHBOR_ITERATION_HPP
00002 #define VIENNAGRID_MESH_NEIGHBOR_ITERATION_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 #include "viennagrid/mesh/segmentation.hpp"
00017 #include "viennagrid/mesh/coboundary_iteration.hpp"
00018 
00022 #include "../forwards.hpp"
00023 
00024 namespace viennagrid
00025 {
00026   namespace result_of
00027   {
00028     template<typename MeshOrSegmentHandleT, typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT>
00029     struct neighbor_range;
00030 
00031     template<typename MeshOrSegmentHandleT, typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT>
00032     struct const_neighbor_range;
00033   }
00034 
00035   template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename WrappedConfigT, typename ElementOrHandleT>
00036   typename result_of::neighbor_range<viennagrid::mesh<WrappedConfigT>, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type
00037   neighbor_elements(viennagrid::mesh<WrappedConfigT> & mesh_obj, ElementOrHandleT const & element_or_handle);
00038 
00039   template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename WrappedConfigT, typename ElementOrHandleT>
00040   typename result_of::const_neighbor_range<viennagrid::mesh<WrappedConfigT>, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type
00041   neighbor_elements(viennagrid::mesh<WrappedConfigT> const & mesh_obj, ElementOrHandleT const & element_or_handle);
00042 
00043   template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename SegmentationT, typename ElementOrHandleT>
00044   typename result_of::neighbor_range<segment_handle<SegmentationT>, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type
00045   neighbor_elements(segment_handle<SegmentationT> & segment, ElementOrHandleT const & element_or_handle);
00046 
00047   template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename SegmentationT, typename ElementOrHandleT>
00048   typename result_of::const_neighbor_range<segment_handle<SegmentationT>, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type
00049   neighbor_elements(segment_handle<SegmentationT> const & segment, ElementOrHandleT const & element_or_handle);
00050 
00051 
00052 
00053   namespace detail
00054   {
00055     template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename ContainerT>
00056     class neighbor_range_wrapper : public container_range_wrapper<ContainerT>
00057     {
00058     public:
00059       neighbor_range_wrapper(ContainerT & container) : container_range_wrapper<ContainerT>(&container) {}
00060       neighbor_range_wrapper(container_range_wrapper<ContainerT> const & base) : container_range_wrapper<ContainerT>(base) {}
00061 
00062       template<typename WrappedConfigT, typename ElementOrHandleT>
00063       neighbor_range_wrapper(viennagrid::mesh<WrappedConfigT> & mesh_obj,
00064                              ElementOrHandleT const & element_or_handle) : container_range_wrapper<ContainerT>(viennagrid::neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>(mesh_obj, element_or_handle)) {}
00065 
00066       template<typename SegmentationT, typename ElementOrHandleT>
00067       neighbor_range_wrapper(viennagrid::segment_handle<SegmentationT> & segment_obj,
00068                              ElementOrHandleT const & element_or_handle) : container_range_wrapper<ContainerT>(viennagrid::neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>(segment_obj, element_or_handle)) {}
00069 
00070 
00071       template<typename WrappedConfigT, typename ElementTagT, typename WrappedElementConfigT>
00072       neighbor_range_wrapper(viennagrid::mesh<WrappedConfigT> & mesh_obj,
00073                              viennagrid::element<ElementTagT, WrappedElementConfigT> & el) : container_range_wrapper<ContainerT>(viennagrid::neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>(mesh_obj, viennagrid::handle(mesh_obj, el))) {}
00074 
00075       template<typename SegmentationT, typename ElementTagT, typename WrappedElementConfigT>
00076       neighbor_range_wrapper(viennagrid::segment_handle<SegmentationT> & segment_obj,
00077                              viennagrid::element<ElementTagT, WrappedElementConfigT> & el) : container_range_wrapper<ContainerT>(viennagrid::neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>(segment_obj, viennagrid::handle(segment_obj, el))) {}
00078     };
00079 
00080     template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename ContainerT>
00081     class neighbor_range_wrapper<ElementTypeOrTagT, ConnectorElementTypeOrTagT, const ContainerT> : public container_range_wrapper<const ContainerT>
00082     {
00083     public:
00084       neighbor_range_wrapper(ContainerT const & container) : container_range_wrapper<const ContainerT>(&container) {}
00085       neighbor_range_wrapper(container_range_wrapper<const ContainerT> const & base) : container_range_wrapper<const ContainerT>(base) {}
00086 
00087       template<typename WrappedConfigT, typename ElementOrHandleT>
00088       neighbor_range_wrapper(viennagrid::mesh<WrappedConfigT> const & mesh_obj,
00089                              ElementOrHandleT const & element_or_handle) : container_range_wrapper<const ContainerT>(viennagrid::neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>(mesh_obj, element_or_handle)) {}
00090 
00091       template<typename SegmentationT, typename ElementOrHandleT>
00092       neighbor_range_wrapper(viennagrid::segment_handle<SegmentationT> const & segment_obj,
00093                              ElementOrHandleT const & element_or_handle) : container_range_wrapper<const ContainerT>(viennagrid::neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>(segment_obj, element_or_handle)) {}
00094 
00095 
00096       template<typename WrappedConfigT, typename ElementTagT, typename WrappedElementConfigT>
00097       neighbor_range_wrapper(viennagrid::mesh<WrappedConfigT> const & mesh_obj,
00098                              viennagrid::element<ElementTagT, WrappedElementConfigT> const & el) : container_range_wrapper<const ContainerT>(viennagrid::neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>(mesh_obj, viennagrid::handle(mesh_obj, el))) {}
00099 
00100       template<typename SegmentationT, typename ElementTagT, typename WrappedElementConfigT>
00101       neighbor_range_wrapper(viennagrid::segment_handle<SegmentationT> const & segment_obj,
00102                              viennagrid::element<ElementTagT, WrappedElementConfigT> const & el) : container_range_wrapper<const ContainerT>(viennagrid::neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>(segment_obj, viennagrid::handle(segment_obj, el))) {}
00103     };
00104   }
00105 
00106 
00107 
00108   namespace result_of
00109   {
00111     template<typename mesh_type, typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT>
00112     struct neighbor_view
00113     {
00114       typedef typename viennagrid::result_of::element_tag< ElementTypeOrTagT >::type element_tag;
00115       typedef typename viennagrid::result_of::element_tag< ConnectorElementTypeOrTagT >::type connector_element_tag;
00116 
00117       typedef typename viennagrid::detail::result_of::lookup<
00118           typename viennagrid::detail::result_of::lookup<
00119               typename mesh_type::appendix_type,
00120               neighbor_collection_tag
00121             >::type,
00122           viennagrid::static_pair<element_tag, connector_element_tag>
00123         >::type::container_type::value_type type;
00124     };
00125 
00126     template<typename SegmentationT, typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT>
00127     struct neighbor_view< viennagrid::segment_handle<SegmentationT>, ElementTypeOrTagT, ConnectorElementTypeOrTagT >
00128     {
00129       typedef typename neighbor_view< typename viennagrid::segment_handle<SegmentationT>::view_type, ElementTypeOrTagT, ConnectorElementTypeOrTagT >::type type;
00130     };
00140     template<typename MeshOrSegmentHandleT, typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT>
00141     struct neighbor_range
00142     {
00143 //       typedef viennagrid::detail::container_range_wrapper< typename neighbor_view<MeshOrSegmentHandleT, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type > type;
00144       typedef viennagrid::detail::neighbor_range_wrapper< ElementTypeOrTagT, ConnectorElementTypeOrTagT, typename neighbor_view<MeshOrSegmentHandleT, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type > type;
00145     };
00146 
00153     template<typename MeshOrSegmentHandleT, typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT>
00154     struct const_neighbor_range
00155     {
00156 //       typedef viennagrid::detail::container_range_wrapper< const typename neighbor_view<MeshOrSegmentHandleT, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type > type;
00157       typedef viennagrid::detail::neighbor_range_wrapper< ElementTypeOrTagT, ConnectorElementTypeOrTagT, const typename neighbor_view<MeshOrSegmentHandleT, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type > type;
00158     };
00159 
00161     template<typename MeshOrSegmentHandleT, typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT>
00162     struct neighbor_range<const MeshOrSegmentHandleT, ElementTypeOrTagT, ConnectorElementTypeOrTagT>
00163     {
00164       typedef typename const_neighbor_range<MeshOrSegmentHandleT, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type type;
00165     };
00168   }
00169 
00170 
00171   namespace detail
00172   {
00173 
00175     template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename mesh_type, typename neigbour_accessor_type>
00176     void create_neighbor_information(mesh_type & mesh_obj, neigbour_accessor_type accessor)
00177     {
00178       typedef typename viennagrid::result_of::element_tag< ElementTypeOrTagT >::type          element_tag;
00179       typedef typename viennagrid::result_of::element_tag< ConnectorElementTypeOrTagT >::type connector_element_tag;
00180 
00181       typedef typename viennagrid::result_of::element< mesh_type, ElementTypeOrTagT >::type   element_type;
00182 
00183       typedef typename viennagrid::result_of::element_range< mesh_type, ElementTypeOrTagT >::type element_range_type;
00184       typedef typename viennagrid::result_of::iterator< element_range_type >::type                element_range_iterator;
00185 
00186       element_range_type elements(mesh_obj);
00187 
00188       for ( element_range_iterator it = elements.begin(); it != elements.end(); ++it )
00189       {
00190         accessor( *it ).clear();
00191         accessor( *it ).set_base_container( viennagrid::get< element_type >( element_collection(mesh_obj) ) );
00192       }
00193 
00194       typedef typename viennagrid::result_of::element_range< mesh_type, connector_element_tag >::type     connector_element_range_type;
00195       typedef typename viennagrid::result_of::iterator< connector_element_range_type >::type              connector_element_range_iterator;
00196 
00197       connector_element_range_type connector_elements(mesh_obj);
00198       for ( connector_element_range_iterator it = connector_elements.begin(); it != connector_elements.end(); ++it )
00199       {
00200         typedef typename viennagrid::result_of::coboundary_range< mesh_type, connector_element_tag, element_tag >::type   element_on_connector_element_range_type;
00201         typedef typename viennagrid::result_of::iterator< element_on_connector_element_range_type >::type                 element_on_connector_element_range_iterator;
00202 
00203         element_on_connector_element_range_type coboundary_range = viennagrid::coboundary_elements<connector_element_tag, element_tag>( mesh_obj, it.handle() );
00204         if (coboundary_range.empty())
00205             continue;
00206 
00207         element_on_connector_element_range_iterator jt1 = coboundary_range.begin(); ++jt1;
00208         for (; jt1 != coboundary_range.end(); ++jt1)
00209         {
00210           for (element_on_connector_element_range_iterator jt0 = coboundary_range.begin(); jt0 != jt1; ++jt0)
00211           {
00212             typedef typename viennagrid::result_of::neighbor_view<mesh_type, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type view_type;
00213             view_type & view_obj = accessor( *jt0 );
00214 
00215             typename view_type::iterator kt = view_obj.begin();
00216             for (; kt != view_obj.end(); ++kt)
00217               if ( kt->id() == jt1->id() )
00218                 break;
00219 
00220             if (kt == view_obj.end())
00221             {
00222               accessor( *jt0 ).insert_handle( jt1.handle() );
00223               accessor( *jt1 ).insert_handle( jt0.handle() );
00224             }
00225           }
00226         }
00227       }
00228     }
00229 
00230 
00232     template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename mesh_type>
00233     void create_neighbor_information(mesh_type & mesh_obj)
00234     {
00235       typedef typename viennagrid::result_of::element_tag< ElementTypeOrTagT >::type           element_tag;
00236       typedef typename viennagrid::result_of::element_tag< ConnectorElementTypeOrTagT >::type  connector_element_tag;
00237       typedef typename viennagrid::result_of::element< mesh_type, ElementTypeOrTagT >::type    element_type;
00238 
00239       typedef typename viennagrid::detail::result_of::lookup<
00240               typename viennagrid::detail::result_of::lookup<
00241                   typename mesh_type::appendix_type,
00242                   neighbor_collection_tag
00243               >::type,
00244               viennagrid::static_pair<element_tag, connector_element_tag>
00245               >::type neighbor_container_wrapper_type;
00246       neighbor_container_wrapper_type & neighbor_container_wrapper = detail::neighbor_collection<element_tag, connector_element_tag>(mesh_obj);
00247 
00248       create_neighbor_information<ElementTypeOrTagT, ConnectorElementTypeOrTagT>( mesh_obj, viennagrid::make_accessor<element_type>(neighbor_container_wrapper.container) );
00249 
00250       detail::update_change_counter( mesh_obj, neighbor_container_wrapper.change_counter );
00251     }
00252 
00253 
00254 
00256     template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename neigbour_accessor_type, typename ElementTag, typename WrappedConfigT>
00257     viennagrid::detail::container_range_wrapper<typename neigbour_accessor_type::value_type>
00258     neighbor_elements(neigbour_accessor_type accessor, viennagrid::element<ElementTag, WrappedConfigT> & element)
00259     {
00260       typedef viennagrid::detail::container_range_wrapper<typename neigbour_accessor_type::value_type> range_type;
00261       return range_type( accessor( element ) );
00262     }
00263 
00265     template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename neigbour_accessor_type, typename ElementTag, typename WrappedConfigT>
00266     viennagrid::detail::container_range_wrapper<const typename neigbour_accessor_type::value_type>
00267     neighbor_elements(neigbour_accessor_type const accessor, viennagrid::element<ElementTag, WrappedConfigT> const & element)
00268     {
00269       typedef viennagrid::detail::container_range_wrapper<const typename neigbour_accessor_type::value_type> range_type;
00270       return range_type( accessor( element ) );
00271     }
00272 
00273 
00275     template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename neigbour_accessor_type, typename WrappedConfigT, typename ElementOrHandleT>
00276     viennagrid::detail::container_range_wrapper<typename neigbour_accessor_type::value_type>
00277     neighbor_elements(viennagrid::mesh<WrappedConfigT> & mesh_obj, neigbour_accessor_type accessor, ElementOrHandleT & element_or_handle)
00278     {
00279       return neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>( accessor, viennagrid::dereference_handle(mesh_obj, element_or_handle) );
00280     }
00281 
00283     template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename neigbour_accessor_type, typename WrappedConfigT, typename ElementOrHandleT>
00284     viennagrid::detail::container_range_wrapper<const typename neigbour_accessor_type::value_type>
00285     neighbor_elements(viennagrid::mesh<WrappedConfigT> const & mesh_obj, neigbour_accessor_type const accessor, ElementOrHandleT const & element_or_handle)
00286     {
00287       return neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>( accessor, viennagrid::dereference_handle(mesh_obj, element_or_handle) );
00288     }
00289 
00290   }
00291 
00302   template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename WrappedConfigT, typename ElementOrHandleT>
00303   typename result_of::neighbor_range<viennagrid::mesh<WrappedConfigT>, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type
00304   neighbor_elements(viennagrid::mesh<WrappedConfigT> & mesh_obj, ElementOrHandleT const & element_or_handle)
00305   {
00306     typedef viennagrid::mesh<WrappedConfigT> mesh_type;
00307     typedef typename viennagrid::result_of::element_tag< ElementTypeOrTagT >::type element_tag;
00308     typedef typename viennagrid::result_of::element_tag< ConnectorElementTypeOrTagT >::type connector_element_tag;
00309     typedef typename viennagrid::result_of::element< mesh_type, ElementTypeOrTagT >::type element_type;
00310 
00311     typedef typename viennagrid::detail::result_of::lookup<
00312             typename viennagrid::detail::result_of::lookup<
00313                 typename mesh_type::appendix_type,
00314                 neighbor_collection_tag
00315             >::type,
00316             viennagrid::static_pair<element_tag, connector_element_tag>
00317             >::type neighbor_container_wrapper_type;
00318     neighbor_container_wrapper_type & neighbor_container_wrapper = detail::neighbor_collection<element_tag, connector_element_tag>(mesh_obj);
00319 
00320     if ( detail::is_obsolete( mesh_obj, neighbor_container_wrapper.change_counter ) )
00321       detail::create_neighbor_information<ElementTypeOrTagT, ConnectorElementTypeOrTagT>(mesh_obj);
00322 
00323     return detail::neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>( viennagrid::make_accessor<element_type>(neighbor_container_wrapper.container), viennagrid::dereference_handle(mesh_obj, element_or_handle) );
00324   }
00325 
00336   template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename WrappedConfigT, typename ElementOrHandleT>
00337   typename result_of::const_neighbor_range<viennagrid::mesh<WrappedConfigT>, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type
00338   neighbor_elements(viennagrid::mesh<WrappedConfigT> const & mesh_obj, ElementOrHandleT const & element_or_handle)
00339   {
00340     typedef viennagrid::mesh<WrappedConfigT> mesh_type;
00341     typedef typename viennagrid::result_of::element_tag< ElementTypeOrTagT >::type element_tag;
00342     typedef typename viennagrid::result_of::element_tag< ConnectorElementTypeOrTagT >::type connector_element_tag;
00343     typedef typename viennagrid::result_of::element< mesh_type, ElementTypeOrTagT >::type element_type;
00344 
00345     typedef typename viennagrid::detail::result_of::lookup<
00346             typename viennagrid::detail::result_of::lookup<
00347                 typename mesh_type::appendix_type,
00348                 neighbor_collection_tag
00349             >::type,
00350             viennagrid::static_pair<element_tag, connector_element_tag>
00351             >::type neighbor_container_wrapper_type;
00352     neighbor_container_wrapper_type const & neighbor_container_wrapper = detail::neighbor_collection<element_tag, connector_element_tag>(mesh_obj);
00353 
00354     if ( detail::is_obsolete( mesh_obj, neighbor_container_wrapper.change_counter ) )
00355       detail::create_neighbor_information<ElementTypeOrTagT, ConnectorElementTypeOrTagT>( const_cast<mesh_type&>(mesh_obj) );
00356 
00357 
00358     return detail::neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>( viennagrid::make_accessor<element_type>(neighbor_container_wrapper.container), viennagrid::dereference_handle(mesh_obj, element_or_handle) );
00359   }
00360 
00361 
00372   template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename SegmentationT, typename ElementOrHandleT>
00373   typename result_of::neighbor_range<segment_handle<SegmentationT>, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type
00374   neighbor_elements(segment_handle<SegmentationT> & segment, ElementOrHandleT const & element_or_handle)
00375   {
00376     return neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>( segment.view(), element_or_handle );
00377   }
00378 
00389   template<typename ElementTypeOrTagT, typename ConnectorElementTypeOrTagT, typename SegmentationT, typename ElementOrHandleT>
00390   typename result_of::const_neighbor_range<segment_handle<SegmentationT>, ElementTypeOrTagT, ConnectorElementTypeOrTagT>::type
00391   neighbor_elements(segment_handle<SegmentationT> const & segment, ElementOrHandleT const & element_or_handle)
00392   {
00393     return neighbor_elements<ElementTypeOrTagT, ConnectorElementTypeOrTagT>( segment.view(), element_or_handle );
00394   }
00395 
00396 }
00397 
00398 
00399 #endif