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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// *****************************************************************************
/*!
  \file      src/PDE/PDEStack.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     Stack of differential equations
  \details   This file declares class PDEStack, which implements various
    functionality related to registering and instantiating partial differential
    equation types. Registration and instantiation use a partial differential
    equation factory, which is a std::map (an associative container),
    associating unique partial differential equation keys to their constructor
    calls. For more details, see the in-code documentation of the constructor.
*/
// *****************************************************************************
#ifndef PDEStack_h
#define PDEStack_h

#include <map>
#include <set>
#include <string>
#include <vector>
#include <iostream>

#include "NoWarning/back.hpp"
#include "NoWarning/front.hpp"

#include "Tags.hpp"
#include "Types.hpp"
#include "Exception.hpp"
#include "Factory.hpp"
#include "CGPDE.hpp"
#include "DGPDE.hpp"
#include "FVPDE.hpp"
#include "PDEFactory.hpp"
#include "Inciter/InputDeck/InputDeck.hpp"

namespace inciter {

extern ctr::InputDeck g_inputdeck;

//! \brief Partial differential equations stack
class PDEStack {

  private:
    using ncomp_t = tk::ncomp_t;

  public:
    //! Constructor: register partial differential equations into factory
    explicit PDEStack();

    //! Instantiate selected PDEs using continuous Galerkin discretization
    std::vector< CGPDE > selectedCG() const;

    //! Instantiate selected PDEs using discontinuous Galerkin discretization
    std::vector< DGPDE > selectedDG() const;

    //! Instantiate selected PDEs using finite volume discretization
    std::vector< FVPDE > selectedFV() const;

    //! Constant accessor to CGPDE factory
    //! \return Constant reference to the CGPDE factory
    const CGFactory& cgfactory() const { return m_cgfactory; }

    //! Constant accessor to DGPDE factory
    //! \return Constant reference to the DGPDE factory
    const DGFactory& dgfactory() const { return m_dgfactory; }

    //! Constant accessor to FVPDE factory
    //! \return Constant reference to the FVPDE factory
    const FVFactory& fvfactory() const { return m_fvfactory; }

    //! Return info on selected partial differential equations
    std::vector< std::vector< std::pair< std::string, std::string > > > info()
    const;

    //! Return number of unique equation types registered into the CG factory
    //! \return The number of unique equation types registered into the CG
    //!   factory the factory
    std::size_t cgntypes() const { return m_cgEqTypes.size(); }

    //! Return number of unique equation types registered into the DG factory
    //! \return The number of unique equation types registered into the DG
    //!   factory the factory
    std::size_t dgntypes() const { return m_dgEqTypes.size(); }

    //! Return number of unique equation types registered into the FV factory
    //! \return The number of unique equation types registered into the FV
    //!   factory the factory
    std::size_t fvntypes() const { return m_fvEqTypes.size(); }

  private:
    //! \brief Instantiate a partial differential equation
    //! \details The template argument, EqTag, is used to find the given
    //!   partial differential equation in the input deck, the hierarchical data
    //!   filled during control file parsing, containing user input. The
    //!   template argument Factory specifies which factory we search in. The
    //!   template argument PDE specifies the "base" PDE type that the
    //!   instantiated "child" PDE class object is used polymorphically with.
    //! \param[in] f Factory in which to search PDE in
    //! \param[in] eq The unique partial differential equation key whose object
    //!   to instantiate.
    //! \param[in,out] cnt Counter, a std::map, that counts all instantiated
    //!   partial differential equations by type.
    template< class EqTag, class Factory, class PDE >
    PDE createPDE( const Factory& f,
                   ctr::PDEType eq,
                   std::map< ctr::PDEType, ncomp_t >& cnt ) const
    {
      auto c = ++cnt[ eq ];   // count eqs
      --c;                    // used to index vectors starting with 0<--- Variable 'c' is assigned a value that is never used.
      const auto& nc = g_inputdeck.get< tag::ncomp >();
      if ( nc ) {
        // re-create key and search for it
        auto prob = g_inputdeck.get< EqTag, tag::problem >();
        // if more than one mesh, set problem type for all additional meshes
        // as user-defined
        if (cnt[eq] > 1) prob = ctr::ProblemType::USER_DEFINED;
        ctr::PDEKey key{{ eq,
          g_inputdeck.get< EqTag, tag::physics >(), prob }};
        const auto it = f.find( key );
        Assert( it != end( f ),
                "Can't find PDE with key('" +
                  ctr::PDE().name( key.get< tag::pde >() ) + "', '" +
                  ctr::Physics().name( key.get< tag::physics >() ) + "', '" +
                  ctr::Problem().name( key.get< tag::problem >() ) +
                  + "') in factory" );
        // Associate equation system index (value) to all variable offsets
        for (ncomp_t i=0; i<nc; ++i) g_inputdeck.get<tag::sys>()[i] = c;
        // instantiate and return PDE object
        return it->second();
      } else Throw ( "Can't create PDE with zero components" );
    }

    //! Wrapper of createPDE specialized for registering CG PDEs
    //! \param[in] t Enum selecting PDE type, Control/Inciter/Options/PDE.h
    //! \param[in,out] cnt Counter, a std::map, that counts all instantiated
    //!   partial differential equations by type.
    //! \details The sole reason for this function is to simplify client-code
    //!   calling createPDE specialized to CG PDEs
    template< class EqTag >
    CGPDE createCG( ctr::PDEType t, std::map< ctr::PDEType, ncomp_t >& cnt )
    const {
      return createPDE< EqTag, CGFactory, CGPDE >( m_cgfactory, t, cnt );
    }

    //! Wrapper of createPDE specialized for registering DG PDEs
    //! \param[in] t Enum selecting PDE type, Control/Inciter/Options/PDE.h
    //! \param[in,out] cnt Counter, a std::map, that counts all instantiated
    //!   partial differential equations by type.
    //! \details The sole reason for this function is to simplify client-code
    //!   calling createPDE specialized to DG PDEs
    template< class EqTag >
    DGPDE createDG( ctr::PDEType t, std::map< ctr::PDEType, ncomp_t >& cnt )
    const {
      return createPDE< EqTag, DGFactory, DGPDE >( m_dgfactory, t, cnt );
    }

    //! Wrapper of createPDE specialized for registering FV PDEs
    //! \param[in] t Enum selecting PDE type, Control/Inciter/Options/PDE.h
    //! \param[in,out] cnt Counter, a std::map, that counts all instantiated
    //!   partial differential equations by type.
    //! \details The sole reason for this function is to simplify client-code
    //!   calling createPDE specialized to FV PDEs
    template< class EqTag >
    FVPDE createFV( ctr::PDEType t, std::map< ctr::PDEType, ncomp_t >& cnt )
    const {
      return createPDE< EqTag, FVFactory, FVPDE >( m_fvfactory, t, cnt );
    }

    //! PDE factory for continuous Galerkin discretization
    CGFactory m_cgfactory;
    //! PDE factory for discontinuous Galerkin discretization
    DGFactory m_dgfactory;
    //! PDE factory for finite volume discretization
    FVFactory m_fvfactory;
    //! Counters for equation types registered into the CG factory
    std::set< ctr::PDEType > m_cgEqTypes;
    //! Counters for equation types registered into the DG factory
    std::set< ctr::PDEType > m_dgEqTypes;
    //! Counters for equation types registered into the FV factory
    std::set< ctr::PDEType > m_fvEqTypes;
};

} // inciter::

#endif // PDEStack_h