ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/mesh/coboundary_iteration.hpp
Go to the documentation of this file.
00001 #ifndef VIENNAGRID_MESH_COBOUNDARY_ITERATION_HPP
00002 #define VIENNAGRID_MESH_COBOUNDARY_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/forwards.hpp"
00017 #include "viennagrid/storage/forwards.hpp"
00018 #include "viennagrid/mesh/mesh.hpp"
00019 #include "viennagrid/accessor.hpp"
00020 
00025 namespace viennagrid
00026 {
00027   namespace result_of
00028   {
00029     template<typename MeshOrSegmentHandleT, typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT>
00030     struct coboundary_range;
00031 
00032     template<typename MeshOrSegmentHandleT, typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT>
00033     struct const_coboundary_range;
00034   }
00035 
00036   template<typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT, typename WrappedConfigT, typename ElementOrHandleT>
00037   typename result_of::coboundary_range<viennagrid::mesh<WrappedConfigT>, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type
00038   coboundary_elements(viennagrid::mesh<WrappedConfigT> & mesh_obj, ElementOrHandleT const & element_or_handle);
00039 
00040   template<typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT, typename WrappedConfigT, typename ElementOrHandleT>
00041   typename result_of::const_coboundary_range<viennagrid::mesh<WrappedConfigT>, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type
00042   coboundary_elements(viennagrid::mesh<WrappedConfigT> const & mesh_obj, ElementOrHandleT const & element_or_handle);
00043 
00044   template<typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT, typename SegmentationT, typename element_or_handle_type>
00045   typename result_of::coboundary_range<segment_handle<SegmentationT>, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type
00046   coboundary_elements(segment_handle<SegmentationT> & segment, element_or_handle_type const & element_or_handle);
00047 
00048   template<typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT, typename SegmentationT, typename element_or_handle_type>
00049   typename result_of::const_coboundary_range<segment_handle<SegmentationT>, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type
00050   coboundary_elements(segment_handle<SegmentationT> const & segment, element_or_handle_type const & element_or_handle);
00051 
00052 
00053 
00054 
00055 
00056   namespace detail
00057   {
00058     template<typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT, typename ContainerT>
00059     class coboundary_range_wrapper : public container_range_wrapper<ContainerT>
00060     {
00061     public:
00062       coboundary_range_wrapper(ContainerT & container) : container_range_wrapper<ContainerT>(&container) {}
00063       coboundary_range_wrapper(container_range_wrapper<ContainerT> const & base) : container_range_wrapper<ContainerT>(base) {}
00064 
00065       template<typename WrappedConfigT, typename ElementOrHandleT>
00066       coboundary_range_wrapper(viennagrid::mesh<WrappedConfigT> & mesh_obj,
00067                                ElementOrHandleT const & element_or_handle) : container_range_wrapper<ContainerT>(viennagrid::coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>(mesh_obj, element_or_handle)) {}
00068 
00069       template<typename SegmentationT, typename ElementOrHandleT>
00070       coboundary_range_wrapper(viennagrid::segment_handle<SegmentationT> & segment_obj,
00071                                ElementOrHandleT const & element_or_handle) : container_range_wrapper<ContainerT>(viennagrid::coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>(segment_obj, element_or_handle)) {}
00072 
00073 
00074       template<typename WrappedConfigT, typename ElementTagT, typename WrappedElementConfigT>
00075       coboundary_range_wrapper(viennagrid::mesh<WrappedConfigT> & mesh_obj,
00076                                viennagrid::element<ElementTagT, WrappedElementConfigT> & element) : container_range_wrapper<ContainerT>(viennagrid::coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>(mesh_obj,  viennagrid::handle(mesh_obj, element))) {}
00077 
00078       template<typename SegmentationT, typename ElementTagT, typename WrappedElementConfigT>
00079       coboundary_range_wrapper(viennagrid::segment_handle<SegmentationT> & segment_obj,
00080                                viennagrid::element<ElementTagT, WrappedElementConfigT> & element) : container_range_wrapper<ContainerT>(viennagrid::coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>(segment_obj, viennagrid::handle(segment_obj, element))) {}
00081     };
00082 
00083     template<typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT, typename ContainerT>
00084     class coboundary_range_wrapper<ElementTypeOrTagT, CoboundaryTypeOrTagT, const ContainerT> : public container_range_wrapper<const ContainerT>
00085     {
00086     public:
00087       coboundary_range_wrapper(ContainerT const & container) : container_range_wrapper<const ContainerT>(&container) {}
00088       coboundary_range_wrapper(container_range_wrapper<const ContainerT> const & base) : container_range_wrapper<const ContainerT>(base) {}
00089 
00090       template<typename WrappedConfigT, typename ElementOrHandleT>
00091       coboundary_range_wrapper(viennagrid::mesh<WrappedConfigT> const & mesh_obj,
00092                                ElementOrHandleT const & element_or_handle) : container_range_wrapper<const ContainerT>(viennagrid::coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>(mesh_obj, element_or_handle)) {}
00093 
00094       template<typename SegmentationT, typename ElementOrHandleT>
00095       coboundary_range_wrapper(viennagrid::segment_handle<SegmentationT> const & segment_obj,
00096                                ElementOrHandleT const & element_or_handle) : container_range_wrapper<const ContainerT>(viennagrid::coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>(segment_obj, element_or_handle)) {}
00097 
00098 
00099       template<typename WrappedConfigT, typename ElementTagT, typename WrappedElementConfigT>
00100       coboundary_range_wrapper(viennagrid::mesh<WrappedConfigT> const & mesh_obj,
00101                                viennagrid::element<ElementTagT, WrappedElementConfigT> const & element) : container_range_wrapper<const ContainerT>(viennagrid::coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>(mesh_obj, viennagrid::handle(mesh_obj, element))) {}
00102 
00103       template<typename SegmentationT, typename ElementTagT, typename WrappedElementConfigT>
00104       coboundary_range_wrapper(viennagrid::segment_handle<SegmentationT> const & segment_obj,
00105                                viennagrid::element<ElementTagT, WrappedElementConfigT> const & element) : container_range_wrapper<const ContainerT>(viennagrid::coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>(segment_obj, viennagrid::handle(segment_obj, element))) {}
00106     };
00107   }
00108 
00109 
00110   namespace result_of
00111   {
00113     template<typename mesh_type, typename element_type_or_tag, typename coboundary_type_or_tag>
00114     struct coboundary_view
00115     {
00116       typedef typename viennagrid::result_of::element_tag< element_type_or_tag >::type element_tag;
00117       typedef typename viennagrid::result_of::element_tag< coboundary_type_or_tag >::type coboundary_tag;
00118 
00119       typedef typename viennagrid::detail::result_of::lookup<
00120           typename viennagrid::detail::result_of::lookup<
00121               typename mesh_type::appendix_type,
00122               coboundary_collection_tag
00123             >::type,
00124           viennagrid::static_pair<element_tag, coboundary_tag>
00125         >::type::container_type::value_type type;
00126     };
00127 
00128     template<typename SegmentationType, typename element_type_or_tag, typename coboundary_type_or_tag>
00129     struct coboundary_view< viennagrid::segment_handle<SegmentationType>, element_type_or_tag, coboundary_type_or_tag >
00130     {
00131       typedef typename coboundary_view< typename viennagrid::segment_handle<SegmentationType>::view_type, element_type_or_tag, coboundary_type_or_tag >::type type;
00132     };
00142     template<typename MeshOrSegmentHandleT, typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT>
00143     struct coboundary_range
00144     {
00145       //typedef viennagrid::detail::container_range_wrapper< typename coboundary_view<MeshOrSegmentHandleT, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type > type;
00146       typedef viennagrid::detail::coboundary_range_wrapper< ElementTypeOrTagT, CoboundaryTypeOrTagT, typename coboundary_view<MeshOrSegmentHandleT, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type > type;
00147     };
00148 
00155     template<typename MeshOrSegmentHandleT, typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT>
00156     struct const_coboundary_range
00157     {
00158 //       typedef viennagrid::detail::container_range_wrapper< const typename coboundary_view<MeshOrSegmentHandleT, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type > type;
00159       typedef viennagrid::detail::coboundary_range_wrapper< ElementTypeOrTagT, CoboundaryTypeOrTagT, const typename coboundary_view<MeshOrSegmentHandleT, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type > type;
00160     };
00161 
00163     template<typename MeshOrSegmentHandleT, typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT>
00164     struct coboundary_range<const MeshOrSegmentHandleT, ElementTypeOrTagT, CoboundaryTypeOrTagT>
00165     {
00166       typedef typename const_coboundary_range<MeshOrSegmentHandleT, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type type;
00167     };
00169   }
00170 
00171   namespace detail
00172   {
00173 
00175     template<typename element_type_or_tag, typename coboundary_type_or_tag, typename MeshT, typename coboundary_accessor_type>
00176     void create_coboundary_information(MeshT & mesh_obj, coboundary_accessor_type accessor)
00177     {
00178       typedef typename viennagrid::result_of::element_tag< element_type_or_tag >::type element_tag;
00179 
00180       typedef typename viennagrid::result_of::element< MeshT, coboundary_type_or_tag >::type coboundary_type;
00181 
00182       typedef typename viennagrid::result_of::element_range< MeshT, element_type_or_tag >::type element_range_type;
00183       typedef typename viennagrid::result_of::iterator< element_range_type >::type element_range_iterator;
00184 
00185       element_range_type elements(mesh_obj);
00186 
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< coboundary_type >( element_collection(mesh_obj) ) );
00192       }
00193 
00194 
00195       typedef typename viennagrid::result_of::element_range< MeshT, coboundary_type_or_tag >::type coboundary_element_range_type;
00196       typedef typename viennagrid::result_of::iterator< coboundary_element_range_type >::type coboundary_element_range_iterator;
00197 
00198       coboundary_element_range_type coboundary_elements(mesh_obj);
00199       for (coboundary_element_range_iterator it = coboundary_elements.begin(); it != coboundary_elements.end(); ++it)
00200       {
00201         typedef typename viennagrid::result_of::element_range< coboundary_type, element_tag >::type element_on_coboundary_element_range_type;
00202         typedef typename viennagrid::result_of::iterator< element_on_coboundary_element_range_type >::type element_on_coboundary_element_range_iterator;
00203 
00204         element_on_coboundary_element_range_type elements_on_coboundary_element( *it );
00205         for (element_on_coboundary_element_range_iterator jt = elements_on_coboundary_element.begin(); jt != elements_on_coboundary_element.end(); ++jt)
00206           accessor.at( *jt ).insert_handle( it.handle() );
00207       }
00208     }
00209 
00210     template<typename element_type_or_tag, typename coboundary_type_or_tag, typename WrappedConfigT, typename ElementTypelistT, typename ContainerConfigT, typename coboundary_accessor_type>
00211     void create_coboundary_information(viennagrid::mesh< viennagrid::detail::decorated_mesh_view_config<WrappedConfigT, ElementTypelistT, ContainerConfigT> > & mesh_obj, coboundary_accessor_type accessor)
00212     {
00213       typedef viennagrid::mesh< viennagrid::detail::decorated_mesh_view_config<WrappedConfigT, ElementTypelistT, ContainerConfigT> > ViewType;
00214       typedef typename viennagrid::result_of::element_tag< element_type_or_tag >::type element_tag;
00215 
00216       typedef typename viennagrid::result_of::element< ViewType, coboundary_type_or_tag >::type coboundary_type;
00217 
00218       typedef typename viennagrid::result_of::element_range< ViewType, element_type_or_tag >::type element_range_type;
00219       typedef typename viennagrid::result_of::iterator< element_range_type >::type element_range_iterator;
00220 
00221       element_range_type elements(mesh_obj);
00222 
00223 
00224       for ( element_range_iterator it = elements.begin(); it != elements.end(); ++it )
00225       {
00226         accessor( *it ).clear();
00227         accessor( *it ).set_base_container( viennagrid::get< coboundary_type >( element_collection(mesh_obj) ) );
00228       }
00229 
00230 
00231       typedef typename viennagrid::result_of::element_range< ViewType, coboundary_type_or_tag >::type coboundary_element_range_type;
00232       typedef typename viennagrid::result_of::iterator< coboundary_element_range_type >::type coboundary_element_range_iterator;
00233 
00234       coboundary_element_range_type coboundary_elements(mesh_obj);
00235       for (coboundary_element_range_iterator it = coboundary_elements.begin(); it != coboundary_elements.end(); ++it)
00236       {
00237         typedef typename viennagrid::result_of::element_range< coboundary_type, element_tag >::type element_on_coboundary_element_range_type;
00238         typedef typename viennagrid::result_of::iterator< element_on_coboundary_element_range_type >::type element_on_coboundary_element_range_iterator;
00239 
00240         element_on_coboundary_element_range_type elements_on_coboundary_element( *it );
00241         for (element_on_coboundary_element_range_iterator jt = elements_on_coboundary_element.begin(); jt != elements_on_coboundary_element.end(); ++jt)
00242         {
00243 //           is this line needed??
00244 //           if ( viennagrid::find(mesh_obj, *jt) !=  viennagrid::elements<element_type_or_tag>(mesh_obj).end() )
00245           accessor.at( *jt ).insert_handle( it.handle() );
00246         }
00247       }
00248     }
00249 
00250 
00251 
00252 
00253 
00255     template<typename element_type_or_tag, typename coboundary_type_or_tag, typename mesh_type>
00256     void create_coboundary_information(mesh_type & mesh_obj)
00257     {
00258         typedef typename viennagrid::result_of::element_tag< element_type_or_tag >::type element_tag;
00259         typedef typename viennagrid::result_of::element_tag< coboundary_type_or_tag >::type coboundary_tag;
00260         typedef typename viennagrid::result_of::element< mesh_type, element_type_or_tag >::type element_type;
00261 
00262         typedef typename viennagrid::detail::result_of::lookup<
00263                 typename viennagrid::detail::result_of::lookup<
00264                     typename mesh_type::appendix_type,
00265                     coboundary_collection_tag
00266                 >::type,
00267                 viennagrid::static_pair<element_tag, coboundary_tag>
00268                 >::type coboundary_container_wrapper_type;
00269 
00270         coboundary_container_wrapper_type & coboundary_container_wrapper = detail::coboundary_collection<element_tag, coboundary_tag>(mesh_obj);//viennagrid::storage::detail::get< viennagrid::static_pair<element_tag, coboundary_tag> > ( mesh_obj.coboundary_collection() );
00271 
00272         create_coboundary_information<element_type_or_tag, coboundary_type_or_tag>( mesh_obj, viennagrid::make_accessor<element_type>(coboundary_container_wrapper.container) );
00273         detail::update_change_counter( mesh_obj, coboundary_container_wrapper.change_counter );
00274     }
00275 
00276 
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00287     template<typename ElementTypeOrTagT, typename coboundary_type_or_tag, typename coboundary_accessor_type, typename ElementTag, typename WrappedConfigType>
00288     viennagrid::detail::container_range_wrapper<typename coboundary_accessor_type::value_type>
00289     coboundary_elements(coboundary_accessor_type accessor, viennagrid::element<ElementTag, WrappedConfigType> & element)
00290     {
00291       typedef viennagrid::detail::container_range_wrapper<typename coboundary_accessor_type::value_type> range_type;
00292       return range_type( accessor( element ) );
00293     }
00294 
00296     template<typename ElementTypeOrTagT, typename coboundary_type_or_tag, typename coboundary_accessor_type, typename ElementTag, typename WrappedConfigType>
00297     viennagrid::detail::container_range_wrapper<const typename coboundary_accessor_type::value_type>
00298     coboundary_elements(coboundary_accessor_type const accessor, viennagrid::element<ElementTag, WrappedConfigType> const & element)
00299     {
00300       typedef viennagrid::detail::container_range_wrapper<const typename coboundary_accessor_type::value_type> range_type;
00301       return range_type( accessor( element ) );
00302     }
00303 
00304 
00306     template<typename element_type_or_tag, typename coboundary_type_or_tag, typename coboundary_accessor_type, typename WrappedConfigType, typename element_or_handle_type>
00307     viennagrid::detail::container_range_wrapper<typename coboundary_accessor_type::value_type>
00308     coboundary_elements(viennagrid::mesh<WrappedConfigType> & mesh_obj, coboundary_accessor_type accessor, element_or_handle_type & hendl)
00309     {
00310       return coboundary_elements<element_type_or_tag, coboundary_type_or_tag>( accessor, viennagrid::dereference_handle(mesh_obj, hendl) );
00311     }
00312 
00314     template<typename element_type_or_tag, typename coboundary_type_or_tag, typename coboundary_accessor_type, typename WrappedConfigType, typename element_or_handle_type>
00315     viennagrid::detail::container_range_wrapper<const typename coboundary_accessor_type::value_type>
00316     coboundary_elements(viennagrid::mesh<WrappedConfigType> const & mesh_obj, coboundary_accessor_type const accessor, element_or_handle_type const & hendl)
00317     {
00318       return coboundary_elements<element_type_or_tag, coboundary_type_or_tag>( accessor, viennagrid::dereference_handle(mesh_obj, hendl) );
00319     }
00320 
00321   }
00322 
00323 
00324 
00335   template<typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT, typename WrappedConfigT, typename ElementOrHandleT>
00336   typename result_of::coboundary_range<viennagrid::mesh<WrappedConfigT>, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type
00337   coboundary_elements(viennagrid::mesh<WrappedConfigT> & mesh_obj, ElementOrHandleT const & element_or_handle)
00338   {
00339     typedef viennagrid::mesh<WrappedConfigT> mesh_type;
00340     typedef typename viennagrid::result_of::element_tag< ElementTypeOrTagT >::type element_tag;
00341     typedef typename viennagrid::result_of::element_tag< CoboundaryTypeOrTagT >::type coboundary_tag;
00342     typedef typename viennagrid::result_of::element< mesh_type, ElementTypeOrTagT >::type element_type;
00343 
00344     typedef typename viennagrid::detail::result_of::lookup<
00345             typename viennagrid::detail::result_of::lookup<
00346                 typename mesh_type::appendix_type,
00347                 coboundary_collection_tag
00348             >::type,
00349             viennagrid::static_pair<element_tag, coboundary_tag>
00350             >::type coboundary_container_wrapper_type;
00351     coboundary_container_wrapper_type & coboundary_container_wrapper = detail::coboundary_collection<element_tag, coboundary_tag>(mesh_obj);
00352 
00353     if ( detail::is_obsolete(mesh_obj, coboundary_container_wrapper.change_counter) )
00354       detail::create_coboundary_information<ElementTypeOrTagT, CoboundaryTypeOrTagT>(mesh_obj);
00355 
00356     return detail::coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>( viennagrid::make_accessor<element_type>(coboundary_container_wrapper.container), viennagrid::dereference_handle(mesh_obj, element_or_handle) );
00357   }
00358 
00369   template<typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT, typename WrappedConfigT, typename ElementOrHandleT>
00370   typename result_of::const_coboundary_range<viennagrid::mesh<WrappedConfigT>, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type
00371   coboundary_elements(viennagrid::mesh<WrappedConfigT> const & mesh_obj, ElementOrHandleT const & element_or_handle)
00372   {
00373     typedef viennagrid::mesh<WrappedConfigT> mesh_type;
00374     typedef typename viennagrid::result_of::element_tag< ElementTypeOrTagT >::type element_tag;
00375     typedef typename viennagrid::result_of::element_tag< CoboundaryTypeOrTagT >::type coboundary_tag;
00376     typedef typename viennagrid::result_of::element< mesh_type, ElementTypeOrTagT >::type element_type;
00377 
00378     typedef typename viennagrid::detail::result_of::lookup<
00379             typename viennagrid::detail::result_of::lookup<
00380                 typename mesh_type::appendix_type,
00381                 coboundary_collection_tag
00382             >::type,
00383             viennagrid::static_pair<element_tag, coboundary_tag>
00384             >::type coboundary_container_wrapper_type;
00385     coboundary_container_wrapper_type const & coboundary_container_wrapper = detail::coboundary_collection<element_tag, coboundary_tag>(mesh_obj);
00386 
00387     if ( detail::is_obsolete(mesh_obj, coboundary_container_wrapper.change_counter) )
00388       detail::create_coboundary_information<ElementTypeOrTagT, CoboundaryTypeOrTagT>( const_cast<mesh_type&>(mesh_obj) );
00389 
00390     return detail::coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>( viennagrid::make_accessor<element_type>(coboundary_container_wrapper.container), viennagrid::dereference_handle(mesh_obj, element_or_handle) );
00391   }
00392 
00393 
00394 
00405   template<typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT, typename SegmentationT, typename element_or_handle_type>
00406   typename result_of::coboundary_range<segment_handle<SegmentationT>, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type
00407   coboundary_elements(segment_handle<SegmentationT> & segment, element_or_handle_type const & element_or_handle)
00408   {
00409     return coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>( segment.view(), element_or_handle );
00410   }
00411 
00422   template<typename ElementTypeOrTagT, typename CoboundaryTypeOrTagT, typename SegmentationT, typename element_or_handle_type>
00423   typename result_of::const_coboundary_range<segment_handle<SegmentationT>, ElementTypeOrTagT, CoboundaryTypeOrTagT>::type
00424   coboundary_elements(segment_handle<SegmentationT> const & segment, element_or_handle_type const & element_or_handle)
00425   {
00426     return coboundary_elements<ElementTypeOrTagT, CoboundaryTypeOrTagT>( segment.view(), element_or_handle );
00427   }
00428 
00429 }
00430 
00431 #endif