|
| 1 | +/*! |
| 2 | + * \file roe_contact_tests.cpp |
| 3 | + * \brief Roe-type schemes must resolve a contact discontinuity and a shear layer exactly (upwind flux), in 2D |
| 4 | + * and 3D, on faces not aligned with the axes. |
| 5 | + * \version 8.5.0 "Harrier" |
| 6 | + * |
| 7 | + * SU2 Project Website: https://su2code.github.io |
| 8 | + * |
| 9 | + * The SU2 Project is maintained by the SU2 Foundation |
| 10 | + * (http://su2foundation.org) |
| 11 | + * |
| 12 | + * Copyright 2012-2026, SU2 Contributors (cf. AUTHORS.md) |
| 13 | + * |
| 14 | + * SU2 is free software; you can redistribute it and/or |
| 15 | + * modify it under the terms of the GNU Lesser General Public |
| 16 | + * License as published by the Free Software Foundation; either |
| 17 | + * version 2.1 of the License, or (at your option) any later version. |
| 18 | + * |
| 19 | + * SU2 is distributed in the hope that it will be useful, |
| 20 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 21 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 22 | + * Lesser General Public License for more details. |
| 23 | + * |
| 24 | + * You should have received a copy of the GNU Lesser General Public |
| 25 | + * License along with SU2. If not, see <http://www.gnu.org/licenses/>. |
| 26 | + */ |
| 27 | + |
| 28 | +#include "catch.hpp" |
| 29 | +#include <cmath> |
| 30 | +#include <memory> |
| 31 | +#include <sstream> |
| 32 | +#include "../../../SU2_CFD/include/numerics/flow/convection/roe.hpp" |
| 33 | + |
| 34 | +namespace { |
| 35 | + |
| 36 | +constexpr su2double gamma = 1.4; |
| 37 | + |
| 38 | +std::unique_ptr<CConfig> MakeConfig(bool implicit) { |
| 39 | + std::stringstream options; |
| 40 | + options << "SOLVER= EULER\nCONV_NUM_METHOD_FLOW= ROE\nENTROPY_FIX_COEFF= 0.0\nROE_KAPPA= 0.5\n"; |
| 41 | + options << "TIME_DISCRE_FLOW= " << (implicit ? "EULER_IMPLICIT" : "EULER_EXPLICIT") << "\n"; |
| 42 | + return std::make_unique<CConfig>(options, SU2_COMPONENT::SU2_CFD, false); |
| 43 | +} |
| 44 | + |
| 45 | +/*--- Primitive (T, u, v, [w], p, rho, h, c) and secondary (dp/drho_e, dp/de_rho) variables of an ideal gas. ---*/ |
| 46 | +void State(unsigned short nDim, su2double rho, const su2double* vel, su2double p, su2double* V, su2double* S) { |
| 47 | + su2double q2 = 0.0; |
| 48 | + for (unsigned short iDim = 0; iDim < nDim; iDim++) { |
| 49 | + V[iDim + 1] = vel[iDim]; |
| 50 | + q2 += vel[iDim] * vel[iDim]; |
| 51 | + } |
| 52 | + V[0] = p / (rho * 287.058); |
| 53 | + V[nDim + 1] = p; |
| 54 | + V[nDim + 2] = rho; |
| 55 | + V[nDim + 3] = gamma / (gamma - 1) * p / rho + 0.5 * q2; |
| 56 | + V[nDim + 4] = sqrt(gamma * p / rho); |
| 57 | + S[0] = p / rho; |
| 58 | + S[1] = (gamma - 1) * rho; |
| 59 | +} |
| 60 | + |
| 61 | +template <class Scheme> |
| 62 | +std::unique_ptr<CNumerics> MakeScheme(unsigned short nDim, const CConfig* config) { |
| 63 | + return std::make_unique<Scheme>(nDim, nDim + 2, config); |
| 64 | +} |
| 65 | +template <> |
| 66 | +std::unique_ptr<CNumerics> MakeScheme<CUpwRoe_Flow>(unsigned short nDim, const CConfig* config) { |
| 67 | + return std::make_unique<CUpwRoe_Flow>(nDim, nDim + 2, config, false); |
| 68 | +} |
| 69 | + |
| 70 | +/*--- Two states with the same pressure and normal velocity, different density and (with shear) tangential |
| 71 | + velocity: a contact discontinuity, whose exact (upwind) flux is the flux of the upstream state. ---*/ |
| 72 | +template <class Scheme> |
| 73 | +void CheckContact(const char* name, unsigned short nDim, const su2double* vel, bool implicit, bool shear) { |
| 74 | + auto config = MakeConfig(implicit); |
| 75 | + auto numerics = MakeScheme<Scheme>(nDim, config.get()); |
| 76 | + |
| 77 | + const su2double p = 1.0, rho_i = 1.4, rho_j = 0.7; |
| 78 | + const su2double n2[2] = {0.6, 0.8}, n3[3] = {2.0 / 7, 3.0 / 7, 6.0 / 7}; |
| 79 | + const su2double* n = (nDim == 2) ? n2 : n3; |
| 80 | + const su2double t2[2] = {0.16, -0.12}, t3[3] = {0.15, -0.1, 0.0}; // tangential velocity jumps |
| 81 | + const su2double* t = (nDim == 2) ? t2 : t3; |
| 82 | + su2double vel_j[3] = {0.0}; |
| 83 | + for (unsigned short iDim = 0; iDim < nDim; iDim++) vel_j[iDim] = vel[iDim] + (shear ? t[iDim] : 0.0); |
| 84 | + |
| 85 | + su2double Vi[10] = {0.0}, Vj[10] = {0.0}, Si[2], Sj[2]; |
| 86 | + State(nDim, rho_i, vel, p, Vi, Si); |
| 87 | + State(nDim, rho_j, vel_j, p, Vj, Sj); |
| 88 | + numerics->SetPrimitive(Vi, Vj); |
| 89 | + numerics->SetSecondary(Si, Sj); |
| 90 | + numerics->SetNormal(n); |
| 91 | + const auto res = numerics->ComputeResidual(config.get()); |
| 92 | + |
| 93 | + su2double un = 0.0; |
| 94 | + for (unsigned short iDim = 0; iDim < nDim; iDim++) un += vel[iDim] * n[iDim]; |
| 95 | + const su2double rho_up = (un >= 0.0) ? rho_i : rho_j; |
| 96 | + const su2double* V_up = (un >= 0.0) ? Vi : Vj; |
| 97 | + |
| 98 | + CAPTURE(name, nDim, un, implicit, shear); |
| 99 | + CHECK(res.residual[0] == Approx(rho_up * un).margin(1e-12)); |
| 100 | + for (unsigned short iDim = 0; iDim < nDim; iDim++) |
| 101 | + CHECK(res.residual[iDim + 1] == Approx(rho_up * V_up[iDim + 1] * un + p * n[iDim]).margin(1e-12)); |
| 102 | + CHECK(res.residual[nDim + 1] == Approx(rho_up * V_up[nDim + 3] * un).margin(1e-12)); |
| 103 | +} |
| 104 | + |
| 105 | +template <class Scheme> |
| 106 | +void CheckContacts(const char* name, bool implicit = true, bool shear = true) { |
| 107 | + const su2double zero[3] = {0.0, 0.0, 0.0}, moving[3] = {0.3, -0.1, 0.2}, reverse[3] = {-0.3, 0.1, -0.2}; |
| 108 | + for (const unsigned short nDim : {2, 3}) { |
| 109 | + for (const auto* vel : {zero, moving, reverse}) { |
| 110 | + CheckContact<Scheme>(name, nDim, vel, implicit, false); |
| 111 | + if (shear) CheckContact<Scheme>(name, nDim, vel, implicit, true); |
| 112 | + } |
| 113 | + } |
| 114 | +} |
| 115 | + |
| 116 | +} // namespace |
| 117 | + |
| 118 | +TEST_CASE("Roe schemes resolve a contact and a shear layer exactly", "[Roe]") { |
| 119 | + CheckContacts<CUpwRoe_Flow>("Roe"); |
| 120 | + CheckContacts<CUpwGeneralRoe_Flow>("general Roe", true); |
| 121 | + CheckContacts<CUpwGeneralRoe_Flow>("general Roe", false); |
| 122 | + CheckContacts<CUpwLMRoe_Flow>("LMRoe"); |
| 123 | + /*--- L2Roe scales the tangential velocity jump at low Mach number (not upwind by design). ---*/ |
| 124 | + CheckContacts<CUpwL2Roe_Flow>("L2Roe", true, false); |
| 125 | +} |
0 commit comments