Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/Control/Inciter/InputDeck/Grammar.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 Inciter's input deck grammar definition
9 : : \details Inciter's input deck grammar definition. We use the Parsing
10 : : Expression Grammar Template Library (PEGTL) to create the grammar and the
11 : : associated parser. Word of advice: read from the bottom up.
12 : : */
13 : : // *****************************************************************************
14 : : #ifndef InciterInputDeckGrammar_h
15 : : #define InciterInputDeckGrammar_h
16 : :
17 : : #include <limits>
18 : : #include <cmath>
19 : :
20 : : #include "CommonGrammar.hpp"
21 : : #include "CartesianProduct.hpp"
22 : : #include "Keywords.hpp"
23 : : #include "ContainerUtil.hpp"
24 : : #include "Centering.hpp"
25 : : #include "PDE/MultiMat/MultiMatIndexing.hpp"
26 : :
27 : : namespace inciter {
28 : :
29 : : extern ctr::InputDeck g_inputdeck_defaults;
30 : :
31 : : //! Inciter input deck facilitating user input for computing shock hydrodynamics
32 : : namespace deck {
33 : :
34 : : //! \brief Specialization of tk::grm::use for Inciter's input deck parser
35 : : template< typename keyword >
36 : : using use = tk::grm::use< keyword, ctr::InputDeck::keywords >;
37 : :
38 : : // Inciter's InputDeck state
39 : :
40 : : //! \brief Number of registered equations
41 : : //! \details Counts the number of parsed equation blocks during parsing.
42 : : static tk::TaggedTuple< brigand::list<
43 : : tag::transport, std::size_t
44 : : , tag::compflow, std::size_t
45 : : , tag::multimat, std::size_t
46 : : > > neq;
47 : :
48 : : //! \brief Parser-lifetime storage for point names
49 : : //! \details Used to track the point names registered so that parsing new ones
50 : : //! can be required to be unique.
51 : : static std::set< std::string > pointnames;
52 : :
53 : : //! Parser-lifetime storage of elem or node centering
54 : : static tk::Centering centering = tk::Centering::NODE;
55 : :
56 : : //! Accepted multimat output variable labels and associated index functions
57 : : //! \details The keys are a list of characters accepted as labels for
58 : : //! denoting (matvar-style) output variables used for multi-material variable
59 : : //! output. We use a case- insesitive comparitor, since when this set is used
60 : : //! we only care about whether the variable is selected or not and not whether
61 : : //! it denotes a full variable (upper case) or a fluctuation (lower case).
62 : : //! This is true when matching these labels for output variables with
63 : : //! instantaenous variables as well terms of products in parsing requested
64 : : //! statistics (for turbulence). The values are associated indexing functions
65 : : //! used to index into the state of the multimaterial system, all must follow
66 : : //! the same signature.
67 : : static std::map< char, tk::MultiMatIdxFn,
68 : : tk::ctr::CaseInsensitiveCharLess >
69 : : multimatvars{
70 : : { 'd', densityIdx } // density
71 : : , { 'f', volfracIdx } // volume fraction
72 : : , { 'm', momentumIdx } // momentum
73 : : , { 'e', energyIdx } // specific total energy
74 : : , { 'u', velocityIdx } // velocity (primitive)
75 : : , { 'p', pressureIdx } // material pressure (primitive)
76 : : };
77 : :
78 : : } // ::deck
79 : : } // ::inciter
80 : :
81 : : namespace tk {
82 : : namespace grm {
83 : :
84 : : using namespace tao;
85 : :
86 : : // Note that PEGTL action specializations must be in the same namespace as the
87 : : // template being specialized. See http://stackoverflow.com/a/3052604.
88 : :
89 : : // Inciter's InputDeck actions
90 : :
91 : : //! Rule used to trigger action
92 : : template< class eq > struct register_inciter_eq : pegtl::success {};
93 : : //! \brief Register differential equation after parsing its block
94 : : //! \details This is used by the error checking functors (check_*) during
95 : : //! parsing to identify the recently-parsed block.
96 : : template< class eq >
97 : : struct action< register_inciter_eq< eq > > {
98 : : template< typename Input, typename Stack >
99 : : static void apply( const Input&, Stack& ) {
100 : : using inciter::deck::neq;
101 : 233 : ++neq.get< eq >();
102 : : }
103 : : };
104 : :
105 : : //! Rule used to trigger action
106 : : template< class eq > struct check_mesh : pegtl::success {};
107 : : //! \brief Check mesh ... end block for correctness
108 : : template< class eq >
109 : : struct action< check_mesh< eq > > {
110 : : template< typename Input, typename Stack >
111 [ - + ]: 233 : static void apply( const Input& in, Stack& stack ) {
112 : : using inciter::deck::neq;
113 : : auto& mesh = stack.template get< tag::param, eq, tag::mesh >();
114 : : auto& mesh_ref = mesh.template get< tag::reference >();
115 : : // if no mesh reference given by user
116 [ - + ][ - - ]: 233 : if (mesh_ref.empty() || mesh_ref.size() != neq.get< eq >()) {
117 : : // put in '-', meaning no reference
118 [ + - ]: 233 : mesh_ref.push_back('-');
119 : : auto& location = mesh.template get< tag::location >();
120 : : // if no location, put in the origin
121 [ + - ]: 233 : if (location.size() != neq.get< eq >())
122 [ + - ]: 466 : location.push_back( { 0.0, 0.0, 0.0 } );
123 : : else // reference was not given, but location was, error out
124 : 0 : Message< Stack, ERROR, MsgKey::LOC_NOMESHREF >( stack, in );
125 : : auto& orientation = mesh.template get< tag::orientation >();
126 [ + - ]: 233 : if (orientation.size() != neq.get< eq >())
127 [ + - ]: 466 : orientation.push_back( { 0.0, 0.0, 0.0 } );
128 : : else // reference was not given, but orientation was, error out
129 : 0 : Message< Stack, ERROR, MsgKey::ORI_NOMESHREF >( stack, in );
130 : : }
131 : :
132 : : // Ensure the number of depvars and the number of mesh references equal
133 : : const auto& depvar = stack.template get< tag::param, eq, tag::depvar >();
134 : : Assert( depvar.size() == mesh_ref.size(), "Mesh ref size mismatch" );
135 : :
136 : : // Ensure mesh ref var is not the same as the current depvar and is
137 : : // defined upstream in input file (by another solver)
138 [ - + ]: 233 : if ( mesh_ref.back() != '-' &&
139 [ - - ][ - - ]: 0 : (mesh_ref.back() == depvar.back() ||
140 : : depvars.find(mesh_ref.back()) == end(depvars)) )
141 : : {
142 : 0 : Message< Stack, ERROR, MsgKey::DEPVAR_AS_MESHREF >( stack, in );
143 : : }
144 : 233 : }
145 : : };
146 : :
147 : : //! Rule used to trigger action
148 : : template< class eq > struct check_transport : pegtl::success {};
149 : : //! \brief Set defaults and do error checking on the transport equation block
150 : : //! \details This is error checking that only the transport equation block
151 : : //! must satisfy. Besides error checking we also set defaults here as
152 : : //! this block is called when parsing of a transport...end block has
153 : : //! just finished.
154 : : template< class eq >
155 : : struct action< check_transport< eq > > {
156 : : template< typename Input, typename Stack >
157 [ + - ]: 126 : static void apply( const Input& in, Stack& stack ) {
158 : : using inciter::deck::neq;
159 : : using tag::param;
160 : :
161 : : // Error out if no dependent variable has been selected
162 : : auto& depvar = stack.template get< param, eq, tag::depvar >();
163 [ + - ][ - + ]: 126 : if (depvar.empty() || depvar.size() != neq.get< eq >())
164 : 0 : Message< Stack, ERROR, MsgKey::NODEPVAR >( stack, in );
165 : :
166 : : // If no number of components has been selected, default to 1
167 : : auto& ncomp = stack.template get< tag::component, eq >();
168 [ + + ][ - + ]: 126 : if (ncomp.empty() || ncomp.size() != neq.get< eq >())
169 : 86 : ncomp.push_back( 1 );
170 : :
171 : : // If physics type is not given, default to 'advection'
172 : : auto& physics = stack.template get< param, eq, tag::physics >();
173 [ + - ][ - + ]: 126 : if (physics.empty() || physics.size() != neq.get< eq >())
174 : 0 : physics.push_back( inciter::ctr::PhysicsType::ADVECTION );
175 : :
176 : : // If physics type is advection-diffusion, check for correct number of
177 : : // advection velocity, shear, and diffusion coefficients
178 [ + + ]: 126 : if (physics.back() == inciter::ctr::PhysicsType::ADVDIFF) {
179 : : auto& u0 = stack.template get< param, eq, tag::u0 >();
180 [ - + ]: 7 : if (u0.back().size() != ncomp.back()) // must define 1 component
181 : 0 : Message< Stack, ERROR, MsgKey::WRONGSIZE >( stack, in );
182 : : auto& diff = stack.template get< param, eq, tag::diffusivity >();
183 [ - + ]: 7 : if (diff.back().size() != 3*ncomp.back()) // must define 3 components
184 : 0 : Message< Stack, ERROR, MsgKey::WRONGSIZE >( stack, in );
185 : : auto& lambda = stack.template get< param, eq, tag::lambda >();
186 [ - + ]: 7 : if (lambda.back().size() != 2*ncomp.back()) // must define 2 shear comps
187 : 0 : Message< Stack, ERROR, MsgKey::WRONGSIZE >( stack, in );
188 : : }
189 : : // If problem type is not given, error out
190 : : auto& problem = stack.template get< param, eq, tag::problem >();
191 [ + - ][ - + ]: 126 : if (problem.empty() || problem.size() != neq.get< eq >())
192 : 0 : Message< Stack, ERROR, MsgKey::NOPROBLEM >( stack, in );
193 : : // Error check Dirichlet boundary condition block for all transport eq
194 : : // configurations
195 : : const auto& bc = stack.template get< param, eq, tag::bc, tag::bcdir >();
196 [ + + ]: 162 : for (const auto& s : bc)
197 [ - + ]: 36 : if (s.empty()) Message< Stack, ERROR, MsgKey::BC_EMPTY >( stack, in );
198 : :
199 : : // If interface compression is not specified, default to 'false'
200 : : auto& intsharp = stack.template get< param, eq, tag::intsharp >();
201 [ - + ][ - - ]: 126 : if (intsharp.empty() || intsharp.size() != neq.get< eq >())
202 : 126 : intsharp.push_back( 0 );
203 : :
204 : : // If interface compression parameter is not specified, default to 1.0
205 : : auto& intsharp_p = stack.template get< param, eq,
206 : : tag::intsharp_param >();
207 [ - + ][ - - ]: 126 : if (intsharp_p.empty() || intsharp_p.size() != neq.get< eq >())
208 : 126 : intsharp_p.push_back( 1.0 );
209 : 126 : }
210 : : };
211 : :
212 : : //! Rule used to trigger action
213 : : template< class eq > struct check_compflow : pegtl::success {};
214 : : //! \brief Set defaults and do error checking on the compressible flow
215 : : //! equation block
216 : : //! \details This is error checking that only the compressible flow equation
217 : : //! block must satisfy. Besides error checking we also set defaults here as
218 : : //! this block is called when parsing of a compflow...end block has
219 : : //! just finished.
220 : : template< class eq >
221 : : struct action< check_compflow< eq > > {
222 : : template< typename Input, typename Stack >
223 [ + - ]: 95 : static void apply( const Input& in, Stack& stack ) {
224 : : using inciter::deck::neq;
225 : : using tag::param;
226 : :
227 : : // Error out if no dependent variable has been selected
228 : : auto& depvar = stack.template get< param, eq, tag::depvar >();
229 [ + - ][ - + ]: 95 : if (depvar.empty() || depvar.size() != neq.get< eq >())
230 : 0 : Message< Stack, ERROR, MsgKey::NODEPVAR >( stack, in );
231 : :
232 : : // If physics type is not given, default to 'euler'
233 : : auto& physics = stack.template get< param, eq, tag::physics >();
234 [ + - ][ - + ]: 95 : if (physics.empty() || physics.size() != neq.get< eq >()) {
235 : 0 : physics.push_back( inciter::ctr::PhysicsType::EULER );
236 : : }
237 : :
238 : : // Set number of components to 5 (mass, 3 x mom, energy)
239 [ + + ]: 95 : stack.template get< tag::component, eq >().push_back( 5 );
240 : :
241 : : // Set default to sysfct (on/off) if not specified
242 : : auto& sysfct = stack.template get< param, eq, tag::sysfct >();
243 [ + + ][ - + ]: 95 : if (sysfct.empty() || sysfct.size() != neq.get< eq >())
244 : 71 : sysfct.push_back( 1 );
245 : :
246 : : // Set default flux to HLLC if not specified
247 : : auto& flux = stack.template get< tag::param, eq, tag::flux >();
248 [ + + ][ - + ]: 95 : if (flux.empty() || flux.size() != neq.get< eq >())
249 : 93 : flux.push_back( inciter::ctr::FluxType::HLLC );
250 : :
251 : : // Verify that sysfctvar variables are within bounds (if specified) and
252 : : // defaults if not
253 : : auto& sysfctvar = stack.template get< param, eq, tag::sysfctvar >();
254 : : // If sysfctvar is not specified, use all variables for system FCT
255 [ - + ][ - - ]: 95 : if (sysfctvar.empty() || sysfctvar.back().empty()) {
256 [ + - ]: 190 : sysfctvar.push_back( {0,1,2,3,4} );
257 : : } else { // if specified, do error checking on variables
258 : : auto& vars = sysfctvar.back();
259 [ - - ]: 0 : if (vars.size() > 5) {
260 : 0 : Message< Stack, ERROR, MsgKey::SYSFCTVAR >( stack, in );
261 : : }
262 [ - - ]: 0 : for (const auto& i : vars) {
263 [ - - ]: 0 : if (i > 4) Message< Stack, ERROR, MsgKey::SYSFCTVAR >( stack, in );
264 : : }
265 : : }
266 : :
267 : : // Verify correct number of material properties configured
268 : 95 : auto& matprop = stack.template get< param, eq, tag::material >().back()[0];
269 : : auto& matidxmap = stack.template get< param, eq, tag::matidxmap >();
270 : 95 : matidxmap.template get< tag::eosidx >().resize(1);
271 : 95 : matidxmap.template get< tag::matidx >().resize(1);
272 : : auto& meos = matprop.template get< tag::eos >();
273 : : auto& mat_id = matprop.template get< tag::id >();
274 : :
275 [ + - ]: 95 : if (mat_id.empty())
276 : 95 : mat_id.push_back(0);
277 [ - - ]: 0 : else if (mat_id.size() != 1)
278 : 0 : Message< Stack, ERROR, MsgKey::NUMMAT >( stack, in );
279 : : else
280 : 0 : mat_id[0] = 0;
281 : :
282 [ + - ]: 95 : if (meos == inciter::ctr::MaterialType::STIFFENEDGAS) {
283 : : const auto& gamma = matprop.template get< tag::gamma >();
284 : : // If gamma vector is wrong size, error out
285 [ + - ][ - + ]: 95 : if (gamma.empty() || gamma.size() != 1)
286 : 0 : Message< Stack, ERROR, MsgKey::EOSGAMMA >( stack, in );
287 : :
288 : : auto& cv = matprop.template get< tag::cv >();
289 : : // As a default, the specific heat of air (717.5 J/Kg-K) is used
290 [ + + ]: 95 : if (cv.empty())
291 : 93 : cv.push_back(717.5);
292 : : // If specific heat vector is wrong size, error out
293 [ - + ]: 95 : if (cv.size() != 1)
294 : 0 : Message< Stack, ERROR, MsgKey::EOSCV >( stack, in );
295 : :
296 : : auto& pstiff = matprop.template get< tag::pstiff >();
297 : : // As a default, a stiffness coefficient of 0.0 is used
298 [ + - ]: 95 : if (pstiff.empty())
299 : 95 : pstiff.push_back(0.0);
300 : : // If stiffness coefficient vector is wrong size, error out
301 [ - + ]: 95 : if (pstiff.size() != 1)
302 : 0 : Message< Stack, ERROR, MsgKey::EOSPSTIFF >( stack, in );
303 : : }
304 : :
305 : : // Generate mapping between material index and eos parameter index
306 : : auto& eosmap = matidxmap.template get< tag::eosidx >();
307 : : auto& idxmap = matidxmap.template get< tag::matidx >();
308 [ + + ]: 95 : eosmap[mat_id[0]] = static_cast< std::size_t >(matprop.template get<
309 : : tag::eos >());
310 [ + + ]: 95 : idxmap[mat_id[0]] = 0;
311 : :
312 : : // If problem type is not given, default to 'user_defined'
313 : : auto& problem = stack.template get< param, eq, tag::problem >();
314 [ + + ][ + - ]: 95 : if (problem.empty() || problem.size() != neq.get< eq >())
315 : 5 : problem.push_back( inciter::ctr::ProblemType::USER_DEFINED );
316 [ + + ]: 90 : else if (problem.back() == inciter::ctr::ProblemType::VORTICAL_FLOW) {
317 : : const auto& alpha = stack.template get< param, eq, tag::alpha >();
318 : : const auto& beta = stack.template get< param, eq, tag::beta >();
319 : : const auto& p0 = stack.template get< param, eq, tag::p0 >();
320 [ + - ][ + - ]: 27 : if ( alpha.size() != problem.size() ||
321 [ + - ][ + - ]: 27 : beta.size() != problem.size() ||
[ - + ]
322 [ - + ]: 27 : p0.size() != problem.size() )
323 : 0 : Message< Stack, ERROR, MsgKey::VORTICAL_UNFINISHED >( stack, in );
324 : : }
325 [ + + ]: 63 : else if (problem.back() == inciter::ctr::ProblemType::NL_ENERGY_GROWTH) {
326 : : const auto& alpha = stack.template get< param, eq, tag::alpha >();
327 : : const auto& betax = stack.template get< param, eq, tag::betax >();
328 : : const auto& betay = stack.template get< param, eq, tag::betay >();
329 : : const auto& betaz = stack.template get< param, eq, tag::betaz >();
330 : : const auto& kappa = stack.template get< param, eq, tag::kappa >();
331 : : const auto& r0 = stack.template get< param, eq, tag::r0 >();
332 : : const auto& ce = stack.template get< param, eq, tag::ce >();
333 [ + - ][ + - ]: 12 : if ( alpha.size() != problem.size() ||
334 [ + - ][ + - ]: 12 : betax.size() != problem.size() ||
335 [ + - ][ + - ]: 12 : betay.size() != problem.size() ||
336 [ + - ][ + - ]: 12 : betaz.size() != problem.size() ||
337 [ + - ][ + - ]: 12 : kappa.size() != problem.size() ||
338 [ + - ][ + - ]: 24 : r0.size() != problem.size() ||
[ - + ]
339 [ - + ]: 12 : ce.size() != problem.size() )
340 : 0 : Message< Stack, ERROR, MsgKey::ENERGY_UNFINISHED >( stack, in);
341 : : }
342 [ + + ]: 51 : else if (problem.back() == inciter::ctr::ProblemType::RAYLEIGH_TAYLOR) {
343 : : const auto& alpha = stack.template get< param, eq, tag::alpha >();
344 : : const auto& betax = stack.template get< param, eq, tag::betax >();
345 : : const auto& betay = stack.template get< param, eq, tag::betay >();
346 : : const auto& betaz = stack.template get< param, eq, tag::betaz >();
347 : : const auto& kappa = stack.template get< param, eq, tag::kappa >();
348 : : const auto& p0 = stack.template get< param, eq, tag::p0 >();
349 : : const auto& r0 = stack.template get< param, eq, tag::r0 >();
350 [ + - ][ + - ]: 4 : if ( alpha.size() != problem.size() ||
351 [ + - ][ + - ]: 4 : betax.size() != problem.size() ||
352 [ + - ][ + - ]: 4 : betay.size() != problem.size() ||
353 [ + - ][ + - ]: 4 : betaz.size() != problem.size() ||
354 [ + - ][ + - ]: 4 : kappa.size() != problem.size() ||
355 [ + - ][ + - ]: 8 : p0.size() != problem.size() ||
[ - + ]
356 [ - + ]: 4 : r0.size() != problem.size() )
357 : 0 : Message< Stack, ERROR, MsgKey::RT_UNFINISHED >( stack, in);
358 : : }
359 : :
360 : : // Error check on user-defined problem type
361 : : auto& ic = stack.template get< param, eq, tag::ic >();
362 : : auto& bgdensityic = ic.template get< tag::density >();
363 : : auto& bgvelocityic = ic.template get< tag::velocity >();
364 : : auto& bgpressureic = ic.template get< tag::pressure >();
365 : : auto& bgenergyic = ic.template get< tag::energy >();
366 : : auto& bgtemperatureic = ic.template get< tag::temperature >();
367 [ + + ]: 95 : if (problem.back() == inciter::ctr::ProblemType::USER_DEFINED) {
368 : : // must have defined background ICs for user-defined ICs
369 : 7 : auto n = neq.get< eq >();
370 [ + - ][ + - ]: 7 : if ( bgdensityic.size() != n || bgvelocityic.size() != n ||
[ - + ]
371 [ - + ][ - - ]: 7 : ( bgpressureic.size() != n && bgenergyic.size() != n &&
[ - - ]
372 [ - - ]: 0 : bgtemperatureic.size() != n ) )
373 : : {
374 : 0 : Message< Stack, ERROR, MsgKey::BGICMISSING >( stack, in );
375 : : }
376 : :
377 : : // Error check Dirichlet boundary condition block for all compflow
378 : : // configurations
379 : : const auto& bc = stack.template get< param, eq, tag::bc, tag::bcdir >();
380 [ - + ]: 7 : for (const auto& s : bc)
381 [ - - ]: 0 : if (s.empty()) Message< Stack, ERROR, MsgKey::BC_EMPTY >( stack, in );
382 : :
383 : : // Error check stagnation BC block
384 : : const auto& stag = stack.template get<tag::param, eq, tag::stag>();
385 : : const auto& spoint = stag.template get< tag::point >();
386 : : const auto& sradius = stag.template get< tag::radius >();
387 [ - - ][ - - ]: 0 : if ( (!spoint.empty() && !spoint.back().empty() &&
388 [ - - ]: 0 : !sradius.empty() && !sradius.back().empty() &&
389 [ - - ]: 0 : spoint.back().size() != 3*sradius.back().size())
390 [ - + ][ - - ]: 7 : || (!sradius.empty() && !sradius.back().empty() &&
[ - - ]
391 [ - - ]: 0 : !spoint.empty() && !spoint.back().empty() &&
392 [ - - ]: 0 : spoint.back().size() != 3*sradius.back().size())
393 [ - + ][ - - ]: 7 : || (!spoint.empty() && !spoint.back().empty() &&
[ - - ]
394 [ - - ]: 0 : (sradius.empty() || (!sradius.empty() && sradius.back().empty())))
395 [ - + ][ - + ]: 14 : || (!sradius.empty() && !sradius.back().empty() &&
[ - - ][ - - ]
396 [ - - ]: 0 : (spoint.empty() || (!spoint.empty() && spoint.back().empty()))) )
397 : : {
398 : 0 : Message< Stack, ERROR, MsgKey::STAGBCWRONG >( stack, in );
399 : : }
400 : :
401 : : // Error check skip BC block
402 : : const auto& skip = stack.template get<tag::param, eq, tag::skip>();
403 : : const auto& kpoint = skip.template get< tag::point >();
404 : : const auto& kradius = skip.template get< tag::radius >();
405 [ - - ][ - - ]: 0 : if ( (!kpoint.empty() && !kpoint.back().empty() &&
406 [ - - ]: 0 : !kradius.empty() && !kradius.back().empty() &&
407 [ - - ]: 0 : kpoint.back().size() != 3*kradius.back().size())
408 [ - + ][ - - ]: 7 : || (!kradius.empty() && !kradius.back().empty() &&
[ - - ]
409 [ - - ]: 0 : !kpoint.empty() && !kpoint.back().empty() &&
410 [ - - ]: 0 : kpoint.back().size() != 3*kradius.back().size())
411 [ - + ][ - - ]: 7 : || (!kpoint.empty() && !kpoint.back().empty() &&
[ - - ]
412 [ - - ]: 0 : (kradius.empty() || (!kradius.empty() && kradius.back().empty())))
413 [ - + ][ - + ]: 14 : || (!kradius.empty() && !kradius.back().empty() &&
[ - - ][ - - ]
414 [ - - ]: 0 : (kpoint.empty() || (!kpoint.empty() && kpoint.back().empty()))) )
415 : : {
416 : 0 : Message< Stack, ERROR, MsgKey::SKIPBCWRONG >( stack, in );
417 : : }
418 : :
419 : : // Error check sponge BC parameter vectors for symmetry BC block
420 : : const auto& sponge =
421 : : stack.template get< tag::param, eq, tag::sponge >();
422 : : const auto& ss = sponge.template get< tag::sideset >();
423 : :
424 : : const auto& spvel = sponge.template get< tag::velocity >();
425 [ - + ][ - - ]: 7 : if ( !spvel.empty() && !spvel.back().empty()) {
426 [ - - ]: 0 : if (spvel.back().size() != ss.back().size())
427 : 0 : Message< Stack, ERROR, MsgKey::SPONGEBCWRONG >( stack, in );
428 [ - - ]: 0 : for (const auto& s : spvel.back())
429 [ - - ][ - - ]: 0 : if ( s < 0.0 || s > 1.0 )
430 : 0 : Message< Stack, ERROR, MsgKey::SPONGEBCWRONG >( stack, in );
431 : : }
432 : :
433 : : const auto& sppre = sponge.template get< tag::velocity >();
434 [ - + ][ - - ]: 7 : if ( !sppre.empty() && !sppre.back().empty()) {
435 [ - - ]: 0 : if (sppre.back().size() != ss.back().size())
436 : 0 : Message< Stack, ERROR, MsgKey::SPONGEBCWRONG >( stack, in );
437 [ - - ]: 0 : for (const auto& s : sppre.back())
438 [ - - ][ - - ]: 0 : if ( s < 0.0 || s > 1.0 )
439 : 0 : Message< Stack, ERROR, MsgKey::SPONGEBCWRONG >( stack, in );
440 : : }
441 : :
442 : : // Error check user defined time dependent BC for this system
443 : : const auto& tdepbc =
444 : : stack.template get< tag::param, eq, tag::bctimedep >().back();
445 : : // multiple time dependent BCs can be specified on different side sets
446 [ + + ]: 8 : for (const auto& bndry : tdepbc) {
447 : : const auto& s = bndry.template get< tag::sideset >();
448 [ - + ]: 1 : if (s.empty()) Message< Stack, ERROR, MsgKey::BC_EMPTY >( stack, in );
449 : : const auto& f = bndry.template get< tag::fn >();
450 [ + - ][ - + ]: 1 : if (f.empty() or f.size() % 6 != 0)
451 : 0 : Message< Stack, ERROR, MsgKey::INCOMPLETEUSERFN>( stack, in );
452 : : }
453 : : }
454 : 95 : }
455 : : };
456 : :
457 : : //! Rule used to trigger action
458 : : template< class eq > struct check_multimat : pegtl::success {};
459 : : //! \brief Set defaults and do error checking on the multimaterial
460 : : //! compressible flow equation block
461 : : //! \details This is error checking that only the multimaterial compressible
462 : : //! flow equation block must satisfy. Besides error checking we also set
463 : : //! defaults here as this block is called when parsing of a
464 : : //! multimat...end block has just finished.
465 : : template< class eq >
466 : : struct action< check_multimat< eq > > {
467 : : template< typename Input, typename Stack >
468 [ + - ]: 12 : static void apply( const Input& in, Stack& stack ) {
469 : : using inciter::deck::neq;
470 : : using tag::param;
471 : :
472 : : // Error out if no dependent variable has been selected
473 : : auto& depvar = stack.template get< param, eq, tag::depvar >();
474 [ + - ][ - + ]: 12 : if (depvar.empty() || depvar.size() != neq.get< eq >())
475 : 0 : Message< Stack, ERROR, MsgKey::NODEPVAR >( stack, in );
476 : :
477 : : // If physics type is not given, default to 'veleq'
478 : : auto& physics = stack.template get< param, eq, tag::physics >();
479 [ + - ][ - + ]: 12 : if (physics.empty() || physics.size() != neq.get< eq >())
480 : 0 : physics.push_back( inciter::ctr::PhysicsType::VELEQ );
481 : :
482 : : // Set default flux to AUSM if not specified
483 : : auto& flux = stack.template get< tag::param, eq, tag::flux >();
484 [ - + ][ - - ]: 12 : if (flux.empty() || flux.size() != neq.get< eq >())
485 : 12 : flux.push_back( inciter::ctr::FluxType::AUSM );
486 : :
487 : : // Set number of scalar components based on number of materials
488 : : auto& nmat = stack.template get< param, eq, tag::nmat >();
489 : : auto& ncomp = stack.template get< tag::component, eq >();
490 [ + - ]: 12 : if (physics.back() == inciter::ctr::PhysicsType::VELEQ) {
491 : : // physics = veleq: m-material compressible flow
492 : : // scalar components: volfrac:m + mass:m + momentum:3 + energy:m
493 : : // if nmat is unspecified, configure it be 2
494 [ + - ][ - + ]: 12 : if (nmat.empty() || nmat.size() != neq.get< eq >()) {
495 : 0 : Message< Stack, WARNING, MsgKey::NONMAT >( stack, in );
496 : 0 : nmat.push_back( 2 );
497 : : }
498 : : // set ncomp based on nmat
499 : 12 : auto m = nmat.back();
500 : 12 : ncomp.push_back( m + m + 3 + m );
501 : : }
502 : :
503 : : // Verify correct number of multi-material properties (gamma, cv, pstiff)
504 : : // have been configured
505 : : auto& matprop = stack.template get< param, eq, tag::material >();
506 : : auto& matidxmap = stack.template get< param, eq, tag::matidxmap >();
507 : 12 : matidxmap.template get< tag::eosidx >().resize(nmat.back());
508 : 12 : matidxmap.template get< tag::matidx >().resize(nmat.back());
509 : : std::size_t tmat(0), i(0);
510 : : std::set< std::size_t > matidset;
511 : :
512 [ + + ]: 24 : for (auto& mtype : matprop.back()) {
513 : : const auto& meos = mtype.template get< tag::eos >();
514 : : const auto& mat_id = mtype.template get< tag::id >();
515 : :
516 [ + - ]: 12 : if (meos == inciter::ctr::MaterialType::STIFFENEDGAS) {
517 : : const auto& gamma = mtype.template get< tag::gamma >();
518 : : // If gamma vector is wrong size, error out
519 [ + - ][ - + ]: 12 : if (gamma.empty() || gamma.size() != mat_id.size())
520 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::EOSGAMMA >( stack, in );
521 : :
522 : : auto& cv = mtype.template get< tag::cv >();
523 : : // As a default, the specific heat of air (717.5 J/Kg-K) is used
524 [ + + ]: 12 : if (cv.empty()) {
525 [ + + ]: 21 : for (std::size_t k=0; k<mat_id.size(); ++k) {
526 [ + - ]: 14 : cv.push_back(717.5);
527 : : }
528 : : }
529 : : // If specific heat vector is wrong size, error out
530 [ - + ]: 12 : if (cv.size() != mat_id.size())
531 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::EOSCV >( stack, in );
532 : :
533 : : auto& pstiff = mtype.template get< tag::pstiff >();
534 : : // As a default, a stiffness coefficient of 0.0 is used
535 [ + + ]: 12 : if (pstiff.empty()) {
536 [ + + ]: 29 : for (std::size_t k=0; k<mat_id.size(); ++k) {
537 [ + - ]: 20 : pstiff.push_back(0.0);
538 : : }
539 : : }
540 : : // If stiffness coefficient vector is wrong size, error out
541 [ - + ]: 12 : if (pstiff.size() != mat_id.size())
542 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::EOSPSTIFF >( stack, in );
543 : : }
544 : :
545 : : // Track total number of materials in multiple material blocks
546 : 12 : tmat += mat_id.size();
547 : :
548 : : // Check for repeating user specified material ids
549 [ + + ]: 38 : for (auto midx : mat_id) {
550 : : if (!matidset.count(midx))
551 : : matidset.insert(midx);
552 : : else
553 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::REPMATID >( stack, in );
554 : : }
555 : :
556 : : // Generate mapping between material index and eos parameter index
557 : : auto& eosmap = matidxmap.template get< tag::eosidx >();
558 : : auto& idxmap = matidxmap.template get< tag::matidx >();
559 [ + + ]: 38 : for (auto midx : mat_id) {
560 : 26 : midx -= 1;
561 : 26 : eosmap[midx] = static_cast< std::size_t >(mtype.template get<
562 : : tag::eos >());
563 : 26 : idxmap[midx] = i;
564 : 26 : ++i;
565 : : }
566 : : // end of materials for this eos, thus reset index counter
567 : : i = 0;
568 : : }
569 : :
570 : : // If total number of materials is incorrect, error out
571 [ - + ]: 12 : if (tmat != nmat.back())
572 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::NUMMAT >( stack, in );
573 : :
574 : : // Check if material ids are contiguous and 1-based
575 : : if (!matidset.count(1))
576 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::ONEMATID >( stack, in );
577 : : std::size_t icount(1);
578 [ + + ]: 38 : for (auto midx : matidset) {
579 [ - + ]: 26 : if (midx != icount)
580 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::GAPMATID >( stack, in );
581 : 26 : ++icount;
582 : : }
583 : :
584 : : // If pressure relaxation is not specified, default to 'false'
585 : : auto& prelax = stack.template get< param, eq, tag::prelax >();
586 [ + + ][ - + ]: 12 : if (prelax.empty() || prelax.size() != neq.get< eq >())
587 [ + - ]: 9 : prelax.push_back( 0 );
588 : :
589 : : // If pressure relaxation time-scale is not specified, default to 1.0
590 : : auto& prelax_ts = stack.template get< param, eq,
591 : : tag::prelax_timescale >();
592 [ + + ][ - + ]: 12 : if (prelax_ts.empty() || prelax_ts.size() != neq.get< eq >())
593 [ + - ]: 9 : prelax_ts.push_back( 1.0 );
594 : :
595 : : // If interface compression is not specified, default to 'false'
596 : : auto& intsharp = stack.template get< param, eq, tag::intsharp >();
597 [ + + ][ - + ]: 12 : if (intsharp.empty() || intsharp.size() != neq.get< eq >())
598 [ + - ]: 10 : intsharp.push_back( 0 );
599 : :
600 : : // If interface compression parameter is not specified, default to 1.0
601 : : auto& intsharp_p = stack.template get< param, eq,
602 : : tag::intsharp_param >();
603 [ + + ][ - + ]: 12 : if (intsharp_p.empty() || intsharp_p.size() != neq.get< eq >())
604 [ + - ]: 10 : intsharp_p.push_back( 1.0 );
605 : :
606 : : // If problem type is not given, default to 'user_defined'
607 : : auto& problem = stack.template get< param, eq, tag::problem >();
608 [ + - ][ + - ]: 12 : if (problem.empty() || problem.size() != neq.get< eq >())
609 [ - - ]: 0 : problem.push_back( inciter::ctr::ProblemType::USER_DEFINED );
610 [ - + ]: 12 : else if (problem.back() == inciter::ctr::ProblemType::VORTICAL_FLOW) {
611 : : const auto& alpha = stack.template get< param, eq, tag::alpha >();
612 : : const auto& beta = stack.template get< param, eq, tag::beta >();
613 : : const auto& p0 = stack.template get< param, eq, tag::p0 >();
614 [ - - ][ - - ]: 0 : if ( alpha.size() != problem.size() ||
615 [ - - ][ - - ]: 0 : beta.size() != problem.size() ||
[ - - ]
616 [ - - ]: 0 : p0.size() != problem.size() )
617 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::VORTICAL_UNFINISHED >( stack, in );
618 : : }
619 : :
620 : : // Error check on user-defined problem type
621 : : auto& ic = stack.template get< param, eq, tag::ic >();
622 : : auto& bgmatid = ic.template get< tag::materialid >();
623 : : auto& bgdensityic = ic.template get< tag::density >();
624 : : auto& bgvelocityic = ic.template get< tag::velocity >();
625 : : auto& bgpressureic = ic.template get< tag::pressure >();
626 : : auto& bgenergyic = ic.template get< tag::energy >();
627 : : auto& bgtemperatureic = ic.template get< tag::temperature >();
628 [ - + ]: 12 : if (problem.back() == inciter::ctr::ProblemType::USER_DEFINED) {
629 : : // must have defined background ICs for user-defined ICs
630 : 0 : auto n = neq.get< eq >();
631 [ - - ]: 0 : if (bgmatid.size() != n) {
632 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::BGMATIDMISSING >( stack, in );
633 : : }
634 : :
635 [ - - ][ - - ]: 0 : if ( bgdensityic.size() != n || bgvelocityic.size() != n ||
[ - - ]
636 [ - - ][ - - ]: 0 : ( bgpressureic.size() != n && bgenergyic.size() != n &&
[ - - ]
637 [ - - ]: 0 : bgtemperatureic.size() != n ) )
638 : : {
639 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::BGICMISSING >( stack, in );
640 : : }
641 : :
642 : : // each IC box should have material id specified, and it should be
643 : : // within nmat
644 : : auto& icbox = ic.template get< tag::box >();
645 : :
646 [ - - ]: 0 : if (!icbox.empty()) {
647 [ - - ]: 0 : for (const auto& b : icbox.back()) { // for all boxes
648 : 0 : auto boxmatid = b.template get< tag::materialid >();
649 [ - - ]: 0 : if (boxmatid == 0) {
650 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::BOXMATIDMISSING >( stack, in );
651 : : }
652 [ - - ]: 0 : else if (boxmatid > nmat.back()) {
653 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::BOXMATIDWRONG >( stack, in );
654 : : }
655 : : }
656 : : }
657 : : }
658 : :
659 : : // Error check Dirichlet boundary condition block for all multimat
660 : : // configurations
661 : : const auto& bc = stack.template get< param, eq, tag::bc, tag::bcdir >();
662 [ + + ]: 14 : for (const auto& s : bc)
663 [ - + ][ - - ]: 2 : if (s.empty()) Message< Stack, ERROR, MsgKey::BC_EMPTY >( stack, in );
664 : 12 : }
665 : : };
666 : :
667 : : //! Rule used to trigger action
668 : : template< class Option, typename...tags >
669 : : struct store_inciter_option : pegtl::success {};
670 : : //! \brief Put option in state at position given by tags
671 : : //! \details This is simply a wrapper around tk::grm::store_option passing the
672 : : //! stack defaults for inciter.
673 : : template< class Option, typename... tags >
674 : : struct action< store_inciter_option< Option, tags... > > {
675 : : template< typename Input, typename Stack >
676 : : static void apply( const Input& in, Stack& stack ) {
677 : : store_option< Stack, inciter::deck::use, Option, inciter::ctr::InputDeck,
678 : : Input, tags... >
679 [ - - ][ + - ]: 539 : ( stack, in, inciter::g_inputdeck_defaults );
[ + - ][ + - ]
[ + - ][ - - ]
[ + - ][ + - ]
[ + - ]
680 : : }
681 : : };
682 : :
683 : : //! Function object to ensure disjoint side sets for all boundary conditions
684 : : //! \details This is instantiated using a Cartesian product of all PDE types
685 : : //! and all BC types at compile time. It goes through all side sets
686 : : //! configured by the user and triggers an error if a side set is assigned
687 : : //! a BC more than once (within a solver).
688 : : template< typename Input, typename Stack >
689 : : struct ensure_disjoint {
690 : : const Input& m_input;
691 : : Stack& m_stack;
692 : : explicit ensure_disjoint( const Input& in, Stack& stack ) :
693 : : m_input( in ), m_stack( stack ) {}
694 : 4194 : template< typename U > void operator()( brigand::type_<U> ) {
695 : : using Eq = typename brigand::front< U >;
696 : : using BC = typename brigand::back< U >;
697 : 4194 : const auto& bc = m_stack.template get< tag::param, Eq, tag::bc, BC >();
698 [ + + ]: 4459 : for (const auto& eq : bc) {
699 : : std::unordered_set< int > bcset;
700 [ + + ]: 982 : for (const auto& s : eq) {
701 : 717 : auto id = std::stoi(s);
702 [ - + ]: 717 : if (bcset.find(id) != end(bcset))
703 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::NONDISJOINTBC >( m_stack, m_input );
704 : : else
705 : : bcset.insert( id );
706 : : }
707 : : }
708 : 4194 : }
709 : : };
710 : :
711 : : //! Function object to count the number of meshes assigned to solvers
712 : : //! \details This is instantiated for all PDE types at compile time. It goes
713 : : //! through all configured solvers (equation system configuration blocks)
714 : : //! and counts the number of mesh filenames configured.
715 : : template< typename Stack >
716 : : struct count_meshes {
717 : : const Stack& stack;
718 : : std::size_t& count;
719 : : explicit
720 : : count_meshes( const Stack& s, std::size_t& c ) : stack(s), count(c) {}
721 : : template< typename eq > void operator()( brigand::type_<eq> ) {
722 : : count +=
723 : : stack.template get< tag::param, eq, tag::mesh, tag::filename >().size();
724 : : }
725 : : };
726 : :
727 : : //! Function object to assign mesh ids to solvers
728 : : //! \details This is instantiated for all PDE types at compile time. It goes
729 : : //! through all configured solvers (equation system configuration blocks)
730 : : //! and assigns a new mesh id to all solvers configured in the input file.
731 : : template< typename Stack >
732 : : struct assign_meshid {
733 : : Stack& stack;
734 : : std::size_t& meshid;
735 : : explicit assign_meshid( Stack& s, std::size_t& m ) : stack(s), meshid(m) {}
736 : : template< typename eq > void operator()( brigand::type_<eq> ) {
737 : : const auto& eq_mesh_filename =
738 : : stack.template get< tag::param, eq, tag::mesh, tag::filename >();
739 : : auto& id = stack.template get< tag::param, eq, tag::mesh, tag::id >();
740 : : for (std::size_t i=0; i<eq_mesh_filename.size(); ++i)
741 : : id.push_back( meshid++ );
742 : : }
743 : : };
744 : :
745 : : //! Rule used to trigger action
746 : : struct configure_scheme : pegtl::success {};
747 : : //! Configure scheme selected by user
748 : : //! \details This grammar action configures the number of degrees of freedom
749 : : //! (NDOF) used for DG methods. For finite volume (or DGP0), the DOF are the
750 : : //! cell-averages. This implies ndof=1 for DGP0. Similarly, ndof=4 and 10 for
751 : : //! DGP1 and DGP2 respectively, since they evolve higher (>1) order solution
752 : : //! information (e.g. gradients) as well. "rdof" includes degrees of freedom
753 : : //! that are both, evolved and reconstructed. For rDGPnPm methods (e.g. P0P1
754 : : //! and P1P2), "n" denotes the evolved solution-order and "m" denotes the
755 : : //! reconstructed solution-order; i.e. P0P1 has ndof=1 and rdof=4, whereas
756 : : //! P1P2 has ndof=4 and rdof=10. For a pure DG method without reconstruction
757 : : //! (DGP0, DGP1, DGP2), rdof=ndof. For more information about rDGPnPm methods,
758 : : //! ref. Luo, H. et al. (2013). A reconstructed discontinuous Galerkin method
759 : : //! based on a hierarchical WENO reconstruction for compressible flows on
760 : : //! tetrahedral grids. Journal of Computational Physics, 236, 477-492.
761 : : template<> struct action< configure_scheme > {
762 : : template< typename Input, typename Stack >
763 : : static void apply( const Input&, Stack& stack ) {
764 : : using inciter::ctr::SchemeType;
765 : : auto& discr = stack.template get< tag::discr >();
766 : : auto& ndof = discr.template get< tag::ndof >();
767 : : auto& rdof = discr.template get< tag::rdof >();
768 : 204 : auto scheme = discr.template get< tag::scheme >();
769 [ + + ]: 204 : if (scheme == SchemeType::P0P1) {
770 : 8 : ndof = 1; rdof = 4;
771 [ + + ]: 196 : } else if (scheme == SchemeType::DGP1) {
772 : 16 : ndof = rdof = 4;
773 [ + + ]: 180 : } else if (scheme == SchemeType::DGP2) {
774 : 10 : ndof = rdof = 10;
775 [ + + ]: 170 : } else if (scheme == SchemeType::PDG) {
776 : 12 : ndof = rdof = 10;
777 : 12 : stack.template get< tag::pref, tag::pref >() = true;
778 : : }
779 : : }
780 : : };
781 : :
782 : : //! Function object to do error checking on output time ranges
783 : : template< typename Stack, typename Input >
784 : : struct range_errchk {
785 : : Stack& stack;
786 : : const Input& input;
787 : : explicit range_errchk( Stack& s, const Input& in ) : stack(s), input(in) {}
788 : 466 : template< typename U > void operator()( brigand::type_<U> ) {
789 [ + + ]: 468 : for (const auto& r : stack.template get< tag::output, tag::range, U >())
790 [ + - ][ + - ]: 2 : if ( r.size() != 3 or r[0] > r[1] or r[2] < 0.0 or r[2] > r[1]-r[0] )
[ + - ][ - + ]
791 : 0 : Message< Stack, ERROR, MsgKey::BADRANGE >( stack, input );
792 : 466 : }
793 : : };
794 : :
795 : : //! Rule used to trigger action
796 : : struct check_inciter : pegtl::success {};
797 : : //! \brief Do error checking on the inciter block
798 : : template<> struct action< check_inciter > {
799 : : template< typename Input, typename Stack >
800 : 233 : static void apply( const Input& in, Stack& stack ) {
801 : : using inciter::deck::neq;
802 : : using inciter::g_inputdeck_defaults;
803 : :
804 : : // Error out if no dt policy has been selected
805 : : const auto& dt = stack.template get< tag::discr, tag::dt >();
806 : : const auto& cfl = stack.template get< tag::discr, tag::cfl >();
807 [ + + ]: 233 : if ( std::abs(dt - g_inputdeck_defaults.get< tag::discr, tag::dt >()) <
808 [ + + ][ - + ]: 233 : std::numeric_limits< tk::real >::epsilon() &&
809 [ - + ]: 116 : std::abs(cfl - g_inputdeck_defaults.get< tag::discr, tag::cfl >()) <
810 : : std::numeric_limits< tk::real >::epsilon() )
811 : 0 : Message< Stack, ERROR, MsgKey::NODT >( stack, in );
812 : :
813 : : // If both dt and cfl are given, warn that dt wins over cfl
814 [ + + ]: 233 : if ( std::abs(dt - g_inputdeck_defaults.get< tag::discr, tag::dt >()) >
815 [ + + ][ - + ]: 233 : std::numeric_limits< tk::real >::epsilon() &&
816 [ - + ]: 117 : std::abs(cfl - g_inputdeck_defaults.get< tag::discr, tag::cfl >()) >
817 : : std::numeric_limits< tk::real >::epsilon() )
818 : 0 : Message< Stack, WARNING, MsgKey::MULDT >( stack, in );
819 : :
820 : : // Do error checking on time history points
821 : : const auto& hist = stack.template get< tag::history, tag::point >();
822 [ - + ]: 233 : if (std::any_of( begin(hist), end(hist),
823 [ - - ][ - - ]: 14 : [](const auto& p){ return p.size() != 3; } ) )
[ - - ][ - - ]
[ - - ][ - + ]
[ - + ]
824 : : {
825 : 0 : Message< Stack, ERROR, MsgKey::WRONGSIZE >( stack, in );
826 : : }
827 : :
828 : : // Do error checking on residual eq system component index
829 [ + - ]: 233 : const auto rc = stack.template get< tag::discr, tag::rescomp >();
830 : : const auto& ncomps = stack.template get< tag::component >();
831 [ + - ][ - + ]: 233 : if (rc < 1 || rc > ncomps.nprop())
832 : 0 : Message< Stack, ERROR, MsgKey::LARGECOMP >( stack, in );
833 : :
834 : : // Ensure no different BC types are assigned to the same side set
835 : : using PDETypes = inciter::ctr::parameters::Keys;
836 : : using BCTypes = inciter::ctr::bc::Keys;
837 : 233 : brigand::for_each< tk::cartesian_product< PDETypes, BCTypes > >(
838 : : ensure_disjoint< Input, Stack >( in, stack ) );
839 : :
840 : : // Do error checking on output time range configuration parameters: they
841 : : // all must be a 3 reals: mintime, maxtime, and dt with maxtime >
842 : : // mintime, and dt<maxtime-mintime.
843 : : brigand::for_each< inciter::ctr::time_range::Keys >
844 : : ( range_errchk< Stack, Input >( stack, in ) );
845 : :
846 : : // Do error checking on time history point names (this is a programmer
847 : : // error if triggers, hence assert)
848 : : Assert(
849 : : (stack.template get< tag::history, tag::id >().size() == hist.size()),
850 : : "Number of history points and ids must equal" );
851 : :
852 : : // If at least a mesh filename is assigned to a solver, all solvers must
853 : : // have a mesh filename assigned
854 : 233 : std::size_t nmesh = 0;
855 : 233 : brigand::for_each< PDETypes >( count_meshes< Stack >( stack, nmesh ) );
856 [ + + ][ - + ]: 233 : if (nmesh > 0 && nmesh != depvars.size())
857 : 0 : Message< Stack, ERROR, MsgKey::MULTIMESH >( stack, in );
858 : :
859 : : // Remove duplicate transfer steps
860 : 233 : tk::unique( stack.template get< tag::couple, tag::transfer >() );
861 : :
862 : : // Now that the inciter ... end block is finished, assign mesh ids to
863 : : // solvers configured
864 : 233 : std::size_t meshid = 0;
865 : : brigand::for_each< PDETypes >( assign_meshid< Stack >( stack, meshid ) );
866 : : Assert( meshid == nmesh, "Not all meshes configured have mesh ids" );
867 : 233 : }
868 : : };
869 : :
870 : : //! Rule used to trigger action
871 : : struct check_ale : pegtl::success {};
872 : : //! \brief Do error checking on the inciter block
873 : : template<> struct action< check_ale > {
874 : : template< typename Input, typename Stack >
875 : 10 : static void apply( const Input& in, Stack& stack ) {
876 : : using inciter::g_inputdeck_defaults;
877 : :
878 : : // Trigger error if steady state + ALE are both enabled
879 : 10 : auto steady = stack.template get< tag::discr, tag::steady_state >();
880 : 10 : auto ale = stack.template get< tag::ale, tag::ale >();
881 [ - + ]: 10 : if (steady && ale) {
882 : 0 : Message< Stack, ERROR, MsgKey::STEADYALE >( stack, in );
883 : : }
884 : :
885 : : // Set a sensible default for dvCFL if ALE is enabled and if dvcfl not set
886 : : auto& dvcfl = stack.template get< tag::ale, tag::dvcfl >();
887 : 10 : auto dvcfl_default = g_inputdeck_defaults.get< tag::ale, tag::dvcfl >();
888 : : auto eps = std::numeric_limits< tk::real >::epsilon();
889 [ + - ][ - + ]: 10 : if (ale && std::abs(dvcfl - dvcfl_default) < eps) dvcfl = 0.01;
890 : :
891 : : // Set a default of zeros for the mesh force ALE parameters
892 : : auto& meshforce = stack.template get< tag::ale, tag::meshforce >();
893 [ + - ][ + - ]: 10 : if (ale && meshforce.size() != 4) meshforce = { 0, 0, 0, 0 };
894 : :
895 : : // Set a default for the ALE mesh motion dimensions
896 : : auto& mesh_motion = stack.template get< tag::ale, tag::mesh_motion >();
897 [ + - ][ + + ]: 10 : if (ale && mesh_motion.empty()) mesh_motion = { 0, 1, 2 };
898 : :
899 : : // Error out if mesh motion dimensions are wrong
900 [ + - ][ + - ]: 20 : if (ale && (mesh_motion.size() > 3 ||
[ - + ]
901 : : std::any_of( begin(mesh_motion), end(mesh_motion),
902 : : [](auto d){return d > 2;} )) )
903 : : {
904 : 0 : Message< Stack, ERROR, MsgKey::WRONGMESHMOTION >( stack, in );
905 : : }
906 : :
907 : : // Error checking on user-defined function for ALE's moving sides
908 : : const auto& move = stack.template get< tag::ale, tag::move >();
909 [ + + ]: 12 : for (const auto& s : move) {
910 : : const auto& f = s.template get< tag::fn >();
911 [ + - ][ - + ]: 2 : if (f.empty() or f.size() % 4 != 0)
912 : 0 : Message< Stack, ERROR, MsgKey::INCOMPLETEUSERFN>( stack, in );
913 : : }
914 : 10 : }
915 : : };
916 : :
917 : : //! Rule used to trigger action
918 : : template< typename Feature >
919 : : struct enable : pegtl::success {};
920 : : //! Enable adaptive mesh refinement (AMR)
921 : : template< typename Feature >
922 : : struct action< enable< Feature > > {
923 : : template< typename Input, typename Stack >
924 : : static void apply( const Input&, Stack& stack ) {
925 [ + - ][ + - ]: 52 : stack.template get< Feature, Feature >() = true;
926 : : }
927 : : };
928 : :
929 : : //! Rule used to trigger action
930 : : struct compute_refvar_idx : pegtl::success {};
931 : : //! Compute indices of refinement variables
932 : : //! \details This functor computes the indices in the unknown vector for all
933 : : //! refinement variables in the system of systems of dependent variables
934 : : //! after the refvar...end block has been parsed in the amr...end block.
935 : : //! After basic error checking, the vector at stack.get<tag::amr,tag::id>()
936 : : //! is filled.
937 : : template<>
938 : : struct action< compute_refvar_idx > {
939 : : template< typename Input, typename Stack >
940 : 33 : static void apply( const Input& in, Stack& stack ) {
941 : : // reference variables just parsed by refvar...end block
942 : : const auto& refvar = stack.template get< tag::amr, tag::refvar >();
943 : : // get ncomponents object from this input deck
944 : : const auto& ncomps = stack.template get< tag::component >();
945 : : // compute offset map associating offsets to dependent variables
946 : 33 : auto offsetmap = ncomps.offsetmap( stack );
947 : : // compute number of components associated to dependent variabels
948 [ + - ]: 33 : auto ncompmap = ncomps.ncompmap( stack );
949 : : // reference variable index vector to fill
950 : : auto& refidx = stack.template get< tag::amr, tag::id >();
951 : : // Compute indices for all refvars
952 [ + + ]: 66 : for (const auto& v : refvar) { // for all reference variables parsed
953 : : // depvar is the first char of a refvar
954 : 33 : auto depvar = v[0];
955 : : // the field ID is optional and is the rest of the depvar string
956 [ - + ][ - - ]: 33 : std::size_t f = (v.size()>1 ? std::stoul(v.substr(1)) : 1) - 1;
[ - - ][ - - ]
957 : : // field ID must be less than or equal to the number of scalar
958 : : // components configured for the eq system for this dependent variable
959 [ - + ]: 33 : if (f >= tk::cref_find( ncompmap, depvar ))
960 [ - - ]: 0 : Message< Stack, ERROR, MsgKey::NOSUCHCOMPONENT >( stack, in );
961 : : // get offset for depvar
962 : 33 : auto eqsys_offset = tk::cref_find( offsetmap, depvar );
963 : : // the index is the eq offset + field ID
964 : 33 : auto idx = eqsys_offset + f;
965 : : // save refvar index in system of all systems
966 [ + - ]: 33 : refidx.push_back( idx );
967 : : }
968 : 33 : }
969 : : };
970 : :
971 : : //! Rule used to trigger action
972 : : struct check_amr_errors : pegtl::success {};
973 : : //! Do error checking for the amr...end block
974 : : //! \details This is error checking that only the amr...end block
975 : : //! must satisfy. Besides error checking this can also set defaults
976 : : //! as this block is called when parsing of a amr...end block has
977 : : //! just finished.
978 : : template<>
979 : : struct action< check_amr_errors > {
980 : : template< typename Input, typename Stack >
981 : 42 : static void apply( const Input& in, Stack& stack ) {
982 : : // Error out if refvar size does not equal refidx size (programmer error)
983 : : Assert( (stack.template get< tag::amr, tag::refvar >().size() ==
984 : : stack.template get< tag::amr, tag::id >().size()),
985 : : "The size of refvar and refidx vectors must equal" );
986 : : const auto& initref = stack.template get< tag::amr, tag::init >();
987 : : const auto& refvar = stack.template get< tag::amr, tag::refvar >();
988 : : const auto& edgelist = stack.template get< tag::amr, tag::edge >();
989 : : // Error out if initref edge list is not divisible by 2 (user error)
990 [ - + ]: 42 : if (edgelist.size() % 2 == 1)
991 : 0 : Message< Stack, ERROR, MsgKey::T0REFODD >( stack, in );
992 : : // Warn if initial AMR will be a no-op
993 [ + + ][ - + ]: 42 : if ( stack.template get< tag::amr, tag::t0ref >() && initref.empty() )
994 : 0 : Message< Stack, WARNING, MsgKey::T0REFNOOP >( stack, in );
995 : : // Error out if timestepping AMR will be a no-op (user error)
996 [ + + ][ - + ]: 42 : if ( stack.template get< tag::amr, tag::dtref >() && refvar.empty() )
997 : 0 : Message< Stack, ERROR, MsgKey::DTREFNOOP >( stack, in );
998 : : // Error out if mesh refinement frequency is zero (programmer error)
999 : : Assert( (stack.template get< tag::amr, tag::dtfreq >() > 0),
1000 : : "Mesh refinement frequency must be positive" );
1001 : 42 : }
1002 : : };
1003 : :
1004 : : //! Rule used to trigger action
1005 : : struct check_pref_errors : pegtl::success {};
1006 : : //! Do error checking for the pref...end block
1007 : : template<>
1008 : : struct action< check_pref_errors > {
1009 : : template< typename Input, typename Stack >
1010 : : static void apply( const Input& in, Stack& stack ) {
1011 : : auto& tolref = stack.template get< tag::pref, tag::tolref >();
1012 [ + - ][ - + ]: 12 : if (tolref < 0.0 || tolref > 1.0)
1013 : 0 : Message< Stack, ERROR, MsgKey::PREFTOL >( stack, in );
1014 : : }
1015 : : };
1016 : :
1017 : : //! Rule used to trigger action
1018 : : struct match_pointname : pegtl::success {};
1019 : : //! \brief Match PDF name to the registered ones
1020 : : //! \details This is used to check the set of PDF names dependent previously
1021 : : //! registered to make sure all are unique.
1022 : : template<>
1023 : : struct action< match_pointname > {
1024 : : template< typename Input, typename Stack >
1025 : 14 : static void apply( const Input& in, Stack& stack ) {
1026 : : using inciter::deck::pointnames;
1027 : : // find matched name in set of registered ones
1028 [ + - ]: 14 : if (pointnames.find( in.string() ) == pointnames.end()) {
1029 : 14 : pointnames.insert( in.string() );
1030 : 14 : stack.template get< tag::history, tag::id >().push_back( in.string() );
1031 : : }
1032 : : else // error out if name matched var is already registered
1033 : 0 : Message< Stack, ERROR, MsgKey::POINTEXISTS >( stack, in );
1034 : 14 : }
1035 : : };
1036 : :
1037 : : //! Rule used to trigger action
1038 : : struct push_depvar : pegtl::success {};
1039 : : //! Add matched outvar based on depvar into vector of outvars
1040 : : //! \details Push outvar based on depvar: use first char of matched token as
1041 : : //! OutVar::var, OutVar::name = "" by default. OutVar::name being empty will
1042 : : //! be used to differentiate a depvar-based outvar from a human-readable
1043 : : //! outvar. Depvar-based outvars can directly access solution arrays using
1044 : : //! their field. Human-readable outvars need a mechanism (a function) to read
1045 : : //! and compute their variables from solution arrays. The 'getvar' function,
1046 : : //! used to compute a physics variable from the numerical solution is assigned
1047 : : //! after initial migration and thus not assigned here (during parsing).
1048 : : template<>
1049 : : struct action< push_depvar > {
1050 : : template< typename Input, typename Stack >
1051 [ + - ]: 59 : static void apply( const Input& in, Stack& stack ) {
1052 : : using inciter::deck::centering;
1053 : : using inciter::ctr::OutVar;
1054 : : auto& vars = stack.template get< tag::cmd, tag::io, tag::outvar >();
1055 [ + - ][ + - ]: 118 : vars.emplace_back(OutVar(in.string()[0], field, centering));
[ + - ][ - + ]
[ - + ][ - + ]
[ - + ][ - - ]
[ - - ][ - - ]
[ - - ]
1056 : 59 : field = 0; // reset field
1057 : 59 : }
1058 : : };
1059 : :
1060 : : //! Rule used to trigger action
1061 : : struct push_matvar : pegtl::success {};
1062 : : //! Add matched outvar based on matvar into vector of outvars
1063 : : //! \details Push outvar based on matvar: use depvar char as OutVar::var,
1064 : : //! OutVar::name = "" by default. Matvar-based outvars are similar to
1065 : : //! depvar-base outvars, in that the OutVar has empty name and the OutVar::var
1066 : : //! is a depvar, but instead of having the user try to guess the field id, the
1067 : : //! grammar accepts a physics label (accepted multimatvars) and a material
1068 : : //! index, which are then converted to a depvar + field index.
1069 : : template<>
1070 : : struct action< push_matvar > {
1071 : : template< typename Input, typename Stack >
1072 : 26 : static void apply( const Input& in, Stack& stack ) {
1073 : : using tag::param;
1074 : : using tag::multimat;
1075 : : using inciter::deck::centering;
1076 : : using inciter::deck::multimatvars;
1077 : : using inciter::ctr::OutVar;
1078 : : auto& vars = stack.template get< tag::cmd, tag::io, tag::outvar >();
1079 : 26 : auto nmat = stack.template get< param, multimat, tag::nmat >().back();
1080 : 26 : auto depvar = stack.template get< param, multimat, tag::depvar >().back();
1081 : : // first char of matched token: accepted multimatvar label char
1082 [ - + ]: 26 : char v = static_cast<char>( in.string()[0] );
1083 : : // Since multimat outvars are configured based on an acceptable character
1084 : : // label (see inciter::deck::multimatvars, denoting a physics variable),
1085 : : // and a material index (instead of a depvar + a component index),
1086 : : // multimat material bounds are checked here. Note that for momentum and
1087 : : // velocity, the field id is the spatial direction not the material id.
1088 : : // Also note that field (in grammar's state) starts from 0.
1089 [ + - ][ + - ]: 26 : if ( ((v=='u'||v=='U'||v=='m'||v=='M') && field>2) ||
[ - + ][ - - ]
1090 [ + - ][ + - ]: 26 : ((v!='u'&&v!='U'&&v!='m'&&v!='M') && field>=nmat) )
[ + - ][ - + ]
1091 : 0 : Message< Stack, ERROR, MsgKey::NOSUCHCOMPONENT >( stack, in );
1092 : : // field contains material id, compute multiat component index
1093 [ - + ]: 26 : auto comp = tk::cref_find( multimatvars, v )( nmat, field );
1094 : : // save depvar + component index based on physics label + material id,
1095 : : // also save physics label + material id as matvar
1096 [ + - ][ + - ]: 26 : vars.emplace_back(
[ + - ][ - + ]
[ - + ][ - + ]
[ - + ][ - - ]
[ - - ][ - - ]
[ - - ]
1097 : : OutVar(depvar, comp, centering, {}, {}, v+std::to_string(field+1)) );
1098 : 26 : field = 0; // reset field
1099 : 26 : }
1100 : : };
1101 : :
1102 : : //! Function object for adding a human-readable output variable
1103 : : //! \details Since human-readable outvars do not necessarily have any
1104 : : //! reference to the depvar of their system they refer to, nor which system
1105 : : //! they refer to, we configure them for all of the systems they are preceded
1106 : : //! by. If there is only a single system of the type the outvar is configured,
1107 : : //! we simply look up the depvar and use that as OutVar::var. If there are
1108 : : //! multiple systems configured upstream to which the outvar could refer to,
1109 : : //! we configure an outvar for all systems configured, and postfix the
1110 : : //! human-readable OutVar::name with '_' + depvar. Hence this function object
1111 : : //! so the code below can be invoked for all equation types.
1112 : : template< typename Stack >
1113 : : struct AddOutVarHuman {
1114 : : Stack& stack;
1115 : : const std::string& in_string;
1116 : : explicit AddOutVarHuman( Stack& s, const std::string& ins )
1117 : : : stack(s), in_string(ins) {}
1118 : 2256 : template< typename Eq > void operator()( brigand::type_<Eq> ) {
1119 : : using inciter::deck::centering;
1120 : : using inciter::ctr::OutVar;
1121 [ + + ]: 2256 : const auto& depvar = stack.template get< tag::param, Eq, tag::depvar >();
1122 : : auto& vars = stack.template get< tag::cmd, tag::io, tag::outvar >();
1123 [ + + ]: 2256 : if (depvar.size() == 1)
1124 [ + - ][ + - ]: 752 : vars.emplace_back( OutVar( depvar[0], 0, centering, in_string ) );
[ - + ][ - + ]
[ - - ][ - - ]
1125 : : else
1126 [ - + ][ - - ]: 1504 : for (auto d : depvar)
1127 [ - - ][ - - ]: 0 : vars.emplace_back( OutVar( d, 0, centering, in_string + '_' + d ) );
[ - - ][ - - ]
[ - - ][ - - ]
[ - - ][ - - ]
[ - - ][ - - ]
[ - - ][ - - ]
1128 : 2256 : }
1129 : : };
1130 : :
1131 : : //! Rule used to trigger action
1132 : : struct push_humanvar : pegtl::success {};
1133 : : //! Add matched outvar based on depvar into vector of vector of outvars
1134 : : //! \details Push outvar based on human readable string for which
1135 : : //! OutVar::name = matched token. OutVar::name being not empty will be used to
1136 : : //! differentiate a depvar-based outvar from a human-readable outvar.
1137 : : //! Depvar-based outvars can directly access solution arrays using their
1138 : : //! field. Human-readable outvars need a mechanism (a function) to read and
1139 : : //! compute their variables from solution arrays. The 'getvar' function, used
1140 : : //! to compute a physics variable from the numerical solution is assigned
1141 : : //! after initial migration and thus not assigned here (during parsing).
1142 : : template<>
1143 : : struct action< push_humanvar > {
1144 : : template< typename Input, typename Stack >
1145 : 752 : static void apply( const Input& in, Stack& stack ) {
1146 : : brigand::for_each< inciter::ctr::parameters::Keys >
1147 : 752 : ( AddOutVarHuman< Stack >( stack, in.string() ) );
1148 : 752 : }
1149 : : };
1150 : :
1151 : : //! Rule used to trigger action
1152 : : struct set_outvar_alias : pegtl::success {};
1153 : : //! Set alias of last pushed output variable
1154 : : template<>
1155 : : struct action< set_outvar_alias > {
1156 : : template< typename Input, typename Stack >
1157 [ + - ]: 658 : static void apply( const Input& in, Stack& stack ) {
1158 : : // Set alias of last pushed outvar:
1159 : : auto& vars = stack.template get< tag::cmd, tag::io, tag::outvar >();
1160 [ + - ]: 1974 : if (!vars.empty()) vars.back().alias = in.string();
1161 : 658 : }
1162 : : };
1163 : :
1164 : : //! Function object for error checking outvar bounds for each equation type
1165 : : template< typename Stack >
1166 : : struct OutVarBounds {
1167 : : const Stack& stack;
1168 : : bool& inbounds;
1169 : : explicit OutVarBounds( const Stack& s, bool& i )
1170 : 85 : : stack(s), inbounds(i) { inbounds = false; }
1171 : 170 : template< typename U > void operator()( brigand::type_<U> ) {
1172 : 85 : if (std::is_same_v< U, tag::multimat >) inbounds = true; // skip multimat
1173 : 170 : const auto& depvar = stack.template get< tag::param, U, tag::depvar >();
1174 : : const auto& ncomp = stack.template get< tag::component, U >();
1175 : : Assert( depvar.size() == ncomp.size(), "Size mismatch" );
1176 : : // called after matching each outvar, so only check the last one
1177 : : auto& vars = stack.template get< tag::cmd, tag::io, tag::outvar >();
1178 : : const auto& last_outvar = vars.back();
1179 : 170 : const auto& v = static_cast<char>( std::tolower(last_outvar.var) );
1180 [ + + ]: 340 : for (std::size_t e=0; e<depvar.size(); ++e)
1181 [ + - ][ + - ]: 59 : if (v == depvar[e] && last_outvar.field < ncomp[e]) inbounds = true;
1182 : 170 : }
1183 : : };
1184 : :
1185 : : //! Rule used to trigger action
1186 : : struct check_outvar : pegtl::success {};
1187 : : //! Bounds checking for output variables at the end of a var ... end block
1188 : : template<>
1189 : : struct action< check_outvar > {
1190 : : template< typename Input, typename Stack >
1191 : 85 : static void apply( const Input& in, Stack& stack ) {
1192 : : bool inbounds;
1193 : : brigand::for_each< inciter::ctr::parameters::Keys >
1194 : : ( OutVarBounds< Stack >( stack, inbounds ) );
1195 [ - + ]: 85 : if (!inbounds)
1196 : 0 : Message< Stack, ERROR, MsgKey::NOSUCHCOMPONENT >( stack, in );
1197 : 85 : }
1198 : : };
1199 : :
1200 : : //! Rule used to trigger action
1201 : : struct set_centering : pegtl::success {};
1202 : : //! Set variable centering in parser's state
1203 : : template<>
1204 : : struct action< set_centering > {
1205 : : template< typename Input, typename Stack >
1206 : : static void apply( const Input& in, Stack& ) {
1207 : : inciter::deck::centering =
1208 : : (in.string() == "node") ? tk::Centering::NODE : tk::Centering::ELEM;
1209 : : }
1210 : : };
1211 : :
1212 : : //! Rule used to trigger action
1213 : : struct match_outvar : pegtl::success {};
1214 : : //! Match output variable based on depvar
1215 : : template<>
1216 : : struct action< match_outvar > {
1217 : : template< typename Input, typename Stack >
1218 : 85 : static void apply( const Input& in, Stack& stack ) {
1219 : : using inciter::deck::neq;
1220 : : using inciter::deck::multimatvars;
1221 : : // convert matched string to char
1222 [ + - ][ - + ]: 85 : auto var = stack.template convert< char >( in.string() );
1223 [ + + ]: 85 : if (neq.get< tag::multimat >() == 0) { // if not multimat
1224 : : // find matched variable in set of selected ones
1225 [ + - ]: 59 : if (depvars.find(var) != end(depvars))
1226 : 59 : action< push_depvar >::apply( in, stack );
1227 : : else // error out if matched var is not selected
1228 : 0 : Message< Stack, ERROR, MsgKey::NOSUCHOUTVAR >( stack, in );
1229 : : } else { // if multimat
1230 : : // find matched variable in set accepted for multimat
1231 [ + - ]: 26 : if (multimatvars.find(var) != end(multimatvars))
1232 : 26 : action< push_matvar >::apply( in, stack );
1233 : : else
1234 : 0 : Message< Stack, ERROR, MsgKey::NOSUCHMULTIMATVAR >( stack, in );
1235 : : }
1236 : 85 : }
1237 : : };
1238 : :
1239 : : // Store mesh/solver id as a source of a transfer
1240 : : template< typename Stack > struct store_transfer_src {
1241 : : store_transfer_src( Stack& stack, std::size_t i ) {
1242 [ - - ]: 0 : stack.template get< tag::couple, tag::transfer >().emplace_back( i, 0 );
1243 : : }
1244 : : };
1245 : :
1246 : : // Store mesh/solver id as a destination of a transfer
1247 : : template< typename Stack > struct store_transfer_dst {
1248 : : store_transfer_dst( Stack& stack, std::size_t i ) {
1249 : 0 : stack.template get< tag::couple, tag::transfer >().back().dst = i;
1250 : : }
1251 : : };
1252 : :
1253 : : //! Rule used to trigger action
1254 : : template< template< class > class StoreTransfer >
1255 : : struct push_transfer : pegtl::success {};
1256 : : //! Add matched value as a source or destination of solution transfer
1257 : : //! \tparam StoreTransfer Type of action to invoke: source or destination
1258 : : template< template< class > class StoreTransfer >
1259 : : struct action< push_transfer< StoreTransfer > > {
1260 : : template< typename Input, typename Stack >
1261 : 0 : static void apply( const Input& in, Stack& stack ) {
1262 : : // Extract dependent variables for solvers configured
1263 : 0 : auto depvar = stack.depvar();
1264 : : // Store index of parsed depvar of transfer being configured
1265 [ - - ]: 0 : auto c = in.string()[0];
1266 [ - - ]: 0 : for (std::size_t i=0; i<depvar.size(); ++i)
1267 [ - - ]: 0 : if (depvar[i] == c)
1268 : 0 : StoreTransfer< Stack >( stack, i );
1269 : 0 : }
1270 : : };
1271 : :
1272 : : } // ::grm
1273 : : } // ::tk
1274 : :
1275 : : namespace inciter {
1276 : :
1277 : : //! Inciter input deck facilitating user input for computing shock hydrodynamics
1278 : : namespace deck {
1279 : :
1280 : : using namespace tao;
1281 : :
1282 : : // Inciter's InputDeck grammar
1283 : :
1284 : : //! scan and store_back equation keyword and option
1285 : : template< typename keyword, class eq >
1286 : : struct scan_eq :
1287 : : tk::grm::scan< typename keyword::pegtl_string,
1288 : : tk::grm::store_back_option< use,
1289 : : ctr::PDE,
1290 : : tag::selected,
1291 : : tag::pde > > {};
1292 : :
1293 : : //! Error checks after an equation...end block has been parsed
1294 : : template< class eq, template< class > class eqchecker >
1295 : : struct check_errors :
1296 : : pegtl::seq<
1297 : : // register differential equation block
1298 : : tk::grm::register_inciter_eq< eq >,
1299 : : // check mesh ... end block
1300 : : tk::grm::check_mesh< eq >,
1301 : : // do error checking on this block
1302 : : eqchecker< eq > > {};
1303 : :
1304 : : //! Match discretization option
1305 : : template< template< class > class use, class keyword, class Option,
1306 : : class Tag >
1307 : : struct discroption :
1308 : : tk::grm::process< use< keyword >,
1309 : : tk::grm::store_inciter_option<
1310 : : Option, tag::discr, Tag >,
1311 : : pegtl::alpha > {};
1312 : :
1313 : : //! Discretization parameters
1314 : : struct discretization :
1315 : : pegtl::sor<
1316 : : tk::grm::discrparam< use, kw::nstep, tag::nstep >,
1317 : : tk::grm::discrparam< use, kw::term, tag::term >,
1318 : : tk::grm::discrparam< use, kw::t0, tag::t0 >,
1319 : : tk::grm::discrparam< use, kw::dt, tag::dt >,
1320 : : tk::grm::discrparam< use, kw::cfl, tag::cfl >,
1321 : : tk::grm::discrparam< use, kw::residual, tag::residual >,
1322 : : tk::grm::discrparam< use, kw::rescomp, tag::rescomp >,
1323 : : tk::grm::process< use< kw::fcteps >,
1324 : : tk::grm::Store< tag::discr, tag::fcteps > >,
1325 : : tk::grm::process< use< kw::fctclip >,
1326 : : tk::grm::Store< tag::discr, tag::fctclip >,
1327 : : pegtl::alpha >,
1328 : : tk::grm::process< use< kw::fct >,
1329 : : tk::grm::Store< tag::discr, tag::fct >,
1330 : : pegtl::alpha >,
1331 : : tk::grm::process< use< kw::ctau >,
1332 : : tk::grm::Store< tag::discr, tag::ctau > >,
1333 : : tk::grm::process< use< kw::pelocal_reorder >,
1334 : : tk::grm::Store< tag::discr, tag::pelocal_reorder >,
1335 : : pegtl::alpha >,
1336 : : tk::grm::process< use< kw::operator_reorder >,
1337 : : tk::grm::Store< tag::discr, tag::operator_reorder >,
1338 : : pegtl::alpha >,
1339 : : tk::grm::process< use< kw::steady_state >,
1340 : : tk::grm::Store< tag::discr, tag::steady_state >,
1341 : : pegtl::alpha >,
1342 : : tk::grm::interval_iter< use< kw::ttyi >,
1343 : : tag::output, tag::iter, tag::tty >,
1344 : : tk::grm::process_alpha< use< kw::scheme >,
1345 : : tk::grm::store_inciter_option<
1346 : : inciter::ctr::Scheme,
1347 : : tag::discr,
1348 : : tag::scheme >,
1349 : : tk::grm::configure_scheme >,
1350 : : discroption< use, kw::limiter, inciter::ctr::Limiter, tag::limiter >,
1351 : : tk::grm::discrparam< use, kw::cweight, tag::cweight >
1352 : : > {};
1353 : :
1354 : : //! PDE parameter vector
1355 : : template< class keyword, class eq, class param, class... xparams >
1356 : : struct pde_parameter_vector :
1357 : : tk::grm::parameter_vector< use,
1358 : : use< keyword >,
1359 : : tk::grm::Store_back_back,
1360 : : tk::grm::start_vector,
1361 : : tk::grm::check_vector,
1362 : : eq, param, xparams... > {};
1363 : :
1364 : : //! Match box parameter
1365 : : template< class eq, typename keyword, typename target >
1366 : : struct box_parameter :
1367 : : pegtl::if_must<
1368 : : tk::grm::readkw< typename use<keyword>::pegtl_string >,
1369 : : tk::grm::scan<
1370 : : pegtl::sor< tk::grm::number,
1371 : : tk::grm::msg< tk::grm::ERROR,
1372 : : tk::grm::MsgKey::MISSING > >,
1373 : : tk::grm::Back_back_store< target,
1374 : : tag::param, eq, tag::ic, tag::box > > > {};
1375 : :
1376 : : //! Match box parameter and store deep
1377 : : template< class eq, typename keyword, typename target, typename subtarget >
1378 : : struct box_deep_parameter :
1379 : : pegtl::if_must<
1380 : : tk::grm::readkw< typename use<keyword>::pegtl_string >,
1381 : : tk::grm::scan<
1382 : : pegtl::sor< tk::grm::number,
1383 : : tk::grm::msg< tk::grm::ERROR,
1384 : : tk::grm::MsgKey::MISSING > >,
1385 : : tk::grm::Back_back_deep_store< target, subtarget,
1386 : : tag::param, eq, tag::ic, tag::box > > > {};
1387 : :
1388 : : //! Match box parameter vector
1389 : : template< class eq, typename keyword, typename target >
1390 : : struct box_vector :
1391 : : tk::grm::vector< use< keyword >,
1392 : : tk::grm::Back_back_store_back< target,
1393 : : tag::param, eq, tag::ic, tag::box >,
1394 : : use< kw::end > > {};
1395 : :
1396 : : //! Match box parameter vector and store deep
1397 : : template< class eq, typename keyword, typename target, typename subtarget >
1398 : : struct box_deep_vector :
1399 : : tk::grm::vector< use< keyword >,
1400 : : tk::grm::Back_back_deep_store_back< target, subtarget,
1401 : : tag::param, eq, tag::ic, tag::box >,
1402 : : use< kw::end > > {};
1403 : :
1404 : :
1405 : : //! Match box option
1406 : : template< class eq, typename Option, typename keyword, typename target,
1407 : : typename subtarget >
1408 : : struct box_option :
1409 : : tk::grm::process<
1410 : : use< keyword >,
1411 : : tk::grm::back_back_deep_store_option< target, subtarget, use,
1412 : : Option, tag::param, eq, tag::ic, tag::box >,
1413 : : pegtl::alpha > {};
1414 : :
1415 : : //! Match material option
1416 : : template< class eq, typename Option, typename keyword, typename target >
1417 : : struct material_option :
1418 : : tk::grm::process<
1419 : : use< keyword >,
1420 : : tk::grm::back_back_store_option< target, use, Option,
1421 : : tag::param, eq, tag::material >,
1422 : : pegtl::alpha > {};
1423 : :
1424 : : //! Match material parameter vector
1425 : : template< class eq, typename keyword, typename target >
1426 : : struct material_vector :
1427 : : tk::grm::vector< use< keyword >,
1428 : : tk::grm::Back_back_store_back< target,
1429 : : tag::param, eq, tag::material >,
1430 : : use< kw::end > > {};
1431 : :
1432 : : //! put in PDE parameter for equation matching keyword
1433 : : template< typename eq, typename keyword, typename param,
1434 : : class kw_type = tk::grm::number >
1435 : : struct parameter :
1436 : : tk::grm::process< use< keyword >,
1437 : : tk::grm::Store_back< tag::param, eq, param >,
1438 : : kw_type > {};
1439 : :
1440 : : //! put in PDE bool parameter for equation matching keyword into vector< int >
1441 : : template< typename eq, typename keyword, typename p >
1442 : : struct parameter_bool :
1443 : : tk::grm::process< use< keyword >,
1444 : : tk::grm::Store_back_bool< tag::param, eq, p >,
1445 : : pegtl::alpha > {};
1446 : :
1447 : : //! Boundary conditions block
1448 : : template< class keyword, class eq, class param >
1449 : : struct bc :
1450 : : pegtl::if_must<
1451 : : tk::grm::readkw< typename use< keyword >::pegtl_string >,
1452 : : tk::grm::block<
1453 : : use< kw::end >,
1454 : : tk::grm::parameter_vector< use,
1455 : : use< kw::sideset >,
1456 : : tk::grm::Store_back_back,
1457 : : tk::grm::start_vector,
1458 : : tk::grm::check_vector,
1459 : : eq, tag::bc, param > > > {};
1460 : :
1461 : : //! Match user-defined function as a discrete list of real numbers
1462 : : template< class target, template< class... > class insert, class tag,
1463 : : class... tags >
1464 : : struct user_fn :
1465 : : pegtl::if_must<
1466 : : tk::grm::readkw< use< kw::fn >::pegtl_string >,
1467 : : tk::grm::block< use< kw::end >,
1468 : : tk::grm::scan< tk::grm::number,
1469 : : insert< target, tag, tags... > > > > {};
1470 : :
1471 : : //! User defined time dependent BC bc_timedep...end block
1472 : : template< class eq >
1473 : : struct timedep_bc :
1474 : : pegtl::if_must<
1475 : : tk::grm::readkw< use< kw::bc_timedep >::pegtl_string >,
1476 : : tk::grm::start_vector_back< tag::param, eq, tag::bctimedep >,
1477 : : tk::grm::block< use< kw::end >,
1478 : : user_fn< tag::fn, tk::grm::Back_back_store_back, tag::param, eq,
1479 : : tag::bctimedep >,
1480 : : pegtl::if_must< tk::grm::vector< use< kw::sideset >,
1481 : : tk::grm::Back_back_store_back< tag::sideset, tag::param, eq,
1482 : : tag::bctimedep >,
1483 : : use< kw::end > > > > > {};
1484 : :
1485 : : //! Stagnation boundary conditions block
1486 : : template< class eq, class bc, class kwbc >
1487 : : struct bc_spec :
1488 : : pegtl::if_must<
1489 : : tk::grm::readkw< typename kwbc::pegtl_string >,
1490 : : tk::grm::block<
1491 : : use< kw::end >,
1492 : : tk::grm::parameter_vector< use,
1493 : : use< kw::radius >,
1494 : : tk::grm::Store_back_back,
1495 : : tk::grm::start_vector,
1496 : : tk::grm::check_vector,
1497 : : eq, bc, tag::radius >,
1498 : : tk::grm::parameter_vector< use,
1499 : : use< kw::point >,
1500 : : tk::grm::Store_back_back,
1501 : : tk::grm::start_vector,
1502 : : tk::grm::check_vector,
1503 : : eq, bc, tag::point > > > {};
1504 : :
1505 : : //! Boundary conditions block
1506 : : template< class eq >
1507 : : struct sponge :
1508 : : pegtl::if_must<
1509 : : tk::grm::readkw< typename use< kw::sponge >::pegtl_string >,
1510 : : tk::grm::block<
1511 : : use< kw::end >,
1512 : : tk::grm::parameter_vector< use,
1513 : : use< kw::velocity >,
1514 : : tk::grm::Store_back_back,
1515 : : tk::grm::start_vector,
1516 : : tk::grm::check_vector,
1517 : : eq, tag::sponge, tag::velocity >,
1518 : : tk::grm::parameter_vector< use,
1519 : : use< kw::pressure >,
1520 : : tk::grm::Store_back_back,
1521 : : tk::grm::start_vector,
1522 : : tk::grm::check_vector,
1523 : : eq, tag::sponge, tag::pressure >,
1524 : : tk::grm::parameter_vector< use,
1525 : : use< kw::sideset >,
1526 : : tk::grm::Store_back_back,
1527 : : tk::grm::start_vector,
1528 : : tk::grm::check_vector,
1529 : : eq, tag::sponge, tag::sideset > > > {};
1530 : :
1531 : : //! Farfield boundary conditions block
1532 : : template< class keyword, class eq, class param >
1533 : : struct farfield_bc :
1534 : : pegtl::if_must<
1535 : : tk::grm::readkw< typename use< keyword >::pegtl_string >,
1536 : : tk::grm::block<
1537 : : use< kw::end >,
1538 : : parameter< eq, kw::pressure, tag::farfield_pressure >,
1539 : : parameter< eq, kw::density, tag::farfield_density >,
1540 : : pde_parameter_vector< kw::velocity, eq,
1541 : : tag::farfield_velocity >,
1542 : : tk::grm::parameter_vector< use,
1543 : : use< kw::sideset >,
1544 : : tk::grm::Store_back_back,
1545 : : tk::grm::start_vector,
1546 : : tk::grm::check_vector,
1547 : : eq, tag::bc, param > > > {};
1548 : :
1549 : : //! edgelist ... end block
1550 : : struct edgelist :
1551 : : tk::grm::vector< use< kw::amr_edgelist >,
1552 : : tk::grm::Store_back< tag::amr, tag::edge >,
1553 : : use< kw::end >,
1554 : : tk::grm::check_vector< tag::amr, tag::edge > > {};
1555 : :
1556 : : //! xminus configuring coordinate-based edge tagging for mesh refinement
1557 : : template< typename keyword, typename Tag >
1558 : : struct half_world :
1559 : : tk::grm::control< use< keyword >, pegtl::digit, tk::grm::Store,
1560 : : tag::amr, Tag > {};
1561 : :
1562 : : //! coords ... end block
1563 : : struct coords :
1564 : : pegtl::if_must<
1565 : : tk::grm::readkw< use< kw::amr_coords >::pegtl_string >,
1566 : : tk::grm::block< use< kw::end >,
1567 : : half_world< kw::amr_xminus, tag::xminus >,
1568 : : half_world< kw::amr_xplus, tag::xplus >,
1569 : : half_world< kw::amr_yminus, tag::yminus >,
1570 : : half_world< kw::amr_yplus, tag::yplus >,
1571 : : half_world< kw::amr_zminus, tag::zminus >,
1572 : : half_world< kw::amr_zplus, tag::zplus > > > {};
1573 : :
1574 : : //! initial conditins box block
1575 : : template< class eq >
1576 : : struct box :
1577 : : pegtl::if_must<
1578 : : tk::grm::readkw< use< kw::box >::pegtl_string >,
1579 : : tk::grm::start_vector_back< tag::param, eq, tag::ic, tag::box >,
1580 : : tk::grm::block< use< kw::end >
1581 : : , box_parameter< eq, kw::xmin, tag::xmin >
1582 : : , box_parameter< eq, kw::xmax, tag::xmax >
1583 : : , box_parameter< eq, kw::ymin, tag::ymin >
1584 : : , box_parameter< eq, kw::ymax, tag::ymax >
1585 : : , box_parameter< eq, kw::zmin, tag::zmin >
1586 : : , box_parameter< eq, kw::zmax, tag::zmax >
1587 : : , box_parameter< eq, kw::materialid, tag::materialid >
1588 : : , box_parameter< eq, kw::density, tag::density >
1589 : : , box_parameter< eq, kw::pressure, tag::pressure >
1590 : : , box_parameter< eq, kw::temperature, tag::temperature >
1591 : : , box_parameter< eq, kw::energy_content, tag::energy_content >
1592 : : , box_parameter< eq, kw::energy, tag::energy >
1593 : : , box_parameter< eq, kw::mass, tag::mass >
1594 : : , box_vector< eq, kw::velocity, tag::velocity >
1595 : : , box_option< eq, ctr::Initiate, kw::initiate, tag::initiate,
1596 : : tag::init >
1597 : : , pegtl::if_must<
1598 : : tk::grm::readkw< use< kw::linear >::pegtl_string >,
1599 : : tk::grm::block< use< kw::end >
1600 : : , box_deep_vector< eq, kw::point, tag::initiate, tag::point >
1601 : : , box_deep_parameter< eq, kw::radius, tag::initiate,
1602 : : tag::radius >
1603 : : , box_deep_parameter< eq, kw::velocity, tag::initiate,
1604 : : tag::velocity > > >
1605 : : > > {};
1606 : :
1607 : : //! initial conditions block for compressible flow
1608 : : template< class eq >
1609 : : struct ic :
1610 : : pegtl::if_must<
1611 : : tk::grm::readkw< use< kw::ic >::pegtl_string >,
1612 : : tk::grm::block< use< kw::end >,
1613 : : pegtl::sor<
1614 : : pde_parameter_vector< kw::density, eq,
1615 : : tag::ic, tag::density >,
1616 : : pde_parameter_vector< kw::materialid, eq,
1617 : : tag::ic, tag::materialid >,
1618 : : pde_parameter_vector< kw::velocity, eq,
1619 : : tag::ic, tag::velocity >,
1620 : : pde_parameter_vector< kw::pressure, eq,
1621 : : tag::ic, tag::pressure >,
1622 : : pde_parameter_vector< kw::temperature, eq,
1623 : : tag::ic, tag::temperature >,
1624 : : pde_parameter_vector< kw::energy, eq,
1625 : : tag::ic, tag::energy > >,
1626 : : pegtl::seq< box< eq > > > > {};
1627 : :
1628 : : //! put in material property for equation matching keyword
1629 : : template< typename eq, typename keyword, typename property >
1630 : : struct material_property :
1631 : : pde_parameter_vector< keyword, eq, property > {};
1632 : :
1633 : : //! Material properties block for compressible flow
1634 : : template< class eq >
1635 : : struct material_properties :
1636 : : pegtl::seq<
1637 : : pegtl::if_must<
1638 : : tk::grm::readkw< use< kw::material >::pegtl_string >,
1639 : : tk::grm::start_vector_back< tag::param, eq, tag::material >,
1640 : : tk::grm::block< use< kw::end >,
1641 : : material_vector< eq, kw::id, tag::id >
1642 : : , material_vector< eq, kw::mat_gamma, tag::gamma >
1643 : : , material_vector< eq, kw::mat_mu, tag::mu >
1644 : : , material_vector< eq, kw::mat_pstiff, tag::pstiff >
1645 : : , material_vector< eq, kw::mat_cv, tag::cv >
1646 : : , material_vector< eq, kw::mat_k, tag::k >
1647 : : , material_option< eq, ctr::Material, kw::eos, tag::eos >
1648 : : > > > {};
1649 : :
1650 : : //! Mesh ... end block
1651 : : template< class eq >
1652 : : struct mesh :
1653 : : pegtl::if_must<
1654 : : tk::grm::readkw< use< kw::mesh >::pegtl_string >,
1655 : : tk::grm::block< use< kw::end >,
1656 : : tk::grm::filename< use, tag::param, eq, tag::mesh, tag::filename >
1657 : : , pde_parameter_vector< kw::location, eq, tag::mesh, tag::location >
1658 : : , pde_parameter_vector< kw::orientation, eq,
1659 : : tag::mesh, tag::orientation >
1660 : : , tk::grm::process<
1661 : : use< kw::reference >,
1662 : : tk::grm::Store_back< tag::param, eq, tag::mesh, tag::reference >,
1663 : : pegtl::alpha >
1664 : : > > {};
1665 : :
1666 : : //! transport equation for scalars
1667 : : struct transport :
1668 : : pegtl::if_must<
1669 : : scan_eq< use< kw::transport >, tag::transport >,
1670 : : tk::grm::block< use< kw::end >,
1671 : : tk::grm::policy< use,
1672 : : use< kw::physics >,
1673 : : ctr::Physics,
1674 : : tag::transport,
1675 : : tag::physics >,
1676 : : tk::grm::policy< use,
1677 : : use< kw::problem >,
1678 : : ctr::Problem,
1679 : : tag::transport,
1680 : : tag::problem >,
1681 : : tk::grm::depvar< use,
1682 : : tag::transport,
1683 : : tag::depvar >,
1684 : : mesh< tag::transport >,
1685 : : tk::grm::component< use< kw::ncomp >,
1686 : : tag::transport >,
1687 : : pde_parameter_vector< kw::pde_diffusivity,
1688 : : tag::transport,
1689 : : tag::diffusivity >,
1690 : : pde_parameter_vector< kw::pde_lambda,
1691 : : tag::transport,
1692 : : tag::lambda >,
1693 : : pde_parameter_vector< kw::pde_u0,
1694 : : tag::transport,
1695 : : tag::u0 >,
1696 : : bc< kw::bc_dirichlet, tag::transport, tag::bcdir >,
1697 : : bc< kw::bc_sym, tag::transport, tag::bcsym >,
1698 : : bc< kw::bc_inlet, tag::transport, tag::bcinlet >,
1699 : : bc< kw::bc_outlet, tag::transport, tag::bcoutlet >,
1700 : : bc< kw::bc_extrapolate, tag::transport,
1701 : : tag::bcextrapolate >,
1702 : : parameter< tag::transport,
1703 : : kw::intsharp_param,
1704 : : tag::intsharp_param >,
1705 : : parameter< tag::transport,
1706 : : kw::intsharp,
1707 : : tag::intsharp > >,
1708 : : check_errors< tag::transport, tk::grm::check_transport > > {};
1709 : :
1710 : : //! compressible flow
1711 : : struct compflow :
1712 : : pegtl::if_must<
1713 : : scan_eq< use< kw::compflow >, tag::compflow >,
1714 : : tk::grm::start_vector< tag::param, tag::compflow, tag::ic, tag::box >,
1715 : : tk::grm::start_vector< tag::param, tag::compflow, tag::material >,
1716 : : tk::grm::start_vector< tag::param, tag::compflow, tag::bctimedep >,
1717 : : tk::grm::block< use< kw::end >,
1718 : : tk::grm::policy< use,
1719 : : use< kw::physics >,
1720 : : ctr::Physics,
1721 : : tag::compflow,
1722 : : tag::physics >,
1723 : : tk::grm::policy< use,
1724 : : use< kw::problem >,
1725 : : ctr::Problem,
1726 : : tag::compflow,
1727 : : tag::problem >,
1728 : : tk::grm::depvar< use,
1729 : : tag::compflow,
1730 : : tag::depvar >,
1731 : : mesh< tag::compflow >,
1732 : : tk::grm::process<
1733 : : use< kw::flux >,
1734 : : tk::grm::store_back_option< use,
1735 : : ctr::Flux,
1736 : : tag::param,
1737 : : tag::compflow,
1738 : : tag::flux >,
1739 : : pegtl::alpha >,
1740 : : ic< tag::compflow >,
1741 : : tk::grm::lua< use, tag::param, tag::compflow >,
1742 : : material_properties< tag::compflow >,
1743 : : pde_parameter_vector< kw::sysfctvar,
1744 : : tag::compflow,
1745 : : tag::sysfctvar >,
1746 : : parameter_bool< tag::compflow,
1747 : : kw::sysfct,
1748 : : tag::sysfct >,
1749 : : parameter< tag::compflow, kw::npar,
1750 : : tag::npar, pegtl::digit >,
1751 : : parameter< tag::compflow, kw::pde_alpha,
1752 : : tag::alpha >,
1753 : : parameter< tag::compflow, kw::pde_p0,
1754 : : tag::p0 >,
1755 : : parameter< tag::compflow, kw::pde_betax,
1756 : : tag::betax >,
1757 : : parameter< tag::compflow, kw::pde_betay,
1758 : : tag::betay >,
1759 : : parameter< tag::compflow, kw::pde_betaz,
1760 : : tag::betaz >,
1761 : : parameter< tag::compflow, kw::pde_beta,
1762 : : tag::beta >,
1763 : : parameter< tag::compflow, kw::pde_r0,
1764 : : tag::r0 >,
1765 : : parameter< tag::compflow, kw::pde_ce,
1766 : : tag::ce >,
1767 : : parameter< tag::compflow, kw::pde_kappa,
1768 : : tag::kappa >,
1769 : : bc< kw::bc_dirichlet, tag::compflow, tag::bcdir >,
1770 : : bc< kw::bc_sym, tag::compflow, tag::bcsym >,
1771 : : bc_spec< tag::compflow, tag::stag, kw::bc_stag >,
1772 : : bc_spec< tag::compflow, tag::skip, kw::bc_skip >,
1773 : : bc< kw::bc_inlet, tag::compflow, tag::bcinlet >,
1774 : : sponge< tag::compflow >,
1775 : : farfield_bc< kw::bc_farfield,
1776 : : tag::compflow,
1777 : : tag::bcfarfield >,
1778 : : bc< kw::bc_extrapolate, tag::compflow,
1779 : : tag::bcextrapolate >,
1780 : : timedep_bc< tag::compflow >
1781 : : >,
1782 : : check_errors< tag::compflow, tk::grm::check_compflow > > {};
1783 : :
1784 : : //! compressible multi-material flow
1785 : : struct multimat :
1786 : : pegtl::if_must<
1787 : : scan_eq< use< kw::multimat >, tag::multimat >,
1788 : : tk::grm::start_vector< tag::param, tag::multimat, tag::ic, tag::box >,
1789 : : tk::grm::start_vector< tag::param, tag::multimat, tag::material >,
1790 : : tk::grm::block< use< kw::end >,
1791 : : tk::grm::policy< use,
1792 : : use< kw::physics >,
1793 : : ctr::Physics,
1794 : : tag::multimat,
1795 : : tag::physics >,
1796 : : tk::grm::policy< use,
1797 : : use< kw::problem >,
1798 : : ctr::Problem,
1799 : : tag::multimat,
1800 : : tag::problem >,
1801 : : tk::grm::depvar< use,
1802 : : tag::multimat,
1803 : : tag::depvar >,
1804 : : mesh< tag::multimat >,
1805 : : parameter< tag::multimat,
1806 : : kw::nmat,
1807 : : tag::nmat >,
1808 : : tk::grm::process<
1809 : : use< kw::flux >,
1810 : : tk::grm::store_back_option< use,
1811 : : ctr::Flux,
1812 : : tag::param,
1813 : : tag::multimat,
1814 : : tag::flux >,
1815 : : pegtl::alpha >,
1816 : : ic< tag::multimat >,
1817 : : material_properties< tag::multimat >,
1818 : : parameter< tag::multimat,
1819 : : kw::pde_alpha,
1820 : : tag::alpha >,
1821 : : parameter< tag::multimat,
1822 : : kw::pde_p0,
1823 : : tag::p0 >,
1824 : : parameter< tag::multimat,
1825 : : kw::pde_beta,
1826 : : tag::beta >,
1827 : : bc< kw::bc_dirichlet,
1828 : : tag::multimat,
1829 : : tag::bcdir >,
1830 : : bc< kw::bc_sym,
1831 : : tag::multimat,
1832 : : tag::bcsym >,
1833 : : bc< kw::bc_inlet,
1834 : : tag::multimat,
1835 : : tag::bcinlet >,
1836 : : bc< kw::bc_outlet,
1837 : : tag::multimat,
1838 : : tag::bcoutlet >,
1839 : : bc< kw::bc_extrapolate,
1840 : : tag::multimat,
1841 : : tag::bcextrapolate >,
1842 : : parameter< tag::multimat,
1843 : : kw::prelax_timescale,
1844 : : tag::prelax_timescale >,
1845 : : parameter< tag::multimat,
1846 : : kw::prelax,
1847 : : tag::prelax >,
1848 : : parameter< tag::multimat,
1849 : : kw::intsharp_param,
1850 : : tag::intsharp_param >,
1851 : : parameter< tag::multimat,
1852 : : kw::intsharp,
1853 : : tag::intsharp > >,
1854 : : check_errors< tag::multimat, tk::grm::check_multimat > > {};
1855 : :
1856 : : //! partitioning ... end block
1857 : : struct partitioning :
1858 : : pegtl::if_must<
1859 : : tk::grm::readkw< use< kw::partitioning >::pegtl_string >,
1860 : : tk::grm::block< use< kw::end >,
1861 : : tk::grm::process<
1862 : : use< kw::algorithm >,
1863 : : tk::grm::store_inciter_option<
1864 : : tk::ctr::PartitioningAlgorithm,
1865 : : tag::selected,
1866 : : tag::partitioner >,
1867 : : pegtl::alpha > > > {};
1868 : :
1869 : : //! equation types
1870 : : struct equations :
1871 : : pegtl::sor< transport, compflow, multimat > {};
1872 : :
1873 : : //! refinement variable(s) (refvar) ... end block
1874 : : struct refvars :
1875 : : pegtl::if_must<
1876 : : tk::grm::vector< use< kw::amr_refvar >,
1877 : : tk::grm::match_depvar<
1878 : : tk::grm::Store_back< tag::amr, tag::refvar > >,
1879 : : use< kw::end >,
1880 : : tk::grm::check_vector< tag::amr, tag::refvar >,
1881 : : tk::grm::fieldvar< pegtl::alpha > >,
1882 : : tk::grm::compute_refvar_idx > {};
1883 : :
1884 : : //! adaptive mesh refinement (AMR) amr...end block
1885 : : struct amr :
1886 : : pegtl::if_must<
1887 : : tk::grm::readkw< use< kw::amr >::pegtl_string >,
1888 : : // enable AMR if amr...end block encountered
1889 : : tk::grm::enable< tag::amr >,
1890 : : tk::grm::block< use< kw::end >,
1891 : : refvars,
1892 : : edgelist,
1893 : : coords,
1894 : : tk::grm::process<
1895 : : use< kw::amr_initial >,
1896 : : tk::grm::store_back_option< use,
1897 : : ctr::AMRInitial,
1898 : : tag::amr,
1899 : : tag::init >,
1900 : : pegtl::alpha >,
1901 : : tk::grm::process<
1902 : : use< kw::amr_error >,
1903 : : tk::grm::store_inciter_option<
1904 : : ctr::AMRError,
1905 : : tag::amr, tag::error >,
1906 : : pegtl::alpha >,
1907 : : tk::grm::control< use< kw::amr_tolref >,
1908 : : pegtl::digit,
1909 : : tk::grm::Store,
1910 : : tag::amr,
1911 : : tag::tolref >,
1912 : : tk::grm::control< use< kw::amr_tolderef >,
1913 : : pegtl::digit,
1914 : : tk::grm::Store,
1915 : : tag::amr,
1916 : : tag::tolderef >,
1917 : : tk::grm::process< use< kw::amr_t0ref >,
1918 : : tk::grm::Store< tag::amr, tag::t0ref >,
1919 : : pegtl::alpha >,
1920 : : tk::grm::process< use< kw::amr_dtref_uniform >,
1921 : : tk::grm::Store< tag::amr, tag::dtref_uniform >,
1922 : : pegtl::alpha >,
1923 : : tk::grm::process< use< kw::amr_dtref >,
1924 : : tk::grm::Store< tag::amr, tag::dtref >,
1925 : : pegtl::alpha >,
1926 : : tk::grm::process< use< kw::amr_dtfreq >,
1927 : : tk::grm::Store< tag::amr, tag::dtfreq >,
1928 : : pegtl::digit > >,
1929 : : tk::grm::check_amr_errors > {};
1930 : :
1931 : :
1932 : : //! Arbitrary-Lagrangian-Eulerian (ALE) move...end block
1933 : : struct moving_sides :
1934 : : pegtl::if_must<
1935 : : tk::grm::readkw< use< kw::move >::pegtl_string >,
1936 : : tk::grm::start_vector< tag::ale, tag::move >,
1937 : : tk::grm::block< use< kw::end >,
1938 : : tk::grm::process<
1939 : : use< kw::fntype >,
1940 : : tk::grm::back_store_option< tag::fntype,
1941 : : use,
1942 : : tk::ctr::UserTable,
1943 : : tag::ale, tag::move >,
1944 : : pegtl::alpha >,
1945 : : user_fn< tag::fn, tk::grm::Back_store_back, tag::ale, tag::move >,
1946 : : pegtl::if_must< tk::grm::vector< use< kw::sideset >,
1947 : : tk::grm::Back_store_back< tag::sideset, tag::ale, tag::move >,
1948 : : use< kw::end > > > > > {};
1949 : :
1950 : : //! Arbitrary-Lagrangian-Eulerian (ALE) ale...end block
1951 : : struct ale :
1952 : : pegtl::if_must<
1953 : : tk::grm::readkw< use< kw::ale >::pegtl_string >,
1954 : : // enable ALE if ale ...end block encountered
1955 : : tk::grm::enable< tag::ale >,
1956 : : tk::grm::block< use< kw::end >,
1957 : : tk::grm::control< use< kw::dvcfl >,
1958 : : pegtl::digit,
1959 : : tk::grm::Store,
1960 : : tag::ale, tag::dvcfl >,
1961 : : tk::grm::control< use< kw::vortmult >,
1962 : : pegtl::digit,
1963 : : tk::grm::Store,
1964 : : tag::ale, tag::vortmult >,
1965 : : tk::grm::control< use< kw::meshvel_maxit >,
1966 : : pegtl::digit,
1967 : : tk::grm::Store,
1968 : : tag::ale, tag::maxit >,
1969 : : tk::grm::control< use< kw::meshvel_tolerance >,
1970 : : pegtl::digit,
1971 : : tk::grm::Store,
1972 : : tag::ale, tag::tolerance >,
1973 : : moving_sides,
1974 : : tk::grm::process<
1975 : : use< kw::meshvelocity >,
1976 : : tk::grm::store_inciter_option< ctr::MeshVelocity,
1977 : : tag::ale, tag::meshvelocity >,
1978 : : pegtl::alpha >,
1979 : : tk::grm::process<
1980 : : use< kw::smoother >,
1981 : : tk::grm::store_inciter_option< ctr::MeshVelocitySmoother,
1982 : : tag::ale, tag::smoother >,
1983 : : pegtl::alpha >,
1984 : : pegtl::if_must< tk::grm::dimensions< use< kw::mesh_motion >,
1985 : : tk::grm::Store_back< tag::ale, tag::mesh_motion >,
1986 : : use< kw::end > > >,
1987 : : pegtl::if_must< tk::grm::vector< use< kw::meshforce >,
1988 : : tk::grm::Store_back< tag::ale, tag::meshforce >,
1989 : : use< kw::end > > >,
1990 : : pegtl::if_must<
1991 : : tk::grm::readkw< use< kw::bc_dirichlet >::pegtl_string >,
1992 : : tk::grm::block< use< kw::end >,
1993 : : pegtl::if_must< tk::grm::vector< use< kw::sideset >,
1994 : : tk::grm::Store_back< tag::ale, tag::bcdir >,
1995 : : use< kw::end > > > > >,
1996 : : pegtl::if_must<
1997 : : tk::grm::readkw< use< kw::bc_sym >::pegtl_string >,
1998 : : tk::grm::block< use< kw::end >,
1999 : : pegtl::if_must< tk::grm::vector< use< kw::sideset >,
2000 : : tk::grm::Store_back< tag::ale, tag::bcsym >,
2001 : : use< kw::end > > > > > >,
2002 : : tk::grm::check_ale > {};
2003 : :
2004 : : //! \brief Match a depvar, defined upstream of control file, coupling a
2005 : : //! solver and store
2006 : : template< template< class > class action >
2007 : : struct coupled_solver :
2008 : : tk::grm::scan_until<
2009 : : pegtl::lower,
2010 : : tk::grm::match_depvar< tk::grm::push_transfer< action > > > {};
2011 : :
2012 : : //! Couple ... end block (used to configure solver coupling)
2013 : : struct couple :
2014 : : pegtl::if_must<
2015 : : tk::grm::readkw< use< kw::couple >::pegtl_string >,
2016 : : tk::grm::block< use< kw::end >,
2017 : : pegtl::seq<
2018 : : coupled_solver< tk::grm::store_transfer_src >,
2019 : : pegtl::one<'>'>,
2020 : : coupled_solver< tk::grm::store_transfer_dst > > > > {};
2021 : :
2022 : : //! p-adaptive refinement (pref) ...end block
2023 : : struct pref :
2024 : : pegtl::if_must<
2025 : : tk::grm::readkw< use< kw::pref >::pegtl_string >,
2026 : : tk::grm::block< use< kw::end >,
2027 : : tk::grm::control< use< kw::pref_tolref >,
2028 : : pegtl::digit,
2029 : : tk::grm::Store,
2030 : : tag::pref,
2031 : : tag::tolref >,
2032 : : tk::grm::control< use< kw::pref_ndofmax >,
2033 : : pegtl::digit,
2034 : : tk::grm::Store,
2035 : : tag::pref,
2036 : : tag::ndofmax >,
2037 : : tk::grm::process<
2038 : : use< kw::pref_indicator >,
2039 : : tk::grm::store_inciter_option<
2040 : : ctr::PrefIndicator,
2041 : : tag::pref, tag::indicator >,
2042 : : pegtl::alpha >
2043 : : >,
2044 : : tk::grm::check_pref_errors > {};
2045 : :
2046 : : //! Match output variable alias
2047 : : struct outvar_alias :
2048 : : tk::grm::quoted< tk::grm::set_outvar_alias > {};
2049 : :
2050 : : //! Match an output variable in a human readable form: var must be a keyword
2051 : : template< class var >
2052 : : struct outvar_human :
2053 : : tk::grm::exact_scan< use< var >, tk::grm::push_humanvar > {};
2054 : :
2055 : : //! Match an output variable based on depvar defined upstream of input file
2056 : : struct outvar_depvar :
2057 : : tk::grm::scan< tk::grm::fieldvar< pegtl::upper >,
2058 : : tk::grm::match_outvar, tk::grm::check_outvar > {};
2059 : :
2060 : : //! Parse a centering token and if matches, set centering in parser's state
2061 : : struct outvar_centering :
2062 : : pegtl::sor<
2063 : : tk::grm::exact_scan< use< kw::node >, tk::grm::set_centering >,
2064 : : tk::grm::exact_scan< use< kw::elem >, tk::grm::set_centering > > {};
2065 : :
2066 : : //! outvar ... end block
2067 : : struct outvar_block :
2068 : : pegtl::if_must<
2069 : : tk::grm::readkw< use< kw::outvar >::pegtl_string >,
2070 : : tk::grm::block<
2071 : : use< kw::end >
2072 : : , outvar_centering
2073 : : , outvar_depvar
2074 : : , outvar_alias
2075 : : , outvar_human< kw::outvar_density >
2076 : : , outvar_human< kw::outvar_xmomentum >
2077 : : , outvar_human< kw::outvar_ymomentum >
2078 : : , outvar_human< kw::outvar_zmomentum >
2079 : : , outvar_human< kw::outvar_specific_total_energy >
2080 : : , outvar_human< kw::outvar_volumetric_total_energy >
2081 : : , outvar_human< kw::outvar_xvelocity >
2082 : : , outvar_human< kw::outvar_yvelocity >
2083 : : , outvar_human< kw::outvar_zvelocity >
2084 : : , outvar_human< kw::outvar_pressure >
2085 : : , outvar_human< kw::outvar_material_indicator >
2086 : : , outvar_human< kw::outvar_analytic >
2087 : : > > {};
2088 : :
2089 : : //! field_output ... end block
2090 : : struct field_output :
2091 : : pegtl::if_must<
2092 : : tk::grm::readkw< use< kw::field_output >::pegtl_string >,
2093 : : tk::grm::block<
2094 : : use< kw::end >,
2095 : : outvar_block,
2096 : : tk::grm::process< use< kw::filetype >,
2097 : : tk::grm::store_inciter_option<
2098 : : tk::ctr::FieldFile,
2099 : : tag::selected,
2100 : : tag::filetype >,
2101 : : pegtl::alpha >,
2102 : : tk::grm::interval_iter< use< kw::interval_iter >,
2103 : : tag::output, tag::iter, tag::field >,
2104 : : tk::grm::interval_time< use< kw::interval_time >,
2105 : : tag::output, tag::time, tag::field >,
2106 : : tk::grm::time_range< use, kw::time_range,
2107 : : tag::output, tag::range, tag::field >,
2108 : : tk::grm::process<
2109 : : use< kw::refined >,
2110 : : tk::grm::Store< tag::cmd, tag::io, tag::refined >,
2111 : : pegtl::alpha >,
2112 : : pegtl::if_must<
2113 : : tk::grm::vector<
2114 : : use< kw::sideset >,
2115 : : tk::grm::Store_back< tag::cmd, tag::io, tag::surface >,
2116 : : use< kw::end > > > > > {};
2117 : :
2118 : : //! history_output ... end block
2119 : : struct history_output :
2120 : : pegtl::if_must<
2121 : : tk::grm::readkw< use< kw::history_output >::pegtl_string >,
2122 : : tk::grm::block<
2123 : : use< kw::end >,
2124 : : outvar_block,
2125 : : tk::grm::interval_iter< use< kw::interval_iter >,
2126 : : tag::output, tag::iter, tag::history >,
2127 : : tk::grm::interval_time< use< kw::interval_time >,
2128 : : tag::output, tag::time, tag::history >,
2129 : : tk::grm::time_range< use, kw::time_range,
2130 : : tag::output, tag::range, tag::history >,
2131 : : tk::grm::precision< use, tag::history >,
2132 : : tk::grm::process<
2133 : : use< kw::txt_float_format >,
2134 : : tk::grm::store_inciter_option< tk::ctr::TxtFloatFormat,
2135 : : tag::flformat,
2136 : : tag::history >,
2137 : : pegtl::alpha >,
2138 : : pegtl::if_must<
2139 : : tk::grm::readkw< use< kw::point >::pegtl_string >,
2140 : : tk::grm::act< pegtl::identifier, tk::grm::match_pointname >,
2141 : : pegtl::seq<
2142 : : tk::grm::start_vector< tag::history, tag::point >,
2143 : : tk::grm::block<
2144 : : use< kw::end >,
2145 : : tk::grm::scan< tk::grm::number,
2146 : : tk::grm::Store_back_back< tag::history, tag::point > > >
2147 : : > > > > {};
2148 : :
2149 : : //! 'inciter' block
2150 : : struct inciter :
2151 : : pegtl::if_must<
2152 : : tk::grm::readkw< use< kw::inciter >::pegtl_string >,
2153 : : pegtl::sor<
2154 : : pegtl::seq< tk::grm::block<
2155 : : use< kw::end >,
2156 : : discretization,
2157 : : equations,
2158 : : amr,
2159 : : ale,
2160 : : pref,
2161 : : partitioning,
2162 : : couple,
2163 : : field_output,
2164 : : history_output,
2165 : : tk::grm::diagnostics<
2166 : : use,
2167 : : tk::grm::store_inciter_option > >,
2168 : : tk::grm::check_inciter >,
2169 : : tk::grm::msg< tk::grm::MsgType::ERROR,
2170 : : tk::grm::MsgKey::UNFINISHED > > > {};
2171 : :
2172 : : //! \brief All keywords
2173 : : struct keywords :
2174 : : pegtl::sor< tk::grm::title< use >, inciter > {};
2175 : :
2176 : : //! \brief Grammar entry point: parse keywords and ignores until eof
2177 : : struct read_file :
2178 : : tk::grm::read_file< keywords, tk::grm::ignore > {};
2179 : :
2180 : : } // deck::
2181 : : } // inciter::
2182 : :
2183 : : #endif // InciterInputDeckGrammar_h
|