Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/DiffEq/DiffEqStack.cpp
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 Stack of differential equations
9 : : \details This file defines class DiffEqStack, which implements various
10 : : functionality related to registering and instantiating differential equation
11 : : types. Registration and instantiation use a differential equation factory,
12 : : which is a std::map (an associative container), associating unique
13 : : differential equation keys to their constructor calls. For more details, see
14 : : the in-code documentation of the constructor.
15 : : */
16 : : // *****************************************************************************
17 : :
18 : : #include "DiffEqStack.hpp"
19 : : #include "Tags.hpp"
20 : :
21 : : #include "ConfigureDirichlet.hpp"
22 : : #include "ConfigureMixDirichlet.hpp"
23 : : #include "ConfigureGeneralizedDirichlet.hpp"
24 : : #include "ConfigureWrightFisher.hpp"
25 : : #include "ConfigureOrnsteinUhlenbeck.hpp"
26 : : #include "ConfigureDiagOrnsteinUhlenbeck.hpp"
27 : : #include "ConfigureBeta.hpp"
28 : : #include "ConfigureNumberFractionBeta.hpp"
29 : : #include "ConfigureMassFractionBeta.hpp"
30 : : #include "ConfigureMixNumberFractionBeta.hpp"
31 : : #include "ConfigureMixMassFractionBeta.hpp"
32 : : #include "ConfigureGamma.hpp"
33 : : #include "ConfigureSkewNormal.hpp"
34 : : #include "ConfigureVelocity.hpp"
35 : : #include "ConfigurePosition.hpp"
36 : : #include "ConfigureDissipation.hpp"
37 : :
38 : : using walker::DiffEqStack;
39 : :
40 [ + - ]: 323 : DiffEqStack::DiffEqStack() : m_factory(), m_eqTypes()
41 : : // *****************************************************************************
42 : : // Constructor: register all differential equations into factory
43 : : //! \details This constructor consists of several blocks, each registering a
44 : : //! potentially large number of entries in the differential equation factory,
45 : : //! m_factory, which is of type walker::DiffEqFactory, a std::map. At this
46 : : //! time, each type of differential equation can be configured to use a unique
47 : : //! _initialization policy_ and a unique _coefficients policy_. (More types
48 : : //! of policies will most likely come in the future.) The policy classes are
49 : : //! template arguments to the differential equation classes and influence
50 : : //! their behavior in a different way, abstracting away certain functions,
51 : : //! e.g., how to set initial conditions and how to update their coefficients
52 : : //! during time integration. For more information on policy-based design, see
53 : : //! http://en.wikipedia.org/wiki/Policy-based_design. This abstraction allows
54 : : //! [separation of concerns]
55 : : //! (http://en.wikipedia.org/wiki/Separation_of_concerns).
56 : : //!
57 : : //! Since the functionality of the policies are orthogonal to each other,
58 : : //! i.e., they do not depend on each other or their host (the differential
59 : : //! equation class), a Cartesian product of combinations are possible,
60 : : //! depending on which policies are selected. _This constructor registers all
61 : : //! possible combinations of policies for all available differential
62 : : //! equations._ By _register_, we mean, an entry is recorded in an associative
63 : : //! container, a std::map, that associates a lightweight key of type
64 : : //! walker::ctr::DiffEqKey, consisting of only an enum for each policy type,
65 : : //! to an std::function object that holds the constructor bound to its
66 : : //! arguments corresponding to a particular differential equation + policies
67 : : //! combination. Note that registering these entries in the map does not
68 : : //! invoke the constructors. The mapped value simply stores how the
69 : : //! constructors should be invoked at a later time. At some point later,
70 : : //! based on user input, we then instantiate only the differential equations
71 : : //! (and only those configurations) that are requested by the user.
72 : : //!
73 : : //! Since all differential equation types (registered in the factory)
74 : : //! "inherit" from a common "base", client-code is unform and generic, and
75 : : //! thus immune to changes in the inner workings of the particular
76 : : //! differential equations as long as they fullfill certain concepts, i.e.,
77 : : //! implement certain member functinos, enforced by the _common base_, DiffEq.
78 : : //! The words "inherit and "base" are quoted here, because the common base
79 : : //! does not use inheritance in the normal OOP sense and does not use
80 : : //! reference semantics, i.e., pointers, visible to client-code either. The
81 : : //! relationship is more of a _models a_-type, which simplifies client-code
82 : : //! and allows for the benfits of runtime inheritance with value-semantics
83 : : //! which is less error prone and easier to read. See more about the
84 : : //! _models-a_ relationship and its implementation in DiffEq/DiffEq.h.
85 : : //!
86 : : //! The design discussed above allows the registration, instantiation, and
87 : : //! use of the differential equations to be generic, which eliminates a lot of
88 : : //! boiler-plate code and makes client-code uniform.
89 : : //!
90 : : //! _Details of registration using brigand::for_each and
91 : : //! tk::cartesian_product:_
92 : : //!
93 : : //! The template argument to brigand::for_each, as used below, requires a
94 : : //! list of list of types. We use brigand::list of brigand::list of types,
95 : : //! listing all possible policies, where the inner list must have exactly two
96 : : //! types, as the list of lists is constructed from two lists using the
97 : : //! cartesian product, and the length of the outer list (the list of lists) is
98 : : //! arbitrary. The constructor argument to brigand::for_each is a functor that
99 : : //! is to be applied to all members of the outer list. tk::cartesian_product
100 : : //! will create all possible combinations of these types and call the functor
101 : : //! with each type of the created sequence as a template parameter. The
102 : : //! functor here inherits from registerDiffEq, which, i.e., its constructor
103 : : //! call, needs a single template argument, a class templated on policy
104 : : //! classes. This is the differential equation class to be configured by
105 : : //! selecting policies and to be registered. The arguments to
106 : : //! registerDiffEq's constructor are the factory, the enum denoting the
107 : : //! differential equation type, and a reference to a variable of type
108 : : //! std::set< ctr::DiffEqType >, which is only used internally to DiffEqStack
109 : : //! for counting up the number of unique differential equation types
110 : : //! registered, used for diagnostics purposes.
111 : : // *****************************************************************************
112 : : {
113 [ + - ]: 323 : registerDirichlet( m_factory, m_eqTypes );
114 [ + - ]: 323 : registerMixDirichlet( m_factory, m_eqTypes );
115 [ + - ]: 323 : registerGenDir( m_factory, m_eqTypes );
116 [ + - ]: 323 : registerWrightFisher( m_factory, m_eqTypes );
117 [ + - ]: 323 : registerOrnsteinUhlenbeck( m_factory, m_eqTypes );
118 [ + - ]: 323 : registerDiagOrnsteinUhlenbeck( m_factory, m_eqTypes );
119 [ + - ]: 323 : registerBeta( m_factory, m_eqTypes );
120 [ + - ]: 323 : registerNumberFractionBeta( m_factory, m_eqTypes );
121 [ + - ]: 323 : registerMassFractionBeta( m_factory, m_eqTypes );
122 [ + - ]: 323 : registerMixNumberFractionBeta( m_factory, m_eqTypes );
123 [ + - ]: 323 : registerMixMassFractionBeta( m_factory, m_eqTypes );
124 [ + - ]: 323 : registerGamma( m_factory, m_eqTypes );
125 [ + - ]: 323 : registerSkewNormal( m_factory, m_eqTypes );
126 [ + - ]: 323 : registerVelocity( m_factory, m_eqTypes );
127 [ + - ]: 323 : registerPosition( m_factory, m_eqTypes );
128 [ + - ]: 323 : registerDissipation( m_factory, m_eqTypes );
129 : 323 : }
130 : :
131 : : std::vector< walker::DiffEq >
132 : 249 : DiffEqStack::selected() const
133 : : // *****************************************************************************
134 : : // Instantiate all selected differential equations
135 : : //! \return std::vector of instantiated differential equation objects
136 : : // *****************************************************************************
137 : : {
138 : : std::map< ctr::DiffEqType, ncomp_t > cnt; // count DiffEqs per type
139 : : std::vector< DiffEq > diffeqs; // will store instantiated DiffEqs
140 : :
141 [ + + ]: 534 : for (const auto& d : g_inputdeck.get< tag::selected, tag::diffeq >()) {
142 [ + + ]: 285 : if (d == ctr::DiffEqType::DIRICHLET)
143 [ + - ]: 44 : diffeqs.push_back( createDiffEq< tag::dirichlet >( d, cnt ) );
144 [ + + ]: 263 : else if (d == ctr::DiffEqType::MIXDIRICHLET)
145 [ + - ]: 64 : diffeqs.push_back( createDiffEq< tag::mixdirichlet >( d, cnt ) );
146 [ + + ]: 231 : else if (d == ctr::DiffEqType::GENDIR)
147 [ + - ]: 22 : diffeqs.push_back( createDiffEq< tag::gendir >( d, cnt ) );
148 [ - + ]: 220 : else if (d == ctr::DiffEqType::WRIGHTFISHER)
149 [ - - ]: 0 : diffeqs.push_back( createDiffEq< tag::wrightfisher >( d, cnt ) );
150 [ + + ]: 220 : else if (d == ctr::DiffEqType::OU)
151 [ + - ]: 54 : diffeqs.push_back( createDiffEq< tag::ou >( d, cnt ) );
152 [ + + ]: 193 : else if (d == ctr::DiffEqType::DIAG_OU)
153 [ + - ]: 76 : diffeqs.push_back( createDiffEq< tag::diagou >( d, cnt ) );
154 [ + + ]: 155 : else if (d == ctr::DiffEqType::BETA)
155 [ + - ]: 22 : diffeqs.push_back( createDiffEq< tag::beta >( d, cnt ) );
156 [ + + ]: 144 : else if (d == ctr::DiffEqType::NUMFRACBETA)
157 [ + - ]: 22 : diffeqs.push_back( createDiffEq< tag::numfracbeta >( d, cnt ) );
158 [ + + ]: 133 : else if (d == ctr::DiffEqType::MASSFRACBETA)
159 [ + - ]: 22 : diffeqs.push_back( createDiffEq< tag::massfracbeta >( d, cnt ) );
160 [ - + ]: 122 : else if (d == ctr::DiffEqType::MIXNUMFRACBETA)
161 [ - - ]: 0 : diffeqs.push_back( createDiffEq< tag::mixnumfracbeta >( d, cnt ) );
162 [ + + ]: 122 : else if (d == ctr::DiffEqType::MIXMASSFRACBETA)
163 [ + - ]: 30 : diffeqs.push_back( createDiffEq< tag::mixmassfracbeta >( d, cnt ) );
164 [ + + ]: 107 : else if (d == ctr::DiffEqType::SKEWNORMAL)
165 [ + - ]: 76 : diffeqs.push_back( createDiffEq< tag::skewnormal >( d, cnt ) );
166 [ + + ]: 69 : else if (d == ctr::DiffEqType::GAMMA)
167 [ + - ]: 22 : diffeqs.push_back( createDiffEq< tag::gamma >( d, cnt ) );
168 [ + + ]: 58 : else if (d == ctr::DiffEqType::VELOCITY)
169 [ + - ]: 44 : diffeqs.push_back( createDiffEq< tag::velocity >( d, cnt ) );
170 [ + + ]: 36 : else if (d == ctr::DiffEqType::POSITION)
171 [ + - ]: 36 : diffeqs.push_back( createDiffEq< tag::position >( d, cnt ) );
172 [ + - ]: 18 : else if (d == ctr::DiffEqType::DISSIPATION)
173 [ + - ]: 36 : diffeqs.push_back( createDiffEq< tag::dissipation >( d, cnt ) );
174 [ - - ][ - - ]: 0 : else Throw( "Can't find selected DiffEq" );
[ - - ][ - - ]
[ - - ][ - - ]
175 : : }
176 : :
177 : 249 : return diffeqs;
178 : : }
179 : :
180 : : std::pair< std::vector< std::string >, std::vector< tk::Table<1> > >
181 : 74 : DiffEqStack::tables() const
182 : : // *****************************************************************************
183 : : // Instantiate tables from which extra statistics data to be output sampled for
184 : : // all selected differential equations
185 : : //! \return Vector of names and tables to sample from during time stepping
186 : : // *****************************************************************************
187 : : {
188 : : std::map< ctr::DiffEqType, ncomp_t > cnt; // count DiffEqs per type
189 : 74 : std::vector< std::string > nam; // names of instantiated tables
190 : 74 : std::vector< tk::Table<1> > tab; // instantiated tables
191 : :
192 [ + + ]: 160 : for (const auto& d : g_inputdeck.get< tag::selected, tag::diffeq >()) {
193 : : std::pair< std::vector< std::string >, std::vector< tk::Table<1> > > t;
194 : :
195 [ + + ]: 86 : if (d == ctr::DiffEqType::MIXMASSFRACBETA)
196 [ + - ]: 10 : t = createTables< tag::mixmassfracbeta >( d, cnt );
197 [ + + ]: 81 : else if (d == ctr::DiffEqType::VELOCITY)
198 [ + - ]: 14 : t = createTables< tag::velocity >( d, cnt );
199 : :
200 [ + - ][ + - ]: 86 : nam.insert( end(nam), begin(t.first), end(t.first) );
201 [ + - ]: 86 : tab.insert( end(tab), begin(t.second), end(t.second) );
202 : : }
203 : :
204 [ + - ]: 148 : return { nam, tab };
205 : : }
206 : :
207 : : std::vector< std::vector< std::pair< std::string, std::string > > >
208 : 74 : DiffEqStack::info() const
209 : : // *****************************************************************************
210 : : // Return information on all selected differential equations
211 : : //! \return A vector of vector of pair of strings, containing the configuration
212 : : //! for each selected differential equation
213 : : // *****************************************************************************
214 : : {
215 : : std::map< ctr::DiffEqType, ncomp_t > cnt; // count DiffEqs per type
216 : : // will store info on all differential equations selected
217 : : std::vector< std::vector< std::pair< std::string, std::string > > > nfo;
218 : :
219 [ + + ]: 160 : for (const auto& d : g_inputdeck.get< tag::selected, tag::diffeq >()) {
220 [ + + ]: 86 : if (d == ctr::DiffEqType::DIRICHLET)
221 [ + - ][ + - ]: 8 : nfo.emplace_back( infoDirichlet( cnt ) );
222 [ + + ]: 78 : else if (d == ctr::DiffEqType::MIXDIRICHLET)
223 [ + - ][ + - ]: 8 : nfo.emplace_back( infoMixDirichlet( cnt ) );
224 [ + + ]: 70 : else if (d == ctr::DiffEqType::GENDIR)
225 [ + - ][ + - ]: 4 : nfo.emplace_back( infoGenDir( cnt ) );
226 [ - + ]: 66 : else if (d == ctr::DiffEqType::WRIGHTFISHER)
227 [ - - ][ - - ]: 0 : nfo.emplace_back( infoWrightFisher( cnt ) );
228 [ + + ]: 66 : else if (d == ctr::DiffEqType::OU)
229 [ + - ][ + - ]: 6 : nfo.emplace_back( infoOrnsteinUhlenbeck( cnt ) );
230 [ + + ]: 60 : else if (d == ctr::DiffEqType::DIAG_OU)
231 [ + - ][ + - ]: 10 : nfo.emplace_back( infoDiagOrnsteinUhlenbeck( cnt ) );
232 [ + + ]: 50 : else if (d == ctr::DiffEqType::BETA)
233 [ + - ][ + - ]: 4 : nfo.emplace_back( infoBeta( cnt ) );
234 [ + + ]: 46 : else if (d == ctr::DiffEqType::NUMFRACBETA)
235 [ + - ][ + - ]: 4 : nfo.emplace_back( infoNumberFractionBeta( cnt ) );
236 [ + + ]: 42 : else if (d == ctr::DiffEqType::MASSFRACBETA)
237 [ + - ][ + - ]: 4 : nfo.emplace_back( infoMassFractionBeta( cnt ) );
238 [ - + ]: 38 : else if (d == ctr::DiffEqType::MIXNUMFRACBETA)
239 [ - - ][ - - ]: 0 : nfo.emplace_back( infoMixNumberFractionBeta( cnt ) );
240 [ + + ]: 38 : else if (d == ctr::DiffEqType::MIXMASSFRACBETA)
241 [ + - ][ + - ]: 5 : nfo.emplace_back( infoMixMassFractionBeta( cnt ) );
242 [ + + ]: 33 : else if (d == ctr::DiffEqType::SKEWNORMAL)
243 [ + - ][ + - ]: 10 : nfo.emplace_back( infoSkewNormal( cnt ) );
244 [ + + ]: 23 : else if (d == ctr::DiffEqType::GAMMA)
245 [ + - ][ + - ]: 4 : nfo.emplace_back( infoGamma( cnt ) );
246 [ + + ]: 19 : else if (d == ctr::DiffEqType::VELOCITY)
247 [ + - ][ + - ]: 7 : nfo.emplace_back( infoVelocity( cnt ) );
248 [ + + ]: 12 : else if (d == ctr::DiffEqType::POSITION)
249 [ + - ][ + - ]: 6 : nfo.emplace_back( infoPosition( cnt ) );
250 [ + - ]: 6 : else if (d == ctr::DiffEqType::DISSIPATION)
251 [ + - ][ + - ]: 6 : nfo.emplace_back( infoDissipation( cnt ) );
252 [ - - ][ - - ]: 0 : else Throw( "Can't find selected DiffEq" );
[ - - ][ - - ]
[ - - ][ - - ]
253 : : }
254 : :
255 : 74 : return nfo;
256 : : }
|