Branch data Line data Source code
1 : : // ***************************************************************************** 2 : : /*! 3 : : \file src/PDE/Riemann/RiemannSolver.hpp 4 : : \copyright 2012-2015 J. Bakosi, 5 : : 2016-2018 Los Alamos National Security, LLC., 6 : : 2019-2021 Triad National Security, LLC. 7 : : All rights reserved. See the LICENSE file for details. 8 : : \brief Riemann solver interface class for various Riemann solvers 9 : : \details This file defines a generic Riemann solver interface class. The 10 : : class uses runtime polymorphism without client-side inheritance: inheritance 11 : : is confined to the internals of the class, invisible to client-code. The 12 : : class exclusively deals with ownership enabling client-side value semantics. 13 : : Credit for this idea goes to Sean Parent at Adobe: 14 : : https://github.com/sean-parent/sean-parent.github.com/wiki/ 15 : : Papers-and-Presentations. 16 : : */ 17 : : // ***************************************************************************** 18 : : #ifndef RiemannSolver_h 19 : : #define RiemannSolver_h 20 : : 21 : : #include <array> 22 : : #include <vector> 23 : : #include <memory> 24 : : 25 : : #include "Types.hpp" 26 : : #include "Fields.hpp" 27 : : #include "FunctionPrototypes.hpp" 28 : : 29 : : namespace inciter { 30 : : 31 : : //! \brief Generic Riemann solver interface class for various Riemann solvers 32 : : //! \details This class uses runtime polymorphism without client-side 33 : : //! inheritance: inheritance is confined to the internals of this class, 34 : : //! invisble to client-code. The class exclusively deals with ownership 35 : : //! enabling client-side value semantics. Credit for this idea goes to Sean 36 : : //! Parent at Adobe: 37 : : //! https://github.com/sean-parent/sean-parent.github.com/wiki/ 38 : : //! Papers-and-Presentations. 39 : 0 : class RiemannSolver { 40 : : 41 : : public: 42 : : //! \brief Constructor taking an object modeling Concept 43 : : //! \details The object of class T comes pre-constructed. 44 : : //! \param[in] x Instantiated object of type T given by the template 45 : : //! argument. 46 : : template< typename T > explicit RiemannSolver( T x ) : 47 : : self( std::make_unique< Model<T> >( std::move(x) ) ) {} 48 : : 49 : : //! \brief Constructor taking a function pointer (std::function) to a 50 : : //! constructor of an object modeling Concept. 51 : : //! \details Passing std::function allows late execution of the constructor, 52 : : //! i.e., as late as inside this class' constructor, and thus usage from 53 : : //! a factory. Note that there are at least two different ways of using 54 : : //! this constructor: 55 : : //! - Bind T's constructor arguments and place it in std::function<T()> 56 : : //! and passing no arguments as args.... This case then instantiates the 57 : : //! model via its constructor and stores it in here. 58 : : //! - Bind a single placeholder argument to T's constructor and pass it in 59 : : //! as host's args..., which then forwards it to model's constructor. This 60 : : //! allows late binding, i.e., binding the argument only here. 61 : : //! \see See also the wrapper tk::recordModel() which does the former for 62 : : //! arbitrary number of model constructor arguments and 63 : : //! tk::recordModelLate() for a single model constructor argument which 64 : : //! does the latter, both defined in src/Base/Factory.h. 65 : : //! \param[in] x Function pointer (std::function) to a constructor of an 66 : : //! object modeling Concept. 67 : : //! \param[in] args Zero or more constructor arguments 68 : : template< typename T, typename...Args > 69 [ - + ]: 220 : explicit RiemannSolver( std::function<T(Args...)> x, Args&&... args ) : 70 : : self( std::make_unique< Model<T> >( 71 [ + - ][ - + ]: 220 : std::move( x( std::forward<Args>(args)... ) ) ) ) {} 72 : : 73 : : //! Public interface to computing the Riemann flux 74 : : std::vector< tk::real > 75 : : flux( const std::array< tk::real, 3 >& fn, 76 : : const std::array< std::vector< tk::real >, 2 >& u, 77 : : const std::vector< std::array< tk::real, 3 > >& v ) const 78 : 78495834 : { return self->flux( fn, u, v ); } 79 : : 80 : : //! Copy assignment 81 : : RiemannSolver& operator=( const RiemannSolver& x ) 82 : : { RiemannSolver tmp(x); *this = std::move(tmp); return *this; } 83 : : //! Copy constructor 84 : 0 : RiemannSolver( const RiemannSolver& x ) : self( x.self->copy() ) {} 85 : : //! Move assignment 86 : : RiemannSolver& operator=( RiemannSolver&& ) noexcept = default; 87 : : //! Move constructor 88 : : RiemannSolver( RiemannSolver&& ) noexcept = default; 89 : : 90 : : private: 91 : : //! \brief Concept is a pure virtual base class specifying the requirements 92 : : //! of polymorphic objects deriving from it, i.e., those functions that 93 : : //! can be overridden 94 : : struct Concept { 95 : : Concept() = default; 96 : 0 : Concept( const Concept& ) = default; 97 : : virtual ~Concept() = default; 98 : : virtual Concept* copy() const = 0; 99 : : virtual std::vector< tk::real > 100 : : flux( const std::array< tk::real, 3 >&, 101 : : const std::array< std::vector< tk::real >, 2 >&, 102 : : const std::vector< std::array< tk::real, 3 > >& ) const = 0; 103 : : }; 104 : : 105 : : //! \brief Model models the Concept above by deriving from it and overriding 106 : : //! the virtual functions required by Concept 107 : : template< typename T > 108 [ - - ]: 0 : struct Model : Concept { 109 : 220 : explicit Model( T x ) : data( std::move(x) ) {} 110 : 0 : Concept* copy() const override { return new Model( *this ); } 111 : : std::vector< tk::real > 112 : 78495834 : flux( const std::array< tk::real, 3 >& fn, 113 : : const std::array< std::vector< tk::real >, 2 >& u, 114 : : const std::vector< std::array< tk::real, 3 > >& v ) const override 115 : 78495834 : { return data.flux( fn, u, v ); } 116 : : T data; 117 : : }; 118 : : 119 : : std::unique_ptr< Concept > self; //!< Base pointer used polymorphically 120 : : }; 121 : : 122 : : } // inciter:: 123 : : 124 : : #endif // RiemannSolver_h