Skip to content
Snippets Groups Projects
tnlLaxFridrichs_impl.h 24.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • /***************************************************************************
    
                              tnlLaxFridrichs_impl.h  -  description
    
                                 -------------------
        begin                : Mar 1, 2013
        copyright            : (C) 2013 by Tomas Oberhuber
        email                : tomas.oberhuber@fjfi.cvut.cz
     ***************************************************************************/
    
    /***************************************************************************
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     ***************************************************************************/
    
    
    #ifndef TNLLAXFRIDRICHS_IMPL_H_
    #define TNLLAXFRIDRICHS_IMPL_H_
    
    
    template< typename Real,
              typename Device,
    
              typename Index,
    
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >,
    
                     PressureGradient > :: tnlLaxFridrichs()
    
    : regularizeEps( 0.0 ),
      viscosityCoefficient( 1.0 ),
    
       rho. setName( "Lax-Fridrichs:rho" );
       rho_u1. setName( "Lax-Fridrichs:rho_u1" );
       rho_u2. setName( "Lax-Fridrichs:rho_u2" );
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    tnlString tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >,
                               PressureGradient > :: getTypeStatic()
    {
       return tnlString( "tnlLaxFridrichs< " ) +
              tnlGrid< 2, Real, Device, Index, GridGeometry > :: getTypeStatic() + ", " +
              PressureGradient :: getTypeStatic() + " >";
    }
    
    
    template< typename Real,
              typename Device,
    
              typename Index,
    
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  >::bindMesh( const MeshType& mesh )
    
       this -> mesh = &mesh;
    }
    
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    const typename tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  >::MeshType&
       tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  >::getMesh() const
    {
       return * this->mesh;
    }
    
    
    template< typename Real,
              typename Device,
    
              typename Index,
    
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  > :: setRegularization( const RealType& epsilon )
    
    {
       this -> regularizeEps = epsilon;
    }
    
    
    template< typename Real,
              typename Device,
    
              typename Index,
    
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  > :: setViscosityCoefficient( const RealType& v )
    
    {
       this -> viscosityCoefficient = v;
    }
    
    
    template< typename Real,
              typename Device,
    
              typename Index,
    
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    
       template< typename Vector >
    
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  > :: setRho( Vector& rho )
    
       this->rho.bind( rho );
       this->rho.setName( tnlString( "bind Of " ) + rho. getName() );
    
              typename Index,
    
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  > :: setRhoU1( Vector& rho_u1 )
    
       this -> rho_u1. setName( tnlString( "bind Of " ) + rho_u1. getName() );
    
              typename Index,
    
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  > :: setRhoU2( Vector& rho_u2 )
    
       this -> rho_u2. setName( tnlString( "bind Of " ) + rho_u2. getName() );
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
       template< typename Vector >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  > :: setE( Vector& e )
    {
       this->e.bind( e );
       this->e.setName( tnlString( "bind Of " ) + e.getName() );
    }
    
    
    template< typename Real,
              typename Device,
    
              typename Index,
    
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  > :: setPressureGradient( Vector& grad_p )
    
    {
       this -> pressureGradient = &grad_p;
    }
    
    template< typename Real,
              typename Device,
    
              typename Index,
    
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  > :: getExplicitRhs( const IndexType centralVolume,
    
                                                                                                                  RealType& rho_t,
                                                                                                                  RealType& rho_u1_t,
    
                                                                                                                  RealType& rho_u2_t,
                                                                                                                  const RealType& tau ) const
    
    {
       tnlAssert( mesh, cerr << "No mesh has been binded with the Lax-Fridrichs scheme." );
       tnlAssert( pressureGradient, cerr << "No pressure gradient was set in the the Lax-Fridrichs scheme." )
    
       const IndexType& c = centralVolume;
    
       const IndexType e = this -> mesh -> getElementNeighbour( centralVolume,  1,  0 );
       const IndexType w = this -> mesh -> getElementNeighbour( centralVolume, -1,  0 );
       const IndexType n = this -> mesh -> getElementNeighbour( centralVolume,  0,  1 );
       const IndexType s = this -> mesh -> getElementNeighbour( centralVolume,  0, -1 );
    
       const RealType u1_e = rho_u1[ e ] / regularize( rho[ e ] );
       const RealType u1_w = rho_u1[ w ] / regularize( rho[ w ] );
       const RealType u2_n = rho_u2[ n ] / regularize( rho[ n ] );
       const RealType u2_s = rho_u2[ s ] / regularize( rho[ s ] );
    
       const RealType u1_c = rho_u1[ c ] / regularize( rho[ c ] );
       const RealType u1_n = rho_u1[ n ] / regularize( rho[ n ] );
       const RealType u1_s = rho_u1[ s ] / regularize( rho[ s ] );
       const RealType u2_c = rho_u2[ c ] / regularize( rho[ c ] );
       const RealType u2_e = rho_u2[ e ] / regularize( rho[ e ] );
       const RealType u2_w = rho_u2[ w ] / regularize( rho[ w ] );
    
       /****
        * Get the central volume and its neighbours (east, north, west, south) coordinates
        */
    
       CoordinatesType c_coordinates, e_coordinates, n_coordinates, w_coordinates, s_coordinates;
    
       this -> mesh -> getElementCoordinates( c, c_coordinates );
       e_coordinates = n_coordinates = w_coordinates = s_coordinates = c_coordinates;
       e_coordinates. x() ++;
       w_coordinates. x() --;
       n_coordinates. y() ++;
       s_coordinates. y() --;
    
       /****
        * Get the volumes measure
        */
       const RealType mu_D_c = this -> mesh -> getElementMeasure( c_coordinates );
       const RealType mu_D_e = this -> mesh -> getElementMeasure( e_coordinates );
       const RealType mu_D_n = this -> mesh -> getElementMeasure( n_coordinates );
       const RealType mu_D_w = this -> mesh -> getElementMeasure( w_coordinates );
       const RealType mu_D_s = this -> mesh -> getElementMeasure( s_coordinates );
    
       /****
    
       VertexType e_normal, w_normal, n_normal, s_normal;
       this -> mesh -> template getEdgeNormal<  1,  0 >( c_coordinates, e_normal );
       this -> mesh -> template getEdgeNormal< -1,  0 >( c_coordinates, w_normal );
       this -> mesh -> template getEdgeNormal<  0,  1 >( c_coordinates, n_normal );
       this -> mesh -> template getEdgeNormal<  0, -1 >( c_coordinates, s_normal );
    
       const RealType rho_f_e = 0.5 * ( rho_u1[ c ] + rho_u1[ e ] );
       const RealType rho_f_w = 0.5 * ( rho_u1[ c ] + rho_u1[ w ] );
       const RealType rho_f_n = 0.5 * ( rho_u1[ c ] + rho_u1[ n ] );
       const RealType rho_f_s = 0.5 * ( rho_u1[ c ] + rho_u1[ s ] );
       const RealType rho_g_e = 0.5 * ( rho_u2[ c ] + rho_u2[ e ] );
       const RealType rho_g_w = 0.5 * ( rho_u2[ c ] + rho_u2[ w ] );
       const RealType rho_g_n = 0.5 * ( rho_u2[ c ] + rho_u2[ n ] );
       const RealType rho_g_s = 0.5 * ( rho_u2[ c ] + rho_u2[ s ] );
    
       const RealType rho_u1_f_e = 0.5 * ( rho_u1[ c ] * u1_c + rho_u1[ e ] * u1_e );
       const RealType rho_u1_f_w = 0.5 * ( rho_u1[ c ] * u1_c + rho_u1[ w ] * u1_w );
       const RealType rho_u1_f_n = 0.5 * ( rho_u1[ c ] * u1_c + rho_u1[ n ] * u1_n );
       const RealType rho_u1_f_s = 0.5 * ( rho_u1[ c ] * u1_c + rho_u1[ s ] * u1_s );
       const RealType rho_u1_g_e = 0.5 * ( rho_u1[ c ] * u2_c + rho_u1[ e ] * u2_e );
       const RealType rho_u1_g_w = 0.5 * ( rho_u1[ c ] * u2_c + rho_u1[ w ] * u2_w );
       const RealType rho_u1_g_n = 0.5 * ( rho_u1[ c ] * u2_c + rho_u1[ n ] * u2_n );
       const RealType rho_u1_g_s = 0.5 * ( rho_u1[ c ] * u2_c + rho_u1[ s ] * u2_s );
    
       const RealType rho_u2_f_e = 0.5 * ( rho_u2[ c ] * u1_c + rho_u2[ e ] * u1_e );
       const RealType rho_u2_f_w = 0.5 * ( rho_u2[ c ] * u1_c + rho_u2[ w ] * u1_w );
       const RealType rho_u2_f_n = 0.5 * ( rho_u2[ c ] * u1_c + rho_u2[ n ] * u1_n );
       const RealType rho_u2_f_s = 0.5 * ( rho_u2[ c ] * u1_c + rho_u2[ s ] * u1_s );
       const RealType rho_u2_g_e = 0.5 * ( rho_u2[ c ] * u2_c + rho_u2[ e ] * u2_e );
       const RealType rho_u2_g_w = 0.5 * ( rho_u2[ c ] * u2_c + rho_u2[ w ] * u2_w );
       const RealType rho_u2_g_n = 0.5 * ( rho_u2[ c ] * u2_c + rho_u2[ n ] * u2_n );
       const RealType rho_u2_g_s = 0.5 * ( rho_u2[ c ] * u2_c + rho_u2[ s ] * u2_s );
    
    
       /****
        * Compute the pressure gradient
        */
       VertexType grad_p;
       pressureGradient -> getGradient( c, grad_p );
    
    
       /****
        * rho_t + ( rho u_1 )_x + ( rho u_2 )_y =  0
        */
    
       rho_t = - 1.0 / mu_D_c * ( rho_f_e * e_normal. x() + rho_g_e * e_normal. y() +
                                  rho_f_n * n_normal. x() + rho_g_n * n_normal. y() +
                                  rho_f_w * w_normal. x() + rho_g_w * w_normal. y() +
                                  rho_f_s * s_normal. x() + rho_g_s * s_normal. y() )
    
               + this -> viscosityCoefficient * 1.0 / ( 8.0 * tau ) * mu_D_c *
    
                                ( ( mu_D_c + mu_D_e ) * ( rho[ e ] - rho[ c ] ) +
                                  ( mu_D_c + mu_D_n ) * ( rho[ n ] - rho[ c ] ) +
                                  ( mu_D_c + mu_D_w ) * ( rho[ w ] - rho[ c ] ) +
                                  ( mu_D_c + mu_D_s ) * ( rho[ s ] - rho[ c ] ) );
    
       /****
        * ( rho * u1 )_t + ( rho * u1 * u1 )_x + ( rho * u1 * u2 )_y - p_x =  0
        */
       rho_u1_t = - 1.0 / mu_D_c * ( rho_u1_f_e * e_normal. x() + rho_u1_g_e * e_normal. y() +
                                     rho_u1_f_n * n_normal. x() + rho_u1_g_n * n_normal. y() +
                                     rho_u1_f_w * w_normal. x() + rho_u1_g_w * w_normal. y() +
                                     rho_u1_f_s * s_normal. x() + rho_u1_g_s * s_normal. y() )
    
                  + this -> viscosityCoefficient * 1.0 / ( 8.0 * tau ) * mu_D_c *
    
                                   ( ( mu_D_c + mu_D_e ) * ( rho_u1[ e ] - rho_u1[ c ] ) +
                                     ( mu_D_c + mu_D_n ) * ( rho_u1[ n ] - rho_u1[ c ] ) +
                                     ( mu_D_c + mu_D_w ) * ( rho_u1[ w ] - rho_u1[ c ] ) +
                                     ( mu_D_c + mu_D_s ) * ( rho_u1[ s ] - rho_u1[ c ] ) )
                                     - grad_p. x();
    
       /****
        * ( rho * u2 )_t + ( rho * u2 * u1 )_x + ( rho * u2 * u2 )_y - p_y =  0
        */
       rho_u2_t = - 1.0 / mu_D_c * ( rho_u2_f_e * e_normal. x() + rho_u2_g_e * e_normal. y() +
                                     rho_u2_f_n * n_normal. x() + rho_u2_g_n * n_normal. y() +
                                     rho_u2_f_w * w_normal. x() + rho_u2_g_w * w_normal. y() +
                                     rho_u2_f_s * s_normal. x() + rho_u2_g_s * s_normal. y() )
    
                  + this -> viscosityCoefficient * 1.0 / ( 8.0 * tau ) * mu_D_c *
    
                                   ( ( mu_D_c + mu_D_e ) * ( rho_u2[ e ] - rho_u2[ c ] ) +
                                     ( mu_D_c + mu_D_n ) * ( rho_u2[ n ] - rho_u2[ c ] ) +
                                     ( mu_D_c + mu_D_w ) * ( rho_u2[ w ] - rho_u2[ c ] ) +
                                     ( mu_D_c + mu_D_s ) * ( rho_u2[ s ] - rho_u2[ c ] ) )
                                     - grad_p. y();
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient,
              template< int, typename, typename, typename > class GridGeometry >
    Real tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, GridGeometry >, PressureGradient  > :: regularize( const Real& r ) const
    {
       return r + ( ( r >= 0 ) - ( r < 0 ) ) * this -> regularizeEps;
    }
    
    /****
     * Specialization for the grids with no deformations (Identical grid geometry)
     */
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
    tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >,
                     PressureGradient > :: tnlLaxFridrichs()
    
    : regularizeEps( 1.0e-5 ),
    
      viscosityCoefficient( 1.0 ),
      mesh( 0 ),
      pressureGradient( 0 )
    {
    }
    
    
    template< typename Real,
              typename Device,
    
              typename Index,
              typename PressureGradient >
    
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: bindMesh( const MeshType& mesh )
    {
       this -> mesh = &mesh;
    }
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: setRegularization( const RealType& epsilon )
    {
       this -> regularizeEps = epsilon;
    }
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: setViscosityCoefficient( const RealType& v )
    {
       this -> viscosityCoefficient = v;
    }
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
       template< typename Vector >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: setRho( Vector& rho )
    {
       this -> rho. bind( rho );
       this -> rho. setName( tnlString( "bind Of " ) + rho. getName() );
    }
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
       template< typename Vector >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: setRhoU1( Vector& rho_u1 )
    {
       this -> rho_u1. bind( rho_u1 );
       this -> rho_u1. setName( tnlString( "bind Of " ) + rho_u1. getName() );
    }
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
       template< typename Vector >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: setRhoU2( Vector& rho_u2 )
    {
       this -> rho_u2. bind( rho_u2 );
       this -> rho_u2. setName( tnlString( "bind Of " ) + rho_u2. getName() );
    }
    
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
       template< typename Vector >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: setE( Vector& e )
    {
       this->energy.bind( e );
       this->energy.setName( tnlString( "bind Of " ) + e.getName() );
    }
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
       template< typename Vector >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: setP( Vector& p )
    {
       this->p.bind( p );
       this->p.setName( tnlString( "bind Of " ) + p.getName() );
    }
    
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
       template< typename Vector >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: setPressureGradient( Vector& grad_p )
    {
       this -> pressureGradient = &grad_p;
    }
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: getExplicitRhs( const IndexType centralVolume,
    
                                                                                                                              RealType& rho_t,
                                                                                                                              RealType& rho_u1_t,
                                                                                                                              RealType& rho_u2_t,
                                                                                                                              const RealType& tau ) const
    
    {
       tnlAssert( mesh, cerr << "No mesh has been binded with the Lax-Fridrichs scheme." );
       tnlAssert( pressureGradient, cerr << "No pressure gradient was set in the the Lax-Fridrichs scheme." )
    
       const IndexType& xSize = this -> mesh -> getDimensions(). x();
       const IndexType& ySize = this -> mesh -> getDimensions(). y();
       const RealType hx = this -> mesh -> getParametricStep(). x();
       const RealType hy = this -> mesh -> getParametricStep(). y();
    
       const IndexType& c = centralVolume;
       const IndexType e = this -> mesh -> getElementNeighbour( centralVolume,  1,  0 );
       const IndexType w = this -> mesh -> getElementNeighbour( centralVolume, -1,  0 );
       const IndexType n = this -> mesh -> getElementNeighbour( centralVolume,  0,  1 );
       const IndexType s = this -> mesh -> getElementNeighbour( centralVolume,  0, -1 );
    
       /****
        * rho_t + ( rho u_1 )_x + ( rho u_2 )_y =  0
        */
       const RealType u1_e = rho_u1[ e ] / regularize( rho[ e ] );
       const RealType u1_w = rho_u1[ w ] / regularize( rho[ w ] );
       const RealType u2_n = rho_u2[ n ] / regularize( rho[ n ] );
       const RealType u2_s = rho_u2[ s ] / regularize( rho[ s ] );
    
       rho_t = this -> viscosityCoefficient / tau * 0.25 * ( rho[ e ] + rho[ w ] + rho[ s ] + rho[ n ] - 4.0 * rho[ c ] )
    
                   - ( rho[ e ] * u1_e - rho[ w ] * u1_w ) / ( 2.0 * hx )
                   - ( rho[ n ] * u2_n - rho[ s ] * u2_s ) / ( 2.0 * hy );
    
       /****
        * Compute the pressure gradient
        */
       VertexType grad_p;
       pressureGradient -> getGradient( c, grad_p );
    
       /****
        * ( rho * u1 )_t + ( rho * u1 * u1 )_x + ( rho * u1 * u2 )_y - p_x =  0
        */
    
       rho_u1_t = this -> viscosityCoefficient / tau * 0.25 * ( rho_u1[ e ] + rho_u1[ w ] + rho_u1[ s ] + rho_u1[ n ] - 4.0 * rho_u1[ c ] )
    
                       - ( rho_u1[ e ] * u1_e - rho_u1[ w ] * u1_w ) / ( 2.0 * hx )
                       - ( rho_u1[ n ] * u2_n - rho_u1[ s ] * u2_s ) / ( 2.0 * hy )
                       - grad_p. x();
       /****
        * ( rho * u2 )_t + ( rho * u2 * u1 )_x + ( rho * u2 * u2 )_y - p_y =  0
        */
    
       rho_u2_t = this -> viscosityCoefficient / tau * 0.25 * ( rho_u2[ e ] + rho_u2[ w ] + rho_u2[ s ] + rho_u2[ n ] - 4.0 * rho_u2[ c ] )
    
                       - ( rho_u2[ e ] * u1_e - rho_u2[ w ] * u1_w ) / ( 2.0 * hx )
                       - ( rho_u2[ n ] * u2_n - rho_u2[ s ] * u2_s ) / ( 2.0 * hy )
                       - grad_p. y();
    }
    
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
    void tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: getExplicitRhs( const IndexType centralVolume,
                                                                                                                              RealType& rho_t,
                                                                                                                              RealType& rho_u1_t,
                                                                                                                              RealType& rho_u2_t,
                                                                                                                              RealType& e_t,
                                                                                                                              const RealType& tau ) const
    {
       tnlAssert( mesh, cerr << "No mesh has been binded with the Lax-Fridrichs scheme." );
       tnlAssert( pressureGradient, cerr << "No pressure gradient was set in the the Lax-Fridrichs scheme." )
    
       const IndexType& xSize = this -> mesh -> getDimensions(). x();
       const IndexType& ySize = this -> mesh -> getDimensions(). y();
       const RealType hx = this -> mesh -> getParametricStep(). x();
       const RealType hy = this -> mesh -> getParametricStep(). y();
    
       const IndexType& c = centralVolume;
       const IndexType e = this -> mesh -> getElementNeighbour( centralVolume,  1,  0 );
       const IndexType w = this -> mesh -> getElementNeighbour( centralVolume, -1,  0 );
       const IndexType n = this -> mesh -> getElementNeighbour( centralVolume,  0,  1 );
       const IndexType s = this -> mesh -> getElementNeighbour( centralVolume,  0, -1 );
    
       /****
        * rho_t + ( rho u_1 )_x + ( rho u_2 )_y =  0
        */
       const RealType u1_e = rho_u1[ e ] / regularize( rho[ e ] );
       const RealType u1_w = rho_u1[ w ] / regularize( rho[ w ] );
       const RealType u2_n = rho_u2[ n ] / regularize( rho[ n ] );
       const RealType u2_s = rho_u2[ s ] / regularize( rho[ s ] );
       rho_t = this -> viscosityCoefficient / tau * 0.25 * ( rho[ e ] + rho[ w ] + rho[ s ] + rho[ n ] - 4.0 * rho[ c ] )
                   - ( rho[ e ] * u1_e - rho[ w ] * u1_w ) / ( 2.0 * hx )
                   - ( rho[ n ] * u2_n - rho[ s ] * u2_s ) / ( 2.0 * hy );
    
       /****
        * Compute the pressure gradient
        */
       VertexType grad_p;
       pressureGradient -> getGradient( c, grad_p );
    
       /****
        * ( rho * u1 )_t + ( rho * u1 * u1 )_x + ( rho * u1 * u2 )_y - p_x =  0
        */
       rho_u1_t = this -> viscosityCoefficient / tau * 0.25 * ( rho_u1[ e ] + rho_u1[ w ] + rho_u1[ s ] + rho_u1[ n ] - 4.0 * rho_u1[ c ] )
                       - ( rho_u1[ e ] * u1_e - rho_u1[ w ] * u1_w ) / ( 2.0 * hx )
                       - ( rho_u1[ n ] * u2_n - rho_u1[ s ] * u2_s ) / ( 2.0 * hy )
                       - grad_p. x();
       /****
        * ( rho * u2 )_t + ( rho * u2 * u1 )_x + ( rho * u2 * u2 )_y - p_y =  0
        */
       rho_u2_t = this -> viscosityCoefficient / tau * 0.25 * ( rho_u2[ e ] + rho_u2[ w ] + rho_u2[ s ] + rho_u2[ n ] - 4.0 * rho_u2[ c ] )
                       - ( rho_u2[ e ] * u1_e - rho_u2[ w ] * u1_w ) / ( 2.0 * hx )
                       - ( rho_u2[ n ] * u2_n - rho_u2[ s ] * u2_s ) / ( 2.0 * hy )
                       - grad_p. y();
    
       /****
        * e_t + ( ( e + p ) * u )_x + ( ( e + p ) * v )_y = 0
        */
       e_t = this -> viscosityCoefficient / tau * 0.25 * ( energy[ e ] + energy[ w ] + energy[ s ] + energy[ n ] - 4.0 * energy[ c ] )
                  - ( ( energy[ e ] + p[ e ] ) * u1_e - ( energy[ w ] + p[ w ] ) * u1_w ) / ( 2.0 * hx )
                  - ( ( energy[ n ] + p[ n ] ) * u2_n - ( energy[ s ] + p[ s ] ) * u2_s ) / ( 2.0 * hy );
    }
    
    
    
    template< typename Real,
              typename Device,
              typename Index,
              typename PressureGradient >
    Real tnlLaxFridrichs< tnlGrid< 2, Real, Device, Index, tnlIdenticalGridGeometry >, PressureGradient  > :: regularize( const Real& r ) const
    
    {
       return r + ( ( r >= 0 ) - ( r < 0 ) ) * this -> regularizeEps;