ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/algorithm/volume.hpp
Go to the documentation of this file.
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