ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/algorithm/quantity_transfer.hpp
Go to the documentation of this file.
00001 #ifndef VIENNAGRID_ALGORITHM_QUANTITY_TRANSFER_HPP
00002 #define VIENNAGRID_ALGORITHM_QUANTITY_TRANSFER_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 <vector>
00017 #include "viennagrid/forwards.hpp"
00018 #include "viennagrid/mesh/mesh.hpp"
00019 
00024 namespace viennagrid
00025 {
00026   namespace detail
00027   {
00029     struct boundary_quantity_transfer_tag {};
00030 
00032     struct coboundary_quantity_transfer_tag {};
00033 
00034     template <typename SourceTag, typename DestinationTag,
00035               bool less_than = (SourceTag::dim < DestinationTag::dim),
00036               bool larger_than = (SourceTag::dim > DestinationTag::dim)>
00037     struct quantity_transfer_dispatcher {};
00038 
00039     template <typename SourceTag, typename DestinationTag>
00040     struct quantity_transfer_dispatcher<SourceTag, DestinationTag, false, true>
00041     {
00042       typedef boundary_quantity_transfer_tag  type;
00043     };
00044 
00045     template <typename SourceTag, typename DestinationTag>
00046     struct quantity_transfer_dispatcher<SourceTag, DestinationTag, true, false>
00047     {
00048       typedef coboundary_quantity_transfer_tag  type;
00049     };
00050 
00051 
00052     // Implementation for boundary transfer
00053     template <typename SourceTag,      typename DestinationTag,
00054               typename MeshOrSegmentT, typename SourceAccessorT, typename DestinationSetterT,
00055               typename AveragerT,      typename SourceFilterT,   typename DestinationFilterT>
00056     void quantity_transfer(MeshOrSegmentT const & mesh_or_segment, SourceAccessorT const & accessor_src, DestinationSetterT & setter_dest,
00057                            AveragerT const & averager, SourceFilterT const & filter_src, DestinationFilterT const & filter_dest,
00058                            boundary_quantity_transfer_tag)
00059     {
00060       typedef typename viennagrid::result_of::element<MeshOrSegmentT, SourceTag>::type              SourceElementType;
00061       typedef typename viennagrid::result_of::element<MeshOrSegmentT, DestinationTag>::type         DestElementType;
00062 
00063       typedef typename viennagrid::result_of::const_element_range<MeshOrSegmentT, SourceTag>::type  SourceContainer;
00064       typedef typename viennagrid::result_of::iterator<SourceContainer>::type                       SourceIterator;
00065 
00066       typedef typename viennagrid::result_of::const_element_range<SourceElementType, DestinationTag>::type  DestOnSrcContainer;
00067       typedef typename viennagrid::result_of::iterator<DestOnSrcContainer>::type                            DestOnSrcIterator;
00068 
00069       typedef typename SourceAccessorT::value_type              value_type;
00070 
00071       typedef std::map<DestElementType const *, std::vector<value_type> >                     DestinationValueMap;  //Think about adding customization options for std::vector<double>
00072 
00073       SourceContainer source_cells(mesh_or_segment);
00074 
00075       DestinationValueMap  values_for_destination_cells;
00076 
00077       // Step 1: Push all values from source cells to their destination boundary.
00078       //         Note that a coboundary-iteration over destination cells has a higher memory footprint, thus this lightweight-variant using only boundary-iterations is used
00079       for (SourceIterator sit = source_cells.begin();
00080                           sit != source_cells.end(); ++sit)
00081       {
00082         if ( filter_src(*sit) )
00083         {
00084           DestOnSrcContainer dest_on_src(*sit);
00085           for (DestOnSrcIterator dosit  = dest_on_src.begin();
00086                                   dosit != dest_on_src.end();
00087                                 ++dosit)
00088           {
00089             if (filter_dest(*dosit))
00090               values_for_destination_cells[&(*dosit)].push_back(accessor_src(*sit));
00091           }
00092         }
00093       }
00094 
00095       // Step 2: Now average over values on destination cells
00096       for (typename DestinationValueMap::const_iterator dest_values_it  = values_for_destination_cells.begin();
00097                                                         dest_values_it != values_for_destination_cells.end();
00098                                                       ++dest_values_it)
00099       {
00100         setter_dest(*(dest_values_it->first),
00101                     averager(dest_values_it->second));
00102       }
00103     }
00104 
00105     // Implementation for quantity transfer
00106     template <typename SourceTag, typename DestinationTag,
00107               typename MeshOrSegmentT, typename SourceAccessorT, typename DestinationSetterT,
00108               typename AveragerT,      typename SourceFilterT,   typename DestinationFilterT>
00109     void quantity_transfer(MeshOrSegmentT const & mesh_or_segment, SourceAccessorT const & accessor_src, DestinationSetterT       & setter_dest,
00110                            AveragerT      const & averager,        SourceFilterT   const & filter_src,   DestinationFilterT const & filter_dest,
00111                            coboundary_quantity_transfer_tag)
00112     {
00113       typedef typename viennagrid::result_of::element<MeshOrSegmentT, DestinationTag>::type         DestElementType;
00114 
00115       typedef typename viennagrid::result_of::const_element_range<MeshOrSegmentT, DestinationTag>::type DestContainer;
00116       typedef typename viennagrid::result_of::iterator<DestContainer>::type                             DestIterator;
00117 
00118       typedef typename viennagrid::result_of::const_element_range<DestElementType, SourceTag>::type  SrcOnDestContainer;
00119       typedef typename viennagrid::result_of::iterator<SrcOnDestContainer>::type                     SrcOnDestIterator;
00120 
00121       typedef typename SourceAccessorT::value_type              value_type;
00122 
00123       DestContainer dest_cells(mesh_or_segment);
00124 
00125       // Iterate over all dest n-cells, push values from source cell to container, then compute final value
00126       for (DestIterator dit = dest_cells.begin(); dit != dest_cells.end(); ++dit)
00127       {
00128         if ( filter_dest(*dit) )   // only consider destination cells accepted by the filter
00129         {
00130           std::vector<value_type> destination_value_container;
00131 
00132           // Push all values from adjacent source cells to the container
00133           SrcOnDestContainer src_on_dest(*dit);
00134           for (SrcOnDestIterator sodit  = src_on_dest.begin();
00135                                   sodit != src_on_dest.end();
00136                                 ++sodit)
00137           {
00138             if (filter_src(*sodit))
00139               destination_value_container.push_back(accessor_src(*dit));
00140           }
00141 
00142           //
00143           setter_dest(*dit, averager(destination_value_container));
00144         }
00145       }
00146     }
00147 
00148   }
00149 
00163   template <typename SourceTypeOrTag, typename DestinationTypeOrTag,
00164             typename MeshOrSegmentT,  typename SourceAccessorT, typename DestinationSetterT,
00165             typename AveragerT,       typename SourceFilterT,   typename DestinationFilterT>
00166   void quantity_transfer(MeshOrSegmentT const & mesh_or_segment, SourceAccessorT const & accessor_src, DestinationSetterT       & setter_dest,
00167                          AveragerT      const & averager,        SourceFilterT   const & filter_src,   DestinationFilterT const & filter_dest)
00168   {
00169     typedef typename viennagrid::result_of::element_tag<SourceTypeOrTag>::type       SourceTag;
00170     typedef typename viennagrid::result_of::element_tag<DestinationTypeOrTag>::type  DestinationTag;
00171 
00172     detail::quantity_transfer<SourceTag, DestinationTag>(mesh_or_segment, accessor_src, setter_dest,
00173                                                  averager, filter_src, filter_dest,
00174                                                  typename detail::quantity_transfer_dispatcher<SourceTag, DestinationTag>::type());
00175   }
00176 
00177 }
00178 
00179 #endif