ViennaGrid - The Vienna Grid Library
2.1.0
|
00001 #ifndef VIENNAGRID_ALGORITHM_VOLUME_HPP 00002 #define VIENNAGRID_ALGORITHM_VOLUME_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 <iostream> 00017 #include <sstream> 00018 #include <string> 00019 #include <stdexcept> 00020 00021 #include "viennagrid/forwards.hpp" 00022 #include "viennagrid/topology/all.hpp" 00023 #include "viennagrid/algorithm/norm.hpp" 00024 #include "viennagrid/algorithm/spanned_volume.hpp" 00025 00026 #include "viennagrid/mesh/mesh.hpp" 00027 #include "viennagrid/accessor.hpp" 00028 00034 namespace viennagrid 00035 { 00036 namespace detail 00037 { 00038 00040 template <typename PointAccessorT, typename ElementT> 00041 typename viennagrid::result_of::coord< typename PointAccessorT::value_type >::type 00042 volume_impl(PointAccessorT const, ElementT const &, viennagrid::vertex_tag) 00043 { 00044 return typename viennagrid::result_of::coord< typename PointAccessorT::value_type >::type(1); 00045 } 00046 00048 template <typename PointAccessorT, typename ElementT> 00049 typename viennagrid::result_of::coord< typename PointAccessorT::value_type >::type 00050 volume_impl(PointAccessorT const accessor, ElementT const & cell, viennagrid::simplex_tag<1>) 00051 { 00052 typedef typename PointAccessorT::value_type PointType; 00053 00054 PointType const & p0 = accessor( vertices(cell)[0] ); 00055 PointType const & p1 = accessor( vertices(cell)[1] ); 00056 00057 return norm(p0 - p1); 00058 } 00059 00061 template <typename PointAccessorT, typename ElementT> 00062 typename viennagrid::result_of::coord< typename PointAccessorT::value_type >::type 00063 volume_impl(PointAccessorT const accessor, ElementT const & cell, viennagrid::hypercube_tag<1>) 00064 { 00065 return volume_impl(accessor, cell, viennagrid::simplex_tag<1>()); 00066 } 00067 00068 //topologically two-dimensional elements 00070 template <typename PointAccessorT, typename ElementT> 00071 typename viennagrid::result_of::coord< typename PointAccessorT::value_type >::type 00072 volume_impl(PointAccessorT const accessor, ElementT const & cell, viennagrid::triangle_tag) 00073 { 00074 typedef typename PointAccessorT::value_type PointType; 00075 00076 PointType const & p0 = accessor( vertices(cell)[0] ); 00077 PointType const & p1 = accessor( vertices(cell)[1] ); 00078 PointType const & p2 = accessor( vertices(cell)[2] ); 00079 00080 return spanned_volume(p0, p1, p2); 00081 } 00082 00084 template <typename PointAccessorT, typename ElementT> 00085 typename viennagrid::result_of::coord< typename PointAccessorT::value_type >::type 00086 volume_impl(PointAccessorT const accessor, ElementT const & cell, viennagrid::quadrilateral_tag) 00087 { 00088 typedef typename PointAccessorT::value_type PointType; 00089 00090 PointType const & p0 = accessor( vertices(cell)[0] ); 00091 PointType const & p1 = accessor( vertices(cell)[1] ); 00092 PointType const & p2 = accessor( vertices(cell)[2] ); 00093 PointType const & p3 = accessor( vertices(cell)[3] ); 00094 00095 return spanned_volume(p0, p1, p3) + spanned_volume(p1, p2, p3); //sum up the two triangular parts 00096 } 00097 00098 00100 template <typename PointAccessorT, typename ElementT> 00101 typename viennagrid::result_of::coord< typename PointAccessorT::value_type >::type 00102 volume_impl(PointAccessorT const accessor, ElementT const & cell, viennagrid::polygon_tag) 00103 { 00104 typedef typename PointAccessorT::value_type PointType; 00105 typedef typename viennagrid::result_of::coord< PointType >::type NumericType; 00106 typedef typename viennagrid::result_of::const_element_range<ElementT, vertex_tag>::type VertexOnCellContainer; 00107 typedef typename viennagrid::result_of::iterator<VertexOnCellContainer>::type VertexOnCellIterator; 00108 00109 00110 VertexOnCellContainer range( cell ); 00111 if (range.size() < 3) return 0; 00112 VertexOnCellIterator it1 = range.begin(); 00113 VertexOnCellIterator it2 = it1; ++it2; 00114 00115 PointType origin = it1->point(); 00116 00117 NumericType volume = 0; 00118 00119 for (; it2 != range.end(); ++it1, ++it2) 00120 volume += signed_spanned_volume(origin, accessor(*it1), accessor(*it2)); 00121 00122 00123 it1 = range.end(); --it1; 00124 volume += signed_spanned_volume( origin, accessor(*it1), accessor(*range.begin()) ); 00125 00126 return std::abs(volume); 00127 } 00128 00129 00130 //topologically three-dimensional elements 00132 template <typename PointAccessorT, typename ElementT> 00133 typename viennagrid::result_of::coord< typename PointAccessorT::value_type >::type 00134 volume_impl(PointAccessorT const accessor, ElementT const & cell, viennagrid::tetrahedron_tag) 00135 { 00136 typedef typename PointAccessorT::value_type PointType; 00137 00138 PointType const & p0 = accessor( vertices(cell)[0] ); 00139 PointType const & p1 = accessor( vertices(cell)[1] ); 00140 PointType const & p2 = accessor( vertices(cell)[2] ); 00141 PointType const & p3 = accessor( vertices(cell)[3] ); 00142 00143 return spanned_volume(p0, p1, p2, p3); 00144 } 00145 00146 00148 template <typename PointAccessorT, typename ElementT> 00149 typename viennagrid::result_of::coord< typename PointAccessorT::value_type >::type 00150 volume_impl(PointAccessorT const accessor, ElementT const & cell, viennagrid::hexahedron_tag) 00151 { 00152 typedef typename PointAccessorT::value_type PointType; 00153 00154 PointType const & p0 = accessor( vertices(cell)[0] ); 00155 PointType const & p1 = accessor( vertices(cell)[1] ); 00156 PointType const & p2 = accessor( vertices(cell)[2] ); 00157 PointType const & p3 = accessor( vertices(cell)[3] ); 00158 PointType const & p4 = accessor( vertices(cell)[4] ); 00159 PointType const & p5 = accessor( vertices(cell)[5] ); 00160 PointType const & p6 = accessor( vertices(cell)[6] ); 00161 PointType const & p7 = accessor( vertices(cell)[7] ); 00162 00163 //decompose hexahedron into six tetrahedra 00164 return spanned_volume(p0, p1, p3, p4) 00165 + spanned_volume(p4, p1, p3, p7) 00166 + spanned_volume(p4, p1, p7, p5) 00167 + spanned_volume(p1, p2, p3, p7) 00168 + spanned_volume(p1, p2, p7, p5) 00169 + spanned_volume(p5, p2, p7, p6); 00170 } 00171 00172 00173 // 00175 template <typename ElementTOrTag, typename MeshSegmentHandleType> 00176 typename viennagrid::result_of::coord< MeshSegmentHandleType >::type 00177 volume_mesh(MeshSegmentHandleType const & mesh_obj) 00178 { 00179 typedef typename viennagrid::result_of::const_element_range<MeshSegmentHandleType, ElementTOrTag>::type CellContainer; 00180 typedef typename viennagrid::result_of::iterator<CellContainer>::type CellIterator; 00181 00182 typename viennagrid::result_of::coord< MeshSegmentHandleType >::type new_volume = 0; 00183 CellContainer new_cells = viennagrid::elements<ElementTOrTag>(mesh_obj); 00184 for (CellIterator new_cit = new_cells.begin(); 00185 new_cit != new_cells.end(); 00186 ++new_cit) 00187 { 00188 new_volume += volume( default_point_accessor(mesh_obj), *new_cit); 00189 } 00190 return new_volume; 00191 } 00192 } //namespace detail 00193 00194 // 00195 // The public interface functions 00196 // 00198 template <typename PointAccessorT, typename ElementT> 00199 typename viennagrid::result_of::coord< typename PointAccessorT::value_type >::type 00200 volume(PointAccessorT const accessor, ElementT const & cell) 00201 { 00202 return detail::volume_impl( accessor, cell, typename ElementT::tag() ); 00203 } 00204 00206 template <typename ElementTag, typename WrappedConfigT> 00207 typename viennagrid::result_of::coord< viennagrid::element<ElementTag, WrappedConfigT> >::type 00208 volume(viennagrid::element<ElementTag, WrappedConfigT> const & cell) 00209 { 00210 return volume( default_point_accessor(cell), cell ); 00211 } 00212 00213 00215 template<typename ElementTOrTag, typename WrappedConfigT> 00216 typename viennagrid::result_of::coord< mesh<WrappedConfigT> >::type 00217 volume(mesh<WrappedConfigT> const & mesh_obj) 00218 { 00219 return detail::volume_mesh<ElementTOrTag>(mesh_obj); 00220 } 00221 00222 // default Element Tag = Cell Tag 00224 template<typename MeshSegmentHandleType> 00225 typename viennagrid::result_of::coord< MeshSegmentHandleType >::type 00226 volume(MeshSegmentHandleType const & mesh_obj) 00227 { 00228 return detail::volume_mesh< typename viennagrid::result_of::cell_tag< MeshSegmentHandleType >::type >(mesh_obj); 00229 } 00230 00231 00232 } //namespace viennagrid 00233 #endif