1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// *****************************************************************************
/*!
  \file      src/PDE/EoS/EOS.hpp
  \copyright 2012-2015 J. Bakosi,
             2016-2018 Los Alamos National Security, LLC.,
             2019-2021 Triad National Security, LLC.
             All rights reserved. See the LICENSE file for details.
  \brief     Polymorphic variant-style implementation for equations of state,
    where children implement specific EOS functions.
*/
// *****************************************************************************
#ifndef EOS_h
#define EOS_h

#include <variant>

#include "PUPUtil.hpp"
#include "Inciter/Options/Material.hpp"
#include "EoS/StiffenedGas.hpp"
#include "EoS/JWL.hpp"
#include "EoS/SmallShearSolid.hpp"
#include "EoS/GodunovRomenskiAluminum.hpp"
#include "EoS/ThermallyPerfectGas.hpp"

namespace inciter {

//! Equation types
enum class EqType : uint8_t { compflow
                            , multimat
                            , multispecies
                            };

//! Base class for generic forwarding interface to eos types
class EOS {

  private:
    //! Variant type listing all eos types modeling the same concept
    std::variant< StiffenedGas
                , JWL
                , SmallShearSolid
                , GodunovRomenskiAluminum
                , ThermallyPerfectGas
                > m_material;

  public:
    //! Empty constructor for Charm++
    explicit EOS() {}

    //! Constructor
    explicit EOS( ctr::MaterialType mattype, EqType eq, std::size_t k );

    //! Entry method tags for specific EOS classes to use with compute()
    struct density {};
    struct pressure {};
    struct soundspeed {};
    struct shearspeed {};
    struct totalenergy {};
    struct temperature {};
    struct min_eff_pressure {};
    struct refDensity {};
    struct refPressure {};
    struct rho0 {};
    //! Call EOS function
    //! \tparam Fn Function tag identifying the function to call
    //! \tparam Args Types of arguments to pass to function
    //! \param[in] args Arguments to member function to be called
    //! \details This function issues a call to a member function of the
    //!   EOS vector and is thus equivalent to mat_blk[imat].Fn(...).
    template< typename Fn, typename... Args >
    tk::real compute( Args&&... args ) const {
      return std::visit( [&]( const auto& m )-> tk::real {
          if constexpr( std::is_same_v< Fn, density > )
            return m.density( std::forward< Args >( args )... );

          else if constexpr( std::is_same_v< Fn, pressure > )
            return m.pressure( std::forward< Args >( args )... );

          else if constexpr( std::is_same_v< Fn, soundspeed > )
            return m.soundspeed( std::forward< Args >( args )... );

          else if constexpr( std::is_same_v< Fn, shearspeed > )
            return m.shearspeed( std::forward< Args >( args )... );

          else if constexpr( std::is_same_v< Fn, totalenergy > )
            return m.totalenergy( std::forward< Args >( args )... );

          else if constexpr( std::is_same_v< Fn, temperature > )
            return m.temperature( std::forward< Args >( args )... );

          else if constexpr( std::is_same_v< Fn, min_eff_pressure > )
            return m.min_eff_pressure( std::forward< Args >( args )... );

          else if constexpr( std::is_same_v< Fn, refDensity > )
            return m.refDensity( std::forward< Args >( args )... );

          else if constexpr( std::is_same_v< Fn, refPressure > )
            return m.refPressure( std::forward< Args >( args )... );

          else if constexpr( std::is_same_v< Fn, rho0 > )
            return m.rho0( std::forward< Args >( args )... );
        }, m_material );
    }

    //! Entry method tags for specific EOS classes to use with computeTensor()
    struct CauchyStress {};
    //! Call EOS function returning a tensor
    //! \tparam Fn Function tag identifying the function to call
    //! \tparam Args Types of arguments to pass to function
    //! \param[in] args Arguments to member function to be called
    //! \details This function issues a call to a member function of the
    //!   EOS vector and is thus equivalent to mat_blk[imat].Fn(...).
    template< typename Fn, typename... Args >
    std::array< std::array< tk::real, 3 >, 3 > computeTensor( Args&&... args )
    const {
      return std::visit( [&]( const auto& m )->
        std::array< std::array< tk::real, 3 >, 3 > {
          if constexpr( std::is_same_v< Fn, CauchyStress > )
            return m.CauchyStress( std::forward< Args >( args )... );

        }, m_material );
    }

    //! Entry method tags for specific EOS classes to use with set()
    struct setRho0 {};
    //! Call EOS function
    //! \tparam Fn Function tag identifying the function to call
    //! \tparam Args Types of arguments to pass to function
    //! \param[in] args Arguments to member function to be called
    //! \details This function issues a call to a member function of the
    //!   EOS vector and is thus equivalent to mat_blk[imat].Fn(...).
    template< typename Fn, typename... Args >
    void set( Args&&... args ) {
      std::visit( [&]( auto& m )-> void {
          if constexpr( std::is_same_v< Fn, setRho0 > )
            m.setRho0( std::forward< Args >( args )... );
        }, m_material );
    }

    /** @name Charm++ pack/unpack serializer member functions */
    ///@{
    //! \brief Pack/Unpack serialize member function
    //! \param[in,out] p Charm++'s PUP::er serializer object reference
    void pup( PUP::er &p ) {<--- Parameter 'p' can be declared with const
      p | m_material;
    }
    //! \brief Pack/Unpack serialize operator|
    //! \param[in,out] p Charm++'s PUP::er serializer object reference
    //! \param[in,out] s EOS object reference
    friend void operator|( PUP::er& p, EOS& s ) { s.pup(p); }
    //@}
};

} // inciter::

#endif // EOS_h