ViennaGrid - The Vienna Grid Library
2.1.0
|
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