28#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
41static constexpr real g_gamma = 1.4;
42static constexpr int dim = 3;
43static constexpr int I4 = dim + 1;
45static constexpr int nVars = 7;
47static constexpr real GOLDEN_NOT_ACQUIRED = 1e300;
51static Eigen::Vector<real, nVars> buildState(
54 Eigen::Vector<real, nVars> U;
55 real E = p / (g_gamma - 1.0) + 0.5 * rho * (u * u +
v *
v + w * w);
56 U << rho, rho * u, rho *
v, rho * w, E, rho * k, rho * omega;
62static Eigen::Matrix<real, dim, nVars> buildShearGrad(
63 const Eigen::Vector<real, nVars> &U,
real S_shear)
65 Eigen::Matrix<real, dim, nVars> DiffU;
68 DiffU(1, 1) = U(0) * S_shear;
79static const real g_rho = 1.225;
80static const real g_u = 50.0;
81static const real g_p = 101325.0;
82static const real g_k = 10.0;
83static const real g_omega = 1000.0;
84static const real g_epsilon = 0.09 * g_k * g_omega;
85static const real g_mu = 1.8e-5;
86static const real g_d = 0.01;
87static const real g_Sshear = 500.0;
95 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
96 auto DiffU = buildShearGrad(U, g_Sshear);
97 real mut = GetMut_KOWilcox<dim>(U, DiffU, g_mu, g_d);
100 CHECK(std::isfinite(mut));
105 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
106 auto DiffU = buildShearGrad(U, g_Sshear);
107 real mut = GetMut_KOWilcox<dim>(U, DiffU, g_mu, g_d);
109 CHECK(mut <= 1e5 * g_mu + 1e-10);
114 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
115 auto DiffU = buildShearGrad(U, g_Sshear);
116 real mut = GetMut_KOWilcox<dim>(U, DiffU, g_mu, g_d);
118 std::cout <<
"[KOWilcox/mut] " << std::scientific << std::setprecision(10) << mut << std::endl;
120 real golden = 8.4000000000e-03;
121 if (golden < GOLDEN_NOT_ACQUIRED)
122 CHECK(mut == doctest::Approx(golden).epsilon(1e-6));
131 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
132 auto DiffU = buildShearGrad(U, g_Sshear);
133 real mut = GetMut_SST<dim>(U, DiffU, g_mu, g_d);
136 CHECK(std::isfinite(mut));
141 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
142 auto DiffU = buildShearGrad(U, g_Sshear);
143 real mut = GetMut_SST<dim>(U, DiffU, g_mu, g_d);
145 CHECK(mut <= 1e5 * g_mu + 1e-10);
150 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
151 auto DiffU = buildShearGrad(U, g_Sshear);
152 real mut = GetMut_SST<dim>(U, DiffU, g_mu, g_d);
154 std::cout <<
"[SST/mut] " << std::scientific << std::setprecision(10) << mut << std::endl;
155 real golden = 7.5950000000e-03;
156 if (golden < GOLDEN_NOT_ACQUIRED)
157 CHECK(mut == doctest::Approx(golden).epsilon(1e-6));
166 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_epsilon);
167 auto DiffU = buildShearGrad(U, g_Sshear);
168 real mut = GetMut_RealizableKe<dim>(U, DiffU, g_mu, g_d);
171 CHECK(std::isfinite(mut));
176 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_epsilon);
177 auto DiffU = buildShearGrad(U, g_Sshear);
178 real mut = GetMut_RealizableKe<dim>(U, DiffU, g_mu, g_d);
180 CHECK(mut <= 1e5 * g_mu + 1e-10);
185 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_epsilon);
186 auto DiffU = buildShearGrad(U, g_Sshear);
187 real mut = GetMut_RealizableKe<dim>(U, DiffU, g_mu, g_d);
189 std::cout <<
"[RealKe/mut] " << std::scientific << std::setprecision(10) << mut << std::endl;
190 real golden = 1.2250000000e-02;
191 if (golden < GOLDEN_NOT_ACQUIRED)
192 CHECK(mut == doctest::Approx(golden).epsilon(1e-6));
199TEST_CASE(
"GetSource_KOWilcox: zero gradient finite and has destruction")
201 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
202 Eigen::Matrix<real, dim, nVars> DiffU = Eigen::Matrix<real, dim, nVars>::Zero();
203 Eigen::Vector<real, nVars> source;
206 GetSource_KOWilcox<dim>(U, DiffU, g_mu, g_d, source, 0);
208 CHECK(std::isfinite(source(I4 + 1)));
209 CHECK(std::isfinite(source(I4 + 2)));
211 CHECK(source(I4 + 1) <= 0.0);
213 CHECK(source(I4 + 2) <= 0.0);
218 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
219 Eigen::Matrix<real, dim, nVars> DiffU = Eigen::Matrix<real, dim, nVars>::Zero();
220 Eigen::Vector<real, nVars> source;
223 GetSource_SST<dim>(U, DiffU, g_mu, g_d, 1e10, source, 0);
225 CHECK(std::isfinite(source(I4 + 1)));
226 CHECK(std::isfinite(source(I4 + 2)));
228 CHECK(source(I4 + 1) <= 0.0);
231TEST_CASE(
"GetSource_RealizableKe: zero gradient finite")
233 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_epsilon);
234 Eigen::Matrix<real, dim, nVars> DiffU = Eigen::Matrix<real, dim, nVars>::Zero();
235 Eigen::Vector<real, nVars> source;
238 GetSource_RealizableKe<dim>(U, DiffU, g_mu, g_d, source, 0);
240 CHECK(std::isfinite(source(I4 + 1)));
241 CHECK(std::isfinite(source(I4 + 2)));
250 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
251 auto DiffU = buildShearGrad(U, g_Sshear);
252 Eigen::Vector<real, nVars> source;
255 GetSource_KOWilcox<dim>(U, DiffU, g_mu, g_d, source, 0);
257 std::cout <<
"[KOWilcox/source] k=" << std::scientific << std::setprecision(10)
258 << source(I4 + 1) <<
" omega=" << source(I4 + 2) << std::endl;
260 CHECK(std::isfinite(source(I4 + 1)));
261 CHECK(std::isfinite(source(I4 + 2)));
269 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
270 auto DiffU = buildShearGrad(U, g_Sshear);
271 Eigen::Vector<real, nVars> source;
274 GetSource_SST<dim>(U, DiffU, g_mu, g_d, 1e10, source, 0);
276 std::cout <<
"[SST/source] k=" << std::scientific << std::setprecision(10)
277 << source(I4 + 1) <<
" omega=" << source(I4 + 2) << std::endl;
279 CHECK(std::isfinite(source(I4 + 1)));
280 CHECK(std::isfinite(source(I4 + 2)));
283TEST_CASE(
"GetSource_RealizableKe: shear gradient golden")
285 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_epsilon);
286 auto DiffU = buildShearGrad(U, g_Sshear);
287 Eigen::Vector<real, nVars> source;
290 GetSource_RealizableKe<dim>(U, DiffU, g_mu, g_d, source, 0);
292 std::cout <<
"[RealKe/source] k=" << std::scientific << std::setprecision(10)
293 << source(I4 + 1) <<
" epsilon=" << source(I4 + 2) << std::endl;
295 CHECK(std::isfinite(source(I4 + 1)));
296 CHECK(std::isfinite(source(I4 + 2)));
303TEST_CASE(
"GetSource_KOWilcox mode=1: implicit diagonal non-negative")
305 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
306 auto DiffU = buildShearGrad(U, g_Sshear);
307 Eigen::Vector<real, nVars> source;
310 GetSource_KOWilcox<dim>(U, DiffU, g_mu, g_d, source, 1);
313 CHECK(source(I4 + 1) >= 0.0);
314 CHECK(source(I4 + 2) >= 0.0);
317TEST_CASE(
"GetSource_SST mode=1: implicit diagonal non-negative")
319 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
320 auto DiffU = buildShearGrad(U, g_Sshear);
321 Eigen::Vector<real, nVars> source;
324 GetSource_SST<dim>(U, DiffU, g_mu, g_d, 1e10, source, 1);
326 CHECK(source(I4 + 1) >= 0.0);
327 CHECK(source(I4 + 2) >= 0.0);
334TEST_CASE(
"GetVisFlux_KOWilcox: zero gradient -> zero flux")
336 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
338 Eigen::Matrix<real, dim, nVars> DiffPrim = Eigen::Matrix<real, dim, nVars>::Zero();
339 Eigen::Vector3d norm(1, 0, 0);
340 Eigen::Vector<real, nVars> vFlux;
344 GetVisFlux_KOWilcox<dim>(U, DiffPrim, norm, mut, g_d, g_mu, vFlux);
346 CHECK(vFlux(I4 + 1) == doctest::Approx(0.0).epsilon(1e-14));
347 CHECK(vFlux(I4 + 2) == doctest::Approx(0.0).epsilon(1e-14));
352 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
353 Eigen::Matrix<real, dim, nVars> DiffPrim = Eigen::Matrix<real, dim, nVars>::Zero();
354 Eigen::Vector3d norm(1, 0, 0);
355 Eigen::Vector<real, nVars> vFlux;
359 GetVisFlux_SST<dim>(U, DiffPrim, norm, mut, g_d, g_mu, vFlux);
361 CHECK(vFlux(I4 + 1) == doctest::Approx(0.0).epsilon(1e-14));
362 CHECK(vFlux(I4 + 2) == doctest::Approx(0.0).epsilon(1e-14));
365TEST_CASE(
"GetVisFlux_RealizableKe: zero gradient -> zero flux")
367 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_epsilon);
368 Eigen::Matrix<real, dim, nVars> DiffPrim = Eigen::Matrix<real, dim, nVars>::Zero();
369 Eigen::Vector3d norm(1, 0, 0);
370 Eigen::Vector<real, nVars> vFlux;
374 GetVisFlux_RealizableKe<dim>(U, DiffPrim, norm, mut, g_d, g_mu, vFlux);
376 CHECK(vFlux(I4 + 1) == doctest::Approx(0.0).epsilon(1e-14));
377 CHECK(vFlux(I4 + 2) == doctest::Approx(0.0).epsilon(1e-14));
384TEST_CASE(
"GetVisFlux_KOWilcox: k-gradient produces k-flux")
386 auto U = buildState(g_rho, g_u, 0, 0, g_p, g_k, g_omega);
387 Eigen::Matrix<real, dim, nVars> DiffPrim = Eigen::Matrix<real, dim, nVars>::Zero();
389 DiffPrim(0, I4 + 1) = 100.0;
390 Eigen::Vector3d norm(1, 0, 0);
391 Eigen::Vector<real, nVars> vFlux;
395 GetVisFlux_KOWilcox<dim>(U, DiffPrim, norm, mut, g_d, g_mu, vFlux);
398 CHECK(vFlux(I4 + 1) > 0.0);
399 CHECK(std::isfinite(vFlux(I4 + 1)));
401 CHECK(vFlux(I4 + 2) == doctest::Approx(0.0).epsilon(1e-14));
410 auto U1 = buildState(g_rho, g_u, 0, 0, g_p, 5.0, g_omega);
411 auto U2 = buildState(g_rho, g_u, 0, 0, g_p, 20.0, g_omega);
412 auto DiffU = buildShearGrad(U1, g_Sshear);
413 auto DiffU2 = buildShearGrad(U2, g_Sshear);
415 real mut1 = GetMut_KOWilcox<dim>(U1, DiffU, g_mu, g_d);
416 real mut2 = GetMut_KOWilcox<dim>(U2, DiffU2, g_mu, g_d);
423 auto U1 = buildState(g_rho, g_u, 0, 0, g_p, 5.0, g_omega);
424 auto U2 = buildState(g_rho, g_u, 0, 0, g_p, 20.0, g_omega);
425 auto DiffU = buildShearGrad(U1, g_Sshear);
426 auto DiffU2 = buildShearGrad(U2, g_Sshear);
428 real mut1 = GetMut_SST<dim>(U1, DiffU, g_mu, g_d);
429 real mut2 = GetMut_SST<dim>(U2, DiffU2, g_mu, g_d);
438TEST_CASE(
"GetMut_KOWilcox: very small k/omega produces finite mut")
440 auto U = buildState(g_rho, g_u, 0, 0, g_p, 1e-10, 1e-5);
441 auto DiffU = buildShearGrad(U, 0.0);
442 real mut = GetMut_KOWilcox<dim>(U, DiffU, g_mu, g_d);
444 CHECK(std::isfinite(mut));
448TEST_CASE(
"GetMut_SST: very small k/omega produces finite mut")
450 auto U = buildState(g_rho, g_u, 0, 0, g_p, 1e-10, 1e-5);
451 auto DiffU = buildShearGrad(U, 0.0);
452 real mut = GetMut_SST<dim>(U, DiffU, g_mu, g_d);
454 CHECK(std::isfinite(mut));
458TEST_CASE(
"GetMut_RealizableKe: very small k/eps produces finite mut")
460 auto U = buildState(g_rho, g_u, 0, 0, g_p, 1e-10, 1e-8);
461 auto DiffU = buildShearGrad(U, 0.0);
462 real mut = GetMut_RealizableKe<dim>(U, DiffU, g_mu, g_d);
464 CHECK(std::isfinite(mut));
RANS two-equation turbulence model implementations for the DNDSR CFD solver.
RANS turbulence model functions (eddy viscosity, viscous flux, source terms).
the host side operators are provided as implemented
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
Eigen::Matrix< real, 5, 1 > v
TEST_CASE("GetSource_KOWilcox mode=1: implicit diagonal non-negative")