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