Theseus
Compressible flow solver
Loading...
Searching...
No Matches
SimFactory_impl.hpp
Go to the documentation of this file.
1// Copyright (c) 2025-2026 Board of Trustees of the University of Illinois
2//
3// This file is part of Theseus.
4//
5// SPDX-License-Identifier: BSD-3-Clause
6#pragma once
7
8#include <memory>
9
10#include "parse_helpers.hpp"
11#include "SimFactory.hpp"
12#include "EulerOperator.hpp"
13#include "NSOperator.hpp"
14#include "LaxFriedrichsFlux.hpp"
15#include "ChandrashekarFlux.hpp"
16#include "HLLFlux.hpp"
17#include "LTETable.hpp"
18#include "TheseusConfig.hpp"
19
20namespace Theseus {
21
22 // TODO: Update for LTE Table Data, and LTE Gas Model setup
23 template <typename Physics, typename GasModelT>
24 std::unique_ptr<Theseus::RHSOperatorBase>
26 bool inviscid,
27 const nlohmann::json &runtime,
28 std::shared_ptr<mfem::ParFiniteElementSpace> vfes,
29 std::shared_ptr<mfem::ParFiniteElementSpace> fes0,
30 std::shared_ptr<mfem::ParMesh> pmesh,
31 std::shared_ptr<mfem::ParGridFunction> eta,
32 std::shared_ptr<mfem::ParGridFunction> alpha,
33 std::vector<std::shared_ptr<mfem::ParGridFunction> > &grad_u,
34 std::shared_ptr<Prandtl::PerssonPeraireIndicator> indicator,
35 mfem::real_t alpha_max,
36 std::shared_ptr<const GasModelT> gas_,
37 const std::string &gasModelName,
38 const std::string &numFluxName)
39 {
40
41 if (inviscid) {
42 return std::make_unique<Theseus::EulerOperator<Physics>>(vfes, fes0, pmesh, eta, alpha,
43 indicator,
44 gas_,
45 gasModelName,
46 numFluxName,
47 alpha_max);
48 } else {
49 return std::make_unique<Theseus::NSOperator<Physics>>(vfes, fes0, pmesh, eta, alpha, grad_u,
50 indicator,
51 gas_,
52 gasModelName,
53 numFluxName,
54 alpha_max);
55 }
56 }
57
58 std::unique_ptr<Theseus::RHSOperatorBase>
59 MakeRHSOperator(const nlohmann::json& runtime,
60 std::shared_ptr<mfem::ParFiniteElementSpace> vfes,
61 std::shared_ptr<mfem::ParFiniteElementSpace> fes0,
62 std::shared_ptr<mfem::ParMesh> pmesh,
63 std::shared_ptr<mfem::ParGridFunction> eta,
64 std::shared_ptr<mfem::ParGridFunction> alpha,
65 std::vector<std::shared_ptr<mfem::ParGridFunction> > &grad_u,
66 std::shared_ptr<Prandtl::PerssonPeraireIndicator> indicator,
67 mfem::real_t alpha_max)
68 {
69
70 std::string gas_model_string =
71 to_lower(runtime.value("gas_model", std::string{}));
72
73 std::string inv_flux_string =
74 to_lower(runtime.value("numerical_flux", std::string{}));
75
76 std::string flow_model_string =
77 to_lower(runtime.value("flow_model", std::string{}));
78
79 const bool use_cpg =
80 gas_model_string.empty() ||
81 gas_model_string == "cpg" ||
82 gas_model_string == "ideal" ||
83 gas_model_string == "ideal_gas";
84
85 const bool use_lte =
86 gas_model_string == "lte";
87
88 const bool use_chan =
89 inv_flux_string.empty() ||
90 inv_flux_string == "chandrashekar" ||
91 starts_with(inv_flux_string, "chan");
92
93 const bool use_hll =
94 inv_flux_string == "hll";
95
96 const bool use_llf =
97 inv_flux_string == "llf" ||
98 inv_flux_string == "lfr" ||
99 inv_flux_string == "laxfriedrichs" ||
100 inv_flux_string == "lax_friedrichs" ||
101 starts_with(inv_flux_string, "lax");
102
103 const bool viscous =
104 starts_with(flow_model_string, "visc") ||
105 starts_with(flow_model_string, "nav") ||
106 starts_with(flow_model_string, "cns") ||
107 starts_with(flow_model_string, "ns");
108 const bool inviscid = !viscous;
109
110 const int dim = pmesh->Dimension();
111 const int num_dofs_scalar = vfes->GetNDofs();
112
113 Theseus::PhysicsConstants physics_constants(runtime.value("gamma", 1.4),
114 runtime.value("Pr", 0.72),
115 runtime.value("R_gas", 287.05),
116 runtime.value("mu", 0.02));
117 Theseus::StateLayout layout(dim, num_dofs_scalar);
118
119 if (use_cpg)
120 {
121
122 auto gas_model =
123 std::make_shared<Theseus::IdealGasModel>(physics_constants, layout);
124 std::string gasModelName("CPG1");
125 if (use_chan)
126 {
127 std::string numFluxName("Chandrashekar");
128 using Physics =
131 return MakeTypedRHSOperator<Physics, Theseus::IdealGasModel>(inviscid, runtime,
132 vfes, fes0, pmesh, eta, alpha, grad_u,
133 indicator, alpha_max, gas_model,
134 gasModelName, numFluxName);
135 }
136 else if (use_hll)
137 {
138 std::string numFluxName("HLL");
139 using Physics =
142
143 return MakeTypedRHSOperator<Physics, Theseus::IdealGasModel>(inviscid, runtime,
144 vfes, fes0, pmesh, eta, alpha, grad_u,
145 indicator, alpha_max, gas_model,
146 gasModelName, numFluxName);
147 }
148 else if (use_llf)
149 {
150 std::string numFluxName("LLF");
151 using Physics =
154
155 return MakeTypedRHSOperator<Physics, Theseus::IdealGasModel>(inviscid, runtime,
156 vfes, fes0, pmesh, eta, alpha, grad_u,
157 indicator, alpha_max, gas_model,
158 gasModelName, numFluxName);
159 }
160 else {
161 std::cerr << "Error: Invalid Numerical Flux Type specified: "
162 << inv_flux_string << "\n"
163 << "Supported: Chandrashekar, LLF/LFR, HLL"
164 << std::endl;
165 return nullptr;
166 }
167 } else if(use_lte){
168 std::string mixture(runtime.value("gas_mixture", "air5"));
169 std::string solver(runtime.value("plato_solver", "LTE_table_rhoT_(air5)"));
170 std::string path(runtime.value("database_path", std::string(Theseus::BuildConfig::PlatoDBPath)));
171 std::string rho_dist(runtime.value("rho_dist", "log"));
172 std::string T_dist(runtime.value("T_dist", "log"));
173 int N_rho = runtime.value("N_rho", 101);
174 int N_T = runtime.value("N_T", 101);
175 mfem::real_t rho_min = runtime.value("rho_min", 0.1);
176 mfem::real_t rho_max = runtime.value("rho_max", 1.1);
177 mfem::real_t T_min = runtime.value("T_min", 250.0);
178 mfem::real_t T_max = runtime.value("T_max", 35.0);
179 int num_properties = 9; // CL NOTE : Check LTE EOS
180 auto lteData = std::make_unique<Theseus::LTETable::Data>();
181 auto &lteTableData = *lteData;
183 lteTableData.lte_table.SetSize(N_rho * N_T * num_properties);
184 lteTableData.inv_table.SetSize(N_rho * N_T);
185 if(rho_dist == "log")
186 {
187 Theseus::LTETable::log_grid(N_rho, rho_min, rho_max, lteTableData.rho_grid);
188 }
189 else
190 {
191 Theseus::LTETable::uniform_grid(N_rho, rho_min, rho_max, lteTableData.rho_grid);
192 }
193
194 if(T_dist == "log")
195 {
196 Theseus::LTETable::log_grid(N_T, T_min, T_max, lteTableData.T_grid);
197 }
198 else
199 {
200 Theseus::LTETable::uniform_grid(N_T, T_min, T_max, lteTableData.T_grid);
201 }
202 lteTableData.e_grid.SetSize(N_T);
203 lteTables.L.setup(N_rho, N_T);
204#ifdef USE_PLATO
205 if(mfem::Mpi::Root())
206 {
207 std::cout << "Constructing LTE table for " << mixture
208 << " with solver " << solver << std::endl
209 << "LTE Database: " << path << std::endl;
210 if(Theseus::LTETable::check_plato_database_path(path)){
211 std::cerr << "Plato Database (" << path << ") not found." << std::endl;
212 return nullptr;
213 }
214 mfem::real_t e_min, e_max;
215 std::string empty_str("empty");
216 plato_initialize(solver.c_str(), mixture.c_str(), empty_str.c_str(), empty_str.c_str(), path.c_str());
217 Theseus::LTETable::fill_table(lteTables.L, lteTableData.rho_grid.GetData(), lteTableData.T_grid.GetData(),
218 lteTableData.lte_table.GetData(), e_min, e_max);
219 std::cout << "Constructing inverse table T = T(rho, e)" << std::endl;
220 Theseus::LTETable::uniform_grid(N_T, e_min, e_max, lteTableData.e_grid);
221 Theseus::LTETable::fill_inv_table(lteTables.L, lteTableData.rho_grid.GetData(), lteTableData.e_grid.GetData(),
222 lteTableData.T_grid.GetData(), lteTableData.inv_table.GetData());
223 plato_finalize();
224 }
225#else
226 // TODO: Eventually, maybe run with pre-generated tables.
227 if(mfem::Mpi::Root()){
228 std::cerr << "LTE runs *must* have Theseus build with PLATO support (-DTHESEUS_WITH_PLATO)" << std::endl;
229 }
230 return nullptr;
231#endif
232 MPI_Bcast(lteTableData.lte_table.GetData(), N_rho * N_T * num_properties, MPI_DOUBLE, 0, pmesh->GetComm());
233 MPI_Bcast(lteTableData.inv_table.GetData(), N_rho * N_T, MPI_DOUBLE, 0, pmesh->GetComm());
234 MPI_Bcast(lteTableData.e_grid.GetData(), N_T, MPI_DOUBLE, 0, pmesh->GetComm());
235 lteTables.tables = {
236 lteTableData.lte_table.HostRead(), lteTableData.inv_table.HostRead(),
237 lteTableData.rho_grid.HostRead(), lteTableData.T_grid.HostRead(),
238 lteTableData.e_grid.HostRead()
239 };
240 auto gas_model = std::make_shared<Theseus::LTEGas>(physics_constants, layout, lteTables);
241 std::string gasModelName("LTE:"+mixture);
242 if (use_chan)
243 {
244 std::string numFluxName("Chandrashekar");
245 using Physics =
248 // return MakeTypedRHSOperator<Physics>(inviscid, runtime,
249 // vfes, fes0, pmesh, eta, alpha, grad_u,
250 // indicator, alpha_max, gas_model,
251 // gasModelName, numFluxName);
252 std::cerr << "Error: Cannot use Chandrashekar flux with LTE" << std::endl;
253 return nullptr;
254 }
255 else if (use_hll)
256 {
257 std::string numFluxName("HLL");
258 using Physics =
261
262 auto rhsOp = MakeTypedRHSOperator<Physics, Theseus::LTEGas>(inviscid, runtime,
263 vfes, fes0, pmesh, eta, alpha, grad_u,
264 indicator, alpha_max, gas_model,
265 gasModelName, numFluxName);
266 RHSOperator<Physics> *lteRHSOp = dynamic_cast<RHSOperator<Physics> *>(rhsOp.get());
267 auto &operator_cache = lteRHSOp->GetOperatorCacheReference();
268 operator_cache.lteTableData = std::move(lteData);
269 return rhsOp;
270 }
271 else if (use_llf)
272 {
273 std::string numFluxName("LFR");
274 using Physics =
277
278 auto rhsOp = MakeTypedRHSOperator<Physics, Theseus::LTEGas>
279 (inviscid, runtime,vfes, fes0, pmesh, eta, alpha, grad_u,
280 indicator, alpha_max, gas_model,
281 gasModelName, numFluxName);
282
283 RHSOperator<Physics> *lteRHSOp = dynamic_cast<RHSOperator<Physics> *>(rhsOp.get());
284 auto &operator_cache = lteRHSOp->GetOperatorCacheReference();
285 operator_cache.lteTableData = std::move(lteData);
286 return rhsOp;
287 }
288 else {
289 std::cerr << "Error: Invalid Numerical Flux Type specified: "
290 << inv_flux_string << "\n"
291 << "Supported: Chandrashekar, LLF/LFR, HLL"
292 << std::endl;
293 return nullptr;
294 }
295
296 } else {
297 std::cerr << "Error: Invalid Gas Model specified: "
298 << gas_model_string << "\n"
299 << "Supported: CPG, LTE"
300 << std::endl;
301 return nullptr;
302 }
303
304 }
305}
Definition RHSOperator.hpp:121
OperatorCache & GetOperatorCacheReference()
Definition RHSOperator.hpp:158
void log_grid(int N, mfem::real_t min, mfem::real_t max, mfem::Vector &grid)
Definition LTETable.hpp:95
void uniform_grid(int N, mfem::real_t min, mfem::real_t max, mfem::Vector &grid)
Definition LTETable.hpp:85
void fill_table(const LTETable::Layout &L, const mfem::real_t *rho_grid, const mfem::real_t *T_grid, mfem::real_t *lte_table, mfem::real_t &e_min, mfem::real_t &e_max)
Definition LTETable.hpp:105
void fill_inv_table(const LTETable::Layout &L, const mfem::real_t *rho_grid, const mfem::real_t *e_grid, const mfem::real_t *T_grid, mfem::real_t *inv_table)
Definition LTETable.hpp:216
Definition AxisymmetricGeometry.hpp:15
LTEGasModel< LTEGasEOS, LTETransport > LTEGas
Definition LTEGasModel.hpp:241
GasModel< IdealSingleGasEOS, Transport > IdealGasModel
Definition GasModel.hpp:229
std::unique_ptr< Theseus::RHSOperatorBase > MakeRHSOperator(const nlohmann::json &runtime, std::shared_ptr< mfem::ParFiniteElementSpace > vfes, std::shared_ptr< mfem::ParFiniteElementSpace > fes0, std::shared_ptr< mfem::ParMesh > pmesh, std::shared_ptr< mfem::ParGridFunction > eta, std::shared_ptr< mfem::ParGridFunction > alpha, std::vector< std::shared_ptr< mfem::ParGridFunction > > &grad_u, std::shared_ptr< Prandtl::PerssonPeraireIndicator > indicator, mfem::real_t alpha_max)
Definition SimFactory_impl.hpp:59
std::unique_ptr< Theseus::RHSOperatorBase > MakeTypedRHSOperator(bool inviscid, const nlohmann::json &runtime, std::shared_ptr< mfem::ParFiniteElementSpace > vfes, std::shared_ptr< mfem::ParFiniteElementSpace > fes0, std::shared_ptr< mfem::ParMesh > pmesh, std::shared_ptr< mfem::ParGridFunction > eta, std::shared_ptr< mfem::ParGridFunction > alpha, std::vector< std::shared_ptr< mfem::ParGridFunction > > &grad_u, std::shared_ptr< Prandtl::PerssonPeraireIndicator > indicator, mfem::real_t alpha_max, std::shared_ptr< const GasModelT > gas_, const std::string &gasModelName, const std::string &numFluxName)
Definition SimFactory_impl.hpp:25
auto to_lower
Definition parse_helpers.hpp:10
auto starts_with
Definition parse_helpers.hpp:19
Definition ChandrashekarFlux.hpp:186
Definition HLLFlux.hpp:147
Definition LTETable.hpp:75
LTETable::View tables
Definition LTETable.hpp:82
LTETable::Layout L
Definition LTETable.hpp:81
void setup(int nx_, int ny_)
Definition LTETable.hpp:38
const mfem::real_t * lte_table
Definition LTETable.hpp:67
Definition LaxFriedrichsFlux.hpp:136
Definition Physics.hpp:14
Definition SimFactory.hpp:16
Definition GasState.hpp:37