Branch data Line data Source code
1 : : // ***************************************************************************** 2 : : /*! 3 : : \file src/DiffEq/DiffEq.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 Differential equation 9 : : \details This file defines a generic differential equation class. The class 10 : : uses runtime polymorphism without client-side inheritance: inheritance is 11 : : confined to the internals of the class, invisible to client-code. The class 12 : : exclusively deals with ownership enabling client-side value semantics. 13 : : Credit goes to Sean Parent at Adobe: https://github.com/sean-parent/ 14 : : sean-parent.github.com/wiki/Papers-and-Presentations. 15 : : */ 16 : : // ***************************************************************************** 17 : : #ifndef DiffEq_h 18 : : #define DiffEq_h 19 : : 20 : : #include <string> 21 : : #include <functional> 22 : : #include <memory> 23 : : 24 : : #include "Types.hpp" 25 : : #include "Particles.hpp" 26 : : #include "Statistics.hpp" 27 : : 28 : : namespace walker { 29 : : 30 : : //! \brief Differential equation 31 : : //! \details This class uses runtime polymorphism without client-side 32 : : //! inheritance: inheritance is confined to the internals of the this class, 33 : : //! invisible to client-code. The class exclusively deals with ownership 34 : : //! enabling client-side value semantics. Credit goes to Sean Parent at Adobe: 35 : : //! https://github.com/sean-parent/sean-parent.github.com/wiki/ 36 : : //! Papers-and-Presentations. For example client code that models a DiffEq, 37 : : //! see walker::Beta. 38 : : class DiffEq { 39 : : 40 : : public: 41 : : //! Default constructor taking no arguments for Charm++ 42 : 0 : explicit DiffEq() = default; 43 : : 44 : : //! \brief Constructor taking an object modeling Concept. 45 : : //! \details The object of class T comes pre-constructed. 46 : : //! \param[in] x Instantiated object of type T given by the template 47 : : //! argument. 48 : : template< typename T > explicit DiffEq( T x ) : 49 : : self( std::make_unique< Model<T> >( std::move(x) ) ) {} 50 : : 51 : : //! \brief Constructor taking a function pointer to a constructor of an 52 : : //! object modeling Concept. 53 : : //! \details Passing std::function allows late execution of the constructor, 54 : : //! i.e., as late as inside this class' constructor, and thus usage from 55 : : //! a factory. Note that there are at least two different ways of using 56 : : //! this constructor: 57 : : //! - Bind T's constructor arguments and place it in std::function<T()> 58 : : //! and passing no arguments as args.... This case then instantiates the 59 : : //! model via its constructor and stores it in here. 60 : : //! - Bind a single placeholder argument to T's constructor and pass it in 61 : : //! as host's args..., which then forwards it to model's constructor. This 62 : : //! allows late binding, i.e., binding the argument only here. 63 : : //! \see See also the wrapper tk::recordModel() which does the former and 64 : : //! tk::recordModelLate() which does the latter, both defined in 65 : : //! src/Base/Factory.h. 66 : : //! \param[in] x Function pointer to a constructor of an object modeling 67 : : //! Concept. 68 : : //! \param[in] args Zero or more constructor arguments 69 : : template< typename T, typename...Args > 70 : 285 : explicit DiffEq( std::function<T(Args...)> x, Args&&... args ) : 71 : : self( std::make_unique< Model<T> >( 72 [ + - ]: 285 : std::move( x( std::forward<Args>(args)... ) ) ) ) {} 73 : : 74 : : //! Public interface to setting the initial conditions for the diff eq 75 : 960 : void initialize( int stream, tk::Particles& particles ) const 76 : 960 : { self->initialize( stream, particles ); } 77 : : 78 : : //! Public interface to advancing particles in time by the diff eq 79 : 4508509 : void advance( tk::Particles& particles, 80 : : int stream, 81 : : tk::real dt, 82 : : tk::real t, 83 : : const std::map< tk::ctr::Product, tk::real >& moments ) const 84 : 4508509 : { self->advance( particles, stream, dt, t, moments ); } 85 : : 86 : : //! Copy assignment 87 : : DiffEq& operator=( const DiffEq& x ) 88 : : { DiffEq tmp(x); *this = std::move(tmp); return *this; } 89 : : //! Copy constructor 90 : : DiffEq( const DiffEq& x ) : self( x.self->copy() ) {} 91 : : //! Move assignment 92 : : DiffEq& operator=( DiffEq&& ) noexcept = default; 93 : : //! Move constructor 94 : 339 : DiffEq( DiffEq&& ) noexcept = default; 95 : : 96 : : private: 97 : : //! \brief Concept is a pure virtual base class specifying the requirements 98 : : //! of polymorphic objects deriving from it 99 : : struct Concept { 100 : 285 : Concept() = default; 101 : 0 : Concept( const Concept& ) = default; 102 : 285 : virtual ~Concept() = default; 103 : : virtual Concept* copy() const = 0; 104 : : virtual void initialize( int, tk::Particles& ) = 0; 105 : : virtual void advance( tk::Particles&, 106 : : int, 107 : : tk::real, 108 : : tk::real, 109 : : const std::map< tk::ctr::Product, tk::real >& ) = 0; 110 : : }; 111 : : 112 : : //! \brief Model models the Concept above by deriving from it and overriding 113 : : //! the virtual functions required by Concept 114 : : template< typename T > 115 : : struct Model : Concept { 116 [ + - ]: 285 : explicit Model( T x ) : data( std::move(x) ) {} 117 [ - - ]: 0 : Concept* copy() const override { return new Model( *this ); } 118 : 960 : void initialize( int stream, tk::Particles& particles ) 119 : 960 : override { data.initialize( stream, particles ); } 120 : 4508509 : void advance( tk::Particles& particles, 121 : : int stream, 122 : : tk::real dt, 123 : : tk::real t, 124 : : const std::map< tk::ctr::Product, tk::real >& moments ) 125 : 4508509 : override { data.advance( particles, stream, dt, t, moments ); } 126 : : T data; 127 : : }; 128 : : 129 : : std::unique_ptr< Concept > self; //!< Base pointer used polymorphically 130 : : }; 131 : : 132 : : } // walker:: 133 : : 134 : : #endif // DiffEq_h