From a7136d32c0f1c9b50c77a5779d9778b35359fcee Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 27 Jan 2023 18:21:13 +0100 Subject: [PATCH 01/61] - Just copied the CTransLMSolver header and source to commit --- SU2_CFD/include/solvers/CTransSLMSolver.hpp | 218 +++++++ SU2_CFD/src/solvers/CTransSLMSolver.cpp | 602 ++++++++++++++++++++ 2 files changed, 820 insertions(+) create mode 100644 SU2_CFD/include/solvers/CTransSLMSolver.hpp create mode 100644 SU2_CFD/src/solvers/CTransSLMSolver.cpp diff --git a/SU2_CFD/include/solvers/CTransSLMSolver.hpp b/SU2_CFD/include/solvers/CTransSLMSolver.hpp new file mode 100644 index 000000000000..acdf90fb9a47 --- /dev/null +++ b/SU2_CFD/include/solvers/CTransSLMSolver.hpp @@ -0,0 +1,218 @@ +/*! + * \file CTransLMSolver.hpp + * \brief Headers of the CTransLMSolver class + * \author A. Aranake + * \version 7.5.0 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2022, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#pragma once + +#include "CTurbSolver.hpp" +#include "../numerics/turbulent/transition/trans_correlations.hpp" + +/*! + * \class CTransLMSolver + * \brief Main class for defining the transition model solver. + * \ingroup Turbulence_Model + * \author A. Aranake, S. Kang. + */ + +class CTransLMSolver final : public CTurbSolver { +private: + + LM_ParsedOptions options; + TURB_FAMILY TurbFamily; + + TransLMCorrelations TransCorrelations; + +public: + /*! + * \overload + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Index of the mesh in multigrid computations. + */ + CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh); + + /*! + * \brief Destructor of the class. + */ + ~CTransLMSolver() = default; + + /*! + * \brief Restart residual and compute gradients. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Index of the mesh in multigrid computations. + * \param[in] iRKStep - Current step of the Runge-Kutta iteration. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] Output - boolean to determine whether to print output. + */ + void Preprocessing(CGeometry *geometry, + CSolver **solver_container, + CConfig *config, + unsigned short iMesh, + unsigned short iRKStep, + unsigned short RunTime_EqSystem, + bool Output) override; + + /*! + * \brief Computes the effective intermtittency. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Index of the mesh in multigrid computations. + */ + void Postprocessing(CGeometry *geometry, + CSolver **solver_container, + CConfig *config, + unsigned short iMesh) override; + + /*! + * \brief Compute the viscous flux for the LM equation at a particular edge. + * \param[in] iEdge - Edge for which we want to compute the flux + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \note Calls a generic implementation after defining a SolverSpecificNumerics object. + */ + void Viscous_Residual(unsigned long iEdge, CGeometry* geometry, CSolver** solver_container, + CNumerics* numerics, CConfig* config) override; + + /*! + * \brief Source term computation. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics_container - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Index of the mesh in multigrid computations. + */ + void Source_Residual(CGeometry *geometry, + CSolver **solver_container, + CNumerics **numerics_container, + CConfig *config, + unsigned short iMesh) override; + + /*! + * \brief Source term computation. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Index of the mesh in multigrid computations. + */ + void Source_Template(CGeometry *geometry, + CSolver **solver_container, + CNumerics *numerics, + CConfig *config, + unsigned short iMesh) override; + + /*! + * \brief Impose the Langtry Menter transition wall boundary condition. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] conv_numerics - Description of the numerical method. + * \param[in] visc_numerics - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] val_marker - Surface marker where the boundary condition is applied. + */ + void BC_HeatFlux_Wall(CGeometry *geometry, + CSolver **solver_container, + CNumerics *conv_numerics, + CNumerics *visc_numerics, + CConfig *config, + unsigned short val_marker) override; + + /*! + * \brief Impose the Navier-Stokes wall boundary condition. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] conv_numerics - Description of the numerical method. + * \param[in] visc_numerics - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] val_marker - Surface marker where the boundary condition is applied. + */ + void BC_Isothermal_Wall(CGeometry *geometry, + CSolver **solver_container, + CNumerics *conv_numerics, + CNumerics *visc_numerics, + CConfig *config, + unsigned short val_marker) override; + + /*! + * \brief Impose the inlet boundary condition. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] conv_numerics - Description of the numerical method. + * \param[in] visc_numerics - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] val_marker - Surface marker where the boundary condition is applied. + */ + void BC_Inlet(CGeometry *geometry, + CSolver **solver_container, + CNumerics *conv_numerics, + CNumerics *visc_numerics, + CConfig *config, + unsigned short val_marker) override; + + /*! + * \brief Impose the outlet boundary condition. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] conv_numerics - Description of the numerical method. + * \param[in] visc_numerics - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] val_marker - Surface marker where the boundary condition is applied. + */ + void BC_Outlet(CGeometry *geometry, + CSolver **solver_container, + CNumerics *conv_numerics, + CNumerics *visc_numerics, + CConfig *config, + unsigned short val_marker) override; + + /*! + * \brief Get the value of the intermittency. + * \return Value of the turbulent kinetic energy. + */ + inline su2double GetIntermittency_Inf(void) const override { return Solution_Inf[0]; } + + /*! + * \brief Get the value of the intermittency. + * \return Value of the turbulent kinetic energy. + */ + inline su2double GetReThetaT_Inf(void) const override { return Solution_Inf[1]; } + + /*! + * \brief Load a solution from a restart file. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver - Container vector with all of the solvers. + * \param[in] config - Definition of the particular problem. + * \param[in] val_iter - Current external iteration number. + * \param[in] val_update_geo - Flag for updating coords and grid velocity. + */ + void LoadRestart(CGeometry** geometry, CSolver*** solver, CConfig* config, int val_iter, bool val_update_geo) final; + +}; diff --git a/SU2_CFD/src/solvers/CTransSLMSolver.cpp b/SU2_CFD/src/solvers/CTransSLMSolver.cpp new file mode 100644 index 000000000000..01a254e98b7a --- /dev/null +++ b/SU2_CFD/src/solvers/CTransSLMSolver.cpp @@ -0,0 +1,602 @@ +/*! + * \file CTransLMSolver.cpp + * \brief Main subroutines for Langtry-Menter Transition model solver. + * \author A. Aranake, S. Kang. + * \version 7.5.0 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2022, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../include/solvers/CTransLMSolver.hpp" +#include "../../include/variables/CTransLMVariable.hpp" +#include "../../include/variables/CFlowVariable.hpp" +#include "../../include/variables/CTurbSAVariable.hpp" +#include "../../../Common/include/parallelization/omp_structure.hpp" +#include "../../../Common/include/toolboxes/geometry_toolbox.hpp" + +/*--- This is the implementation of the Langtry-Menter transition model. + The main reference for this model is:Langtry, Menter, AIAA J. 47(12) 2009 + DOI: https://doi.org/10.2514/1.42362 ---*/ + +// Note: TransLM seems to use rho*gamma, rho*Re_sigma as Solution variables, thus Conservative=true + +CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) + : CTurbSolver(geometry, config, true) { + unsigned long iPoint; + ifstream restart_file; + string text_line; + + bool multizone = config->GetMultizone_Problem(); + + /*--- Dimension of the problem --> 2 Transport equations (intermittency, Reth) ---*/ + nVar = 2; + nPrimVar = 2; + nPoint = geometry->GetnPoint(); + nPointDomain = geometry->GetnPointDomain(); + + /*--- Initialize nVarGrad for deallocation ---*/ + + nVarGrad = nVar; + + /*--- Define geometry constants in the solver structure ---*/ + + nDim = geometry->GetnDim(); + + /*--- Define variables needed for transition from config file */ + options = config->GetLMParsedOptions(); + TransCorrelations.SetOptions(options); + TurbFamily = TurbModelFamily(config->GetKind_Turb_Model()); + + /*--- Single grid simulation ---*/ + + if (iMesh == MESH_0) { + + /*--- Define some auxiliary vector related with the residual ---*/ + + Residual_RMS.resize(nVar,0.0); + Residual_Max.resize(nVar,0.0); + Point_Max.resize(nVar,0); + Point_Max_Coord.resize(nVar,nDim) = su2double(0.0); + + /*--- Initialization of the structure of the whole Jacobian ---*/ + + if (rank == MASTER_NODE) cout << "Initialize Jacobian structure (LM transition model)." << endl; + Jacobian.Initialize(nPoint, nPointDomain, nVar, nVar, true, geometry, config, ReducerStrategy); + LinSysSol.Initialize(nPoint, nPointDomain, nVar, 0.0); + LinSysRes.Initialize(nPoint, nPointDomain, nVar, 0.0); + System.SetxIsZero(true); + + if (ReducerStrategy) + EdgeFluxes.Initialize(geometry->GetnEdge(), geometry->GetnEdge(), nVar, nullptr); + + /*--- Initialize the BGS residuals in multizone problems. ---*/ + if (multizone){ + Residual_BGS.resize(nVar,0.0); + Residual_Max_BGS.resize(nVar,0.0); + Point_Max_BGS.resize(nVar,0); + Point_Max_Coord_BGS.resize(nVar,nDim) = su2double(0.0); + } + + } + + /*--- Initialize lower and upper limits---*/ + lowerlimit[0] = 1.0e-4; + upperlimit[0] = 5.0; + + lowerlimit[1] = 1.0e-4; + upperlimit[1] = 1.0e15; + + /*--- Far-field flow state quantities and initialization. ---*/ + const su2double Intensity = config->GetTurbulenceIntensity_FreeStream()*100.0; + + const su2double Intermittency_Inf = 1.0; + su2double ReThetaT_Inf = 100.0; + + /*--- Momentum thickness Reynolds number, initialized from freestream turbulent intensity*/ + if (Intensity <= 1.3) { + if(Intensity >=0.027) { + ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(Intensity*Intensity)); + } + else { + ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(0.27*0.27)); + } + } + else if(Intensity>1.3) { + ReThetaT_Inf = 331.5*pow(Intensity-0.5658,-0.671); + } + + Solution_Inf[0] = Intermittency_Inf; + Solution_Inf[1] = ReThetaT_Inf; + + /*--- Initialize the solution to the far-field state everywhere. ---*/ + nodes = new CTransLMVariable(Intermittency_Inf, ReThetaT_Inf, 1.0, 1.0, nPoint, nDim, nVar, config); + SetBaseClassPointerToNodes(); + + /*--- MPI solution ---*/ + + InitiateComms(geometry, config, SOLUTION); + CompleteComms(geometry, config, SOLUTION); + + /*--- Initializate quantities for SlidingMesh Interface ---*/ + + SlidingState.resize(nMarker); + SlidingStateNodes.resize(nMarker); + + for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) { + if (config->GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE) { + SlidingState[iMarker].resize(nVertex[iMarker], nPrimVar+1) = nullptr; + SlidingStateNodes[iMarker].resize(nVertex[iMarker],0); + } + } + + /*-- Allocation of inlets has to happen in derived classes (not CTurbSolver), + due to arbitrary number of turbulence variables ---*/ + + Inlet_TurbVars.resize(nMarker); + for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) { + Inlet_TurbVars[iMarker].resize(nVertex[iMarker],nVar); + for (unsigned long iVertex = 0; iVertex < nVertex[iMarker]; ++iVertex) { + Inlet_TurbVars[iMarker](iVertex,0) = Intermittency_Inf; + Inlet_TurbVars[iMarker](iVertex,1) = ReThetaT_Inf; + } + } + + const su2double CFL = config->GetCFL(MGLevel)*config->GetCFLRedCoeff_Turb(); + for (iPoint = 0; iPoint < nPoint; iPoint++) { + nodes->SetLocalCFL(iPoint, CFL); + } + Min_CFL_Local = CFL; + Max_CFL_Local = CFL; + Avg_CFL_Local = CFL; + + /*--- Add the solver name (max 8 characters) ---*/ + SolverName = "LM model"; + +} + +void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, + unsigned short iMesh, unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output) { + SU2_OMP_SAFE_GLOBAL_ACCESS(config->SetGlobalParam(config->GetKind_Solver(), RunTime_EqSystem);) + + /*--- Upwind second order reconstruction and gradients ---*/ + CommonPreprocessing(geometry, config, Output); +} + +void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh) { + + /*--- Compute LM model gradients. ---*/ + + if (config->GetKind_Gradient_Method() == GREEN_GAUSS) { + SetSolution_Gradient_GG(geometry, config); + } + if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) { + SetSolution_Gradient_LS(geometry, config); + } + + AD::StartNoSharedReading(); + auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); + auto* turbNodes = su2staticcast_p(solver_container[TURB_SOL]->GetNodes()); + + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + + // Here the nodes already have the new solution, thus I have to compute everything from scratch + + const su2double rho = flowNodes->GetDensity(iPoint); + const su2double mu = flowNodes->GetLaminarViscosity(iPoint); + const su2double muT = turbNodes->GetmuT(iPoint); + const su2double dist = geometry->nodes->GetWall_Distance(iPoint); + su2double VorticityMag = GeometryToolbox::Norm(3, flowNodes->GetVorticity(iPoint)); + su2double StrainMag =flowNodes->GetStrainMag(iPoint); + VorticityMag = max(VorticityMag, 1e-12); + StrainMag = max(StrainMag, 1e-12); // safety against division by zero + const su2double Intermittency = nodes->GetSolution(iPoint,0); + const su2double Re_t = nodes->GetSolution(iPoint,1); + const su2double Re_v = rho*dist*dist*StrainMag/mu; + const su2double vel_u = flowNodes->GetVelocity(iPoint, 0); + const su2double vel_v = flowNodes->GetVelocity(iPoint, 1); + const su2double vel_w = (nDim ==3) ? flowNodes->GetVelocity(iPoint, 2) : 0.0; + const su2double VelocityMag = sqrt(vel_u*vel_u + vel_v*vel_v + vel_w*vel_w); + su2double omega = 0.0; + su2double k = 0.0; + if(TurbFamily == TURB_FAMILY::KW){ + omega = turbNodes->GetSolution(iPoint,1); + k = turbNodes->GetSolution(iPoint,0); + } + su2double Tu = 1.0; + if(TurbFamily == TURB_FAMILY::KW) + Tu = max(100.0*sqrt( 2.0 * k / 3.0 ) / VelocityMag,0.027); + if(TurbFamily == TURB_FAMILY::SA) + Tu = config->GetTurbulenceIntensity_FreeStream()*100; + + const su2double Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, Re_t); + + su2double R_t = 1.0; + if(TurbFamily == TURB_FAMILY::KW) + R_t = rho*k/ mu/ omega; + if(TurbFamily == TURB_FAMILY::SA) + R_t = muT/ mu; + + const su2double f_reattach = exp(-pow(R_t/20,4)); + su2double f_wake = 0.0; + if(TurbFamily == TURB_FAMILY::KW){ + const su2double re_omega = rho*omega*dist*dist/mu; + f_wake = exp(-pow(re_omega/(1.0e+05),2)); + } + if(TurbFamily == TURB_FAMILY::SA) + f_wake = 1.0; + + const su2double theta_bl = Re_t*mu / rho /VelocityMag; + const su2double delta_bl = 7.5*theta_bl; + const su2double delta = 50.0*VorticityMag*dist/VelocityMag*delta_bl + 1e-20; + const su2double var1 = (Intermittency-1.0/50.0)/(1.0-1.0/50.0); + const su2double var2 = 1.0 - pow(var1,2.0); + const su2double f_theta = min(max(f_wake*exp(-pow(dist/delta, 4)), var2), 1.0); + su2double Intermittency_Sep = 2.0*max(0.0, Re_v/(3.235*Corr_Rec)-1.0)*f_reattach; + Intermittency_Sep = min(Intermittency_Sep,2.0)*f_theta; + Intermittency_Sep = min(max(0.0, Intermittency_Sep), 2.0); + nodes -> SetIntermittencySep(iPoint, Intermittency_Sep); + nodes -> SetIntermittencyEff(iPoint, Intermittency_Sep); + + } + END_SU2_OMP_FOR + + AD::EndNoSharedReading(); +} + + +void CTransLMSolver::Viscous_Residual(unsigned long iEdge, CGeometry* geometry, CSolver** solver_container, + CNumerics* numerics, CConfig* config) { + + /*--- Define an object to set solver specific numerics contribution. ---*/ + + auto SolverSpecificNumerics = [&](unsigned long iPoint, unsigned long jPoint) {}; + + /*--- Now instantiate the generic implementation with the functor above. ---*/ + + Viscous_Residual_impl(SolverSpecificNumerics, iEdge, geometry, solver_container, numerics, config); +} + + +void CTransLMSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); + + auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); + //auto* turbNodes = su2staticcast_p(solver_container[TURB_SOL]->GetNodes()); + CVariable* turbNodes = solver_container[TURB_SOL]->GetNodes(); + + /*--- Pick one numerics object per thread. ---*/ + auto* numerics = numerics_container[SOURCE_FIRST_TERM + omp_get_thread_num()*MAX_TERMS]; + + /*--- Loop over all points. ---*/ + + AD::StartNoSharedReading(); + + SU2_OMP_FOR_DYN(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { + + + + /*--- Conservative variables w/o reconstruction ---*/ + + numerics->SetPrimitive(flowNodes->GetPrimitive(iPoint), nullptr); + + /*--- Gradient of the primitive and conservative variables ---*/ + + numerics->SetPrimVarGradient(flowNodes->GetGradient_Primitive(iPoint), nullptr); + + /*--- Turbulent variables w/o reconstruction, and its gradient ---*/ + /*--- ScalarVar & ScalarVarGradient : Turbulence model solution(k&w) ---*/ + + numerics->SetScalarVar(turbNodes->GetSolution(iPoint), nullptr); + numerics->SetScalarVarGradient(turbNodes->GetGradient(iPoint), nullptr); + + /*--- Transition variables w/o reconstruction, and its gradient ---*/ + + numerics->SetTransVar(nodes->GetSolution(iPoint), nullptr); + numerics->SetTransVarGradient(nodes->GetGradient(iPoint), nullptr); + + /*--- Set volume ---*/ + + numerics->SetVolume(geometry->nodes->GetVolume(iPoint)); + + /*--- Set distance to the surface ---*/ + + numerics->SetDistance(geometry->nodes->GetWall_Distance(iPoint), 0.0); + + /*--- Set vorticity and strain rate magnitude ---*/ + + numerics->SetVorticity(flowNodes->GetVorticity(iPoint), nullptr); + + numerics->SetStrainMag(flowNodes->GetStrainMag(iPoint), 0.0); + + /*--- Set coordinate (for debugging) ---*/ + numerics->SetCoord(geometry->nodes->GetCoord(iPoint), nullptr); + + if (options.LM2015) { + /*--- Set local grid length (for LM2015)*/ + numerics->SetLocalGridLength(geometry->nodes->GetMaxLength(iPoint)); + } + + /*--- Compute the source term ---*/ + + auto residual = numerics->ComputeResidual(config); + + /*--- Subtract residual and the Jacobian ---*/ + + LinSysRes.SubtractBlock(iPoint, residual); + if (implicit) Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); + + } + END_SU2_OMP_FOR + + AD::EndNoSharedReading(); + +} + +void CTransLMSolver::Source_Template(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, + CConfig *config, unsigned short iMesh) { +} + +void CTransLMSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + + const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); + + SU2_OMP_FOR_STAT(OMP_MIN_SIZE) + for (auto iVertex = 0u; iVertex < geometry->nVertex[val_marker]; iVertex++) { + + const auto iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); + + /*--- Check if the node belongs to the domain (i.e, not a halo node) ---*/ + + if (geometry->nodes->GetDomain(iPoint)) { + + /*--- Allocate the value at the infinity ---*/ + + auto V_infty = solver_container[FLOW_SOL]->GetCharacPrimVar(val_marker, iVertex); + + /*--- Retrieve solution at the farfield boundary node ---*/ + + auto V_domain = solver_container[FLOW_SOL]->GetNodes()->GetPrimitive(iPoint); + + conv_numerics->SetPrimitive(V_domain, V_infty); + + /*--- Set turbulent variable at the wall, and at infinity ---*/ + + conv_numerics->SetScalarVar(nodes->GetSolution(iPoint), Solution_Inf); + + /*--- Set Normal (it is necessary to change the sign) ---*/ + /*--- It's mean wall normal zero flux. */ + + su2double Normal[MAXNDIM] = {0.0}; + for (auto iDim = 0u; iDim < nDim; iDim++) + Normal[iDim] = -geometry->vertex[val_marker][iVertex]->GetNormal(iDim); + conv_numerics->SetNormal(Normal); + + /*--- Grid Movement ---*/ + + if (dynamic_grid) + conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), + geometry->nodes->GetGridVel(iPoint)); + + /*--- Compute residuals and Jacobians ---*/ + + auto residual = conv_numerics->ComputeResidual(config); + + /*--- Add residuals and Jacobians ---*/ + + LinSysRes.AddBlock(iPoint, residual); + if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); + } + } + END_SU2_OMP_FOR + +} + +void CTransLMSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + + BC_HeatFlux_Wall(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker); + +} + +void CTransLMSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, + unsigned short val_marker) { + const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); + + /*--- Loop over all the vertices on this boundary marker ---*/ + + SU2_OMP_FOR_STAT(OMP_MIN_SIZE) + for (auto iVertex = 0u; iVertex < geometry->nVertex[val_marker]; iVertex++) { + + const auto iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); + + /*--- Check if the node belongs to the domain (i.e., not a halo node) ---*/ + + if (geometry->nodes->GetDomain(iPoint)) { + + /*--- Normal vector for this vertex (negate for outward convention) ---*/ + + su2double Normal[MAXNDIM] = {0.0}; + for (auto iDim = 0u; iDim < nDim; iDim++) + Normal[iDim] = -geometry->vertex[val_marker][iVertex]->GetNormal(iDim); + conv_numerics->SetNormal(Normal); + + /*--- Allocate the value at the inlet ---*/ + + auto V_inlet = solver_container[FLOW_SOL]->GetCharacPrimVar(val_marker, iVertex); + + /*--- Retrieve solution at the farfield boundary node ---*/ + + auto V_domain = solver_container[FLOW_SOL]->GetNodes()->GetPrimitive(iPoint); + + /*--- Set various quantities in the solver class ---*/ + + conv_numerics->SetPrimitive(V_domain, V_inlet); + + /*--- Non-dimensionalize Inlet_TurbVars if Inlet-Files are used. ---*/ + su2double Inlet_Vars[MAXNVAR]; + Inlet_Vars[0] = Inlet_TurbVars[val_marker][iVertex][0]; + Inlet_Vars[1] = Inlet_TurbVars[val_marker][iVertex][1]; + if (config->GetInlet_Profile_From_File()) { + Inlet_Vars[0] /= pow(config->GetVelocity_Ref(), 2); + Inlet_Vars[1] *= config->GetViscosity_Ref() / (config->GetDensity_Ref() * pow(config->GetVelocity_Ref(), 2)); + } + + /*--- Set the LM variable states. ---*/ + /*--- Load the inlet transition LM model variables (uniform by default). ---*/ + + conv_numerics->SetScalarVar(nodes->GetSolution(iPoint), Inlet_Vars); + + /*--- Set various other quantities in the solver class ---*/ + + if (dynamic_grid) + conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), + geometry->nodes->GetGridVel(iPoint)); + + /*--- Compute the residual using an upwind scheme ---*/ + + auto residual = conv_numerics->ComputeResidual(config); + LinSysRes.AddBlock(iPoint, residual); + + /*--- Jacobian contribution for implicit integration ---*/ + + if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); + } + } + END_SU2_OMP_FOR + +} + +void CTransLMSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + BC_Far_Field(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker); +} + +void CTransLMSolver::LoadRestart(CGeometry** geometry, CSolver*** solver, CConfig* config, int val_iter, + bool val_update_geo) { + + const string restart_filename = config->GetFilename(config->GetSolution_FileName(), "", val_iter); + + /*--- To make this routine safe to call in parallel most of it can only be executed by one thread. ---*/ + BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS { + /*--- Read the restart data from either an ASCII or binary SU2 file. ---*/ + + if (config->GetRead_Binary_Restart()) { + Read_SU2_Restart_Binary(geometry[MESH_0], config, restart_filename); + } else { + Read_SU2_Restart_ASCII(geometry[MESH_0], config, restart_filename); + } + + /*--- Skip flow variables ---*/ + + unsigned short skipVars = nDim + solver[MESH_0][FLOW_SOL]->GetnVar() + solver[MESH_0][TURB_SOL] ->GetnVar(); + + /*--- Adjust the number of solution variables in the incompressible + restart. We always carry a space in nVar for the energy equation in the + mean flow solver, but we only write it to the restart if it is active. + Therefore, we must reduce skipVars here if energy is inactive so that + the turbulent variables are read correctly. ---*/ + + const bool incompressible = (config->GetKind_Regime() == ENUM_REGIME::INCOMPRESSIBLE); + const bool energy = config->GetEnergy_Equation(); + const bool weakly_coupled_heat = config->GetWeakly_Coupled_Heat(); + + if (incompressible && ((!energy) && (!weakly_coupled_heat))) skipVars--; + + /*--- Load data from the restart into correct containers. ---*/ + + unsigned long counter = 0; + for (auto iPoint_Global = 0ul; iPoint_Global < geometry[MESH_0]->GetGlobal_nPointDomain(); iPoint_Global++) { + /*--- Retrieve local index. If this node from the restart file lives + on the current processor, we will load and instantiate the vars. ---*/ + + const auto iPoint_Local = geometry[MESH_0]->GetGlobal_to_Local_Point(iPoint_Global); + + if (iPoint_Local > -1) { + /*--- We need to store this point's data, so jump to the correct + offset in the buffer of data from the restart file and load it. ---*/ + + const auto index = counter * Restart_Vars[1] + skipVars; + for (auto iVar = 0u; iVar < nVar; iVar++) nodes->SetSolution(iPoint_Local, iVar, Restart_Data[index + iVar]); + nodes ->SetIntermittencySep(iPoint_Local, Restart_Data[index + 2]); + nodes ->SetIntermittencyEff(iPoint_Local, Restart_Data[index + 3]); + + /*--- Increment the overall counter for how many points have been loaded. ---*/ + counter++; + } + } + + /*--- Detect a wrong solution file ---*/ + + if (counter != nPointDomain) { + SU2_MPI::Error(string("The solution file ") + restart_filename + string(" does not match with the mesh file!\n") + + string("This can be caused by empty lines at the end of the file."), + CURRENT_FUNCTION); + } + + } // end SU2_OMP_MASTER, pre and postprocessing are thread-safe. + END_SU2_OMP_SAFE_GLOBAL_ACCESS + + /*--- MPI solution and compute the eddy viscosity ---*/ + + solver[MESH_0][TRANS_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION); + solver[MESH_0][TRANS_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION); + + /*--- For turbulent+species simulations the solver Pre-/Postprocessing is done by the species solver. ---*/ + if (config->GetKind_Species_Model() == SPECIES_MODEL::NONE) { + solver[MESH_0][FLOW_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER, + RUNTIME_FLOW_SYS, false); + solver[MESH_0][TURB_SOL]->Postprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0); + solver[MESH_0][TRANS_SOL]->Postprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0); + } + + /*--- Interpolate the solution down to the coarse multigrid levels ---*/ + + for (auto iMesh = 1u; iMesh <= config->GetnMGLevels(); iMesh++) { + + MultigridRestriction(*geometry[iMesh - 1], solver[iMesh - 1][TRANS_SOL]->GetNodes()->GetSolution(), + *geometry[iMesh], solver[iMesh][TRANS_SOL]->GetNodes()->GetSolution()); + solver[iMesh][TRANS_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION); + solver[iMesh][TRANS_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION); + + if (config->GetKind_Species_Model() == SPECIES_MODEL::NONE) { + solver[iMesh][FLOW_SOL]->Preprocessing(geometry[iMesh], solver[iMesh], config, iMesh, NO_RK_ITER, RUNTIME_FLOW_SYS, + false); + solver[iMesh][TRANS_SOL]->Postprocessing(geometry[iMesh], solver[iMesh], config, iMesh); + } + } + + /*--- Go back to single threaded execution. ---*/ + BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS { + /*--- Delete the class memory that is used to load the restart. ---*/ + + delete[] Restart_Vars; + Restart_Vars = nullptr; + delete[] Restart_Data; + Restart_Data = nullptr; + } + END_SU2_OMP_SAFE_GLOBAL_ACCESS + +} \ No newline at end of file From e9226db18fdf915d49e780ca1e82741fac63bb85 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 27 Jan 2023 18:57:31 +0100 Subject: [PATCH 02/61] - Start of implementation of Simplified LM transition model --- Common/include/option_structure.hpp | 4 + SU2_CFD/include/solvers/CTransSLMSolver.hpp | 218 ------- SU2_CFD/src/solvers/CSolverFactory.cpp | 2 +- SU2_CFD/src/solvers/CTransSLMSolver.cpp | 602 -------------------- 4 files changed, 5 insertions(+), 821 deletions(-) delete mode 100644 SU2_CFD/include/solvers/CTransSLMSolver.hpp delete mode 100644 SU2_CFD/src/solvers/CTransSLMSolver.cpp diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp index d39d6abde86a..6fe937973638 100644 --- a/Common/include/option_structure.hpp +++ b/Common/include/option_structure.hpp @@ -1174,6 +1174,7 @@ static const MapType Trans_Model_Map = { enum class LM_OPTIONS { NONE, /*!< \brief No option / default. */ LM2015, /*!< \brief Cross-flow corrections. */ + SLM, /*!< \brief Simplified version. */ MALAN, /*!< \brief Kind of transition correlation model (Malan). */ SULUKSNA, /*!< \brief Kind of transition correlation model (Suluksna). */ KRAUSE, /*!< \brief Kind of transition correlation model (Krause). */ @@ -1187,6 +1188,7 @@ enum class LM_OPTIONS { static const MapType LM_Options_Map = { MakePair("NONE", LM_OPTIONS::NONE) MakePair("LM2015", LM_OPTIONS::LM2015) + MakePair("SLM", LM_OPTIONS::SLM) MakePair("MALAN", LM_OPTIONS::MALAN) MakePair("SULUKSNA", LM_OPTIONS::SULUKSNA) MakePair("KRAUSE", LM_OPTIONS::KRAUSE) @@ -1216,6 +1218,7 @@ enum class TURB_TRANS_CORRELATION { struct LM_ParsedOptions { LM_OPTIONS version = LM_OPTIONS::NONE; /*!< \brief LM base model. */ bool LM2015 = false; /*!< \brief Use cross-flow corrections. */ + bool SLM = false; /*!< \brief Use simplified version. */ TURB_TRANS_CORRELATION Correlation = TURB_TRANS_CORRELATION::DEFAULT; }; @@ -1235,6 +1238,7 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh }; LMParsedOptions.LM2015 = IsPresent(LM_OPTIONS::LM2015); + LMParsedOptions.SLM = IsPresent(LM_OPTIONS::SLM); int NFoundCorrelations = 0; if (IsPresent(LM_OPTIONS::MALAN)) { diff --git a/SU2_CFD/include/solvers/CTransSLMSolver.hpp b/SU2_CFD/include/solvers/CTransSLMSolver.hpp deleted file mode 100644 index acdf90fb9a47..000000000000 --- a/SU2_CFD/include/solvers/CTransSLMSolver.hpp +++ /dev/null @@ -1,218 +0,0 @@ -/*! - * \file CTransLMSolver.hpp - * \brief Headers of the CTransLMSolver class - * \author A. Aranake - * \version 7.5.0 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2022, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - -#pragma once - -#include "CTurbSolver.hpp" -#include "../numerics/turbulent/transition/trans_correlations.hpp" - -/*! - * \class CTransLMSolver - * \brief Main class for defining the transition model solver. - * \ingroup Turbulence_Model - * \author A. Aranake, S. Kang. - */ - -class CTransLMSolver final : public CTurbSolver { -private: - - LM_ParsedOptions options; - TURB_FAMILY TurbFamily; - - TransLMCorrelations TransCorrelations; - -public: - /*! - * \overload - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - */ - CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh); - - /*! - * \brief Destructor of the class. - */ - ~CTransLMSolver() = default; - - /*! - * \brief Restart residual and compute gradients. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] iRKStep - Current step of the Runge-Kutta iteration. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] Output - boolean to determine whether to print output. - */ - void Preprocessing(CGeometry *geometry, - CSolver **solver_container, - CConfig *config, - unsigned short iMesh, - unsigned short iRKStep, - unsigned short RunTime_EqSystem, - bool Output) override; - - /*! - * \brief Computes the effective intermtittency. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - */ - void Postprocessing(CGeometry *geometry, - CSolver **solver_container, - CConfig *config, - unsigned short iMesh) override; - - /*! - * \brief Compute the viscous flux for the LM equation at a particular edge. - * \param[in] iEdge - Edge for which we want to compute the flux - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \note Calls a generic implementation after defining a SolverSpecificNumerics object. - */ - void Viscous_Residual(unsigned long iEdge, CGeometry* geometry, CSolver** solver_container, - CNumerics* numerics, CConfig* config) override; - - /*! - * \brief Source term computation. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics_container - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - */ - void Source_Residual(CGeometry *geometry, - CSolver **solver_container, - CNumerics **numerics_container, - CConfig *config, - unsigned short iMesh) override; - - /*! - * \brief Source term computation. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - */ - void Source_Template(CGeometry *geometry, - CSolver **solver_container, - CNumerics *numerics, - CConfig *config, - unsigned short iMesh) override; - - /*! - * \brief Impose the Langtry Menter transition wall boundary condition. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the numerical method. - * \param[in] visc_numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] val_marker - Surface marker where the boundary condition is applied. - */ - void BC_HeatFlux_Wall(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) override; - - /*! - * \brief Impose the Navier-Stokes wall boundary condition. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the numerical method. - * \param[in] visc_numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] val_marker - Surface marker where the boundary condition is applied. - */ - void BC_Isothermal_Wall(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) override; - - /*! - * \brief Impose the inlet boundary condition. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the numerical method. - * \param[in] visc_numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] val_marker - Surface marker where the boundary condition is applied. - */ - void BC_Inlet(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) override; - - /*! - * \brief Impose the outlet boundary condition. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] conv_numerics - Description of the numerical method. - * \param[in] visc_numerics - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] val_marker - Surface marker where the boundary condition is applied. - */ - void BC_Outlet(CGeometry *geometry, - CSolver **solver_container, - CNumerics *conv_numerics, - CNumerics *visc_numerics, - CConfig *config, - unsigned short val_marker) override; - - /*! - * \brief Get the value of the intermittency. - * \return Value of the turbulent kinetic energy. - */ - inline su2double GetIntermittency_Inf(void) const override { return Solution_Inf[0]; } - - /*! - * \brief Get the value of the intermittency. - * \return Value of the turbulent kinetic energy. - */ - inline su2double GetReThetaT_Inf(void) const override { return Solution_Inf[1]; } - - /*! - * \brief Load a solution from a restart file. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver - Container vector with all of the solvers. - * \param[in] config - Definition of the particular problem. - * \param[in] val_iter - Current external iteration number. - * \param[in] val_update_geo - Flag for updating coords and grid velocity. - */ - void LoadRestart(CGeometry** geometry, CSolver*** solver, CConfig* config, int val_iter, bool val_update_geo) final; - -}; diff --git a/SU2_CFD/src/solvers/CSolverFactory.cpp b/SU2_CFD/src/solvers/CSolverFactory.cpp index bf2a09ddfe56..9ee374d254b3 100644 --- a/SU2_CFD/src/solvers/CSolverFactory.cpp +++ b/SU2_CFD/src/solvers/CSolverFactory.cpp @@ -381,7 +381,7 @@ CSolver* CSolverFactory::CreateTransSolver(TURB_TRANS_MODEL kindTransModel, CSol solver[FLOW_SOL]->Preprocessing(geometry, solver, config, iMGLevel, NO_RK_ITER, RUNTIME_FLOW_SYS, false); transSolver->Postprocessing(geometry, solver, config, iMGLevel); solver[FLOW_SOL]->Preprocessing(geometry, solver, config, iMGLevel, NO_RK_ITER, RUNTIME_FLOW_SYS, false); - break; + break; case TURB_TRANS_MODEL::NONE: break; } diff --git a/SU2_CFD/src/solvers/CTransSLMSolver.cpp b/SU2_CFD/src/solvers/CTransSLMSolver.cpp deleted file mode 100644 index 01a254e98b7a..000000000000 --- a/SU2_CFD/src/solvers/CTransSLMSolver.cpp +++ /dev/null @@ -1,602 +0,0 @@ -/*! - * \file CTransLMSolver.cpp - * \brief Main subroutines for Langtry-Menter Transition model solver. - * \author A. Aranake, S. Kang. - * \version 7.5.0 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2022, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - -#include "../../include/solvers/CTransLMSolver.hpp" -#include "../../include/variables/CTransLMVariable.hpp" -#include "../../include/variables/CFlowVariable.hpp" -#include "../../include/variables/CTurbSAVariable.hpp" -#include "../../../Common/include/parallelization/omp_structure.hpp" -#include "../../../Common/include/toolboxes/geometry_toolbox.hpp" - -/*--- This is the implementation of the Langtry-Menter transition model. - The main reference for this model is:Langtry, Menter, AIAA J. 47(12) 2009 - DOI: https://doi.org/10.2514/1.42362 ---*/ - -// Note: TransLM seems to use rho*gamma, rho*Re_sigma as Solution variables, thus Conservative=true - -CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) - : CTurbSolver(geometry, config, true) { - unsigned long iPoint; - ifstream restart_file; - string text_line; - - bool multizone = config->GetMultizone_Problem(); - - /*--- Dimension of the problem --> 2 Transport equations (intermittency, Reth) ---*/ - nVar = 2; - nPrimVar = 2; - nPoint = geometry->GetnPoint(); - nPointDomain = geometry->GetnPointDomain(); - - /*--- Initialize nVarGrad for deallocation ---*/ - - nVarGrad = nVar; - - /*--- Define geometry constants in the solver structure ---*/ - - nDim = geometry->GetnDim(); - - /*--- Define variables needed for transition from config file */ - options = config->GetLMParsedOptions(); - TransCorrelations.SetOptions(options); - TurbFamily = TurbModelFamily(config->GetKind_Turb_Model()); - - /*--- Single grid simulation ---*/ - - if (iMesh == MESH_0) { - - /*--- Define some auxiliary vector related with the residual ---*/ - - Residual_RMS.resize(nVar,0.0); - Residual_Max.resize(nVar,0.0); - Point_Max.resize(nVar,0); - Point_Max_Coord.resize(nVar,nDim) = su2double(0.0); - - /*--- Initialization of the structure of the whole Jacobian ---*/ - - if (rank == MASTER_NODE) cout << "Initialize Jacobian structure (LM transition model)." << endl; - Jacobian.Initialize(nPoint, nPointDomain, nVar, nVar, true, geometry, config, ReducerStrategy); - LinSysSol.Initialize(nPoint, nPointDomain, nVar, 0.0); - LinSysRes.Initialize(nPoint, nPointDomain, nVar, 0.0); - System.SetxIsZero(true); - - if (ReducerStrategy) - EdgeFluxes.Initialize(geometry->GetnEdge(), geometry->GetnEdge(), nVar, nullptr); - - /*--- Initialize the BGS residuals in multizone problems. ---*/ - if (multizone){ - Residual_BGS.resize(nVar,0.0); - Residual_Max_BGS.resize(nVar,0.0); - Point_Max_BGS.resize(nVar,0); - Point_Max_Coord_BGS.resize(nVar,nDim) = su2double(0.0); - } - - } - - /*--- Initialize lower and upper limits---*/ - lowerlimit[0] = 1.0e-4; - upperlimit[0] = 5.0; - - lowerlimit[1] = 1.0e-4; - upperlimit[1] = 1.0e15; - - /*--- Far-field flow state quantities and initialization. ---*/ - const su2double Intensity = config->GetTurbulenceIntensity_FreeStream()*100.0; - - const su2double Intermittency_Inf = 1.0; - su2double ReThetaT_Inf = 100.0; - - /*--- Momentum thickness Reynolds number, initialized from freestream turbulent intensity*/ - if (Intensity <= 1.3) { - if(Intensity >=0.027) { - ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(Intensity*Intensity)); - } - else { - ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(0.27*0.27)); - } - } - else if(Intensity>1.3) { - ReThetaT_Inf = 331.5*pow(Intensity-0.5658,-0.671); - } - - Solution_Inf[0] = Intermittency_Inf; - Solution_Inf[1] = ReThetaT_Inf; - - /*--- Initialize the solution to the far-field state everywhere. ---*/ - nodes = new CTransLMVariable(Intermittency_Inf, ReThetaT_Inf, 1.0, 1.0, nPoint, nDim, nVar, config); - SetBaseClassPointerToNodes(); - - /*--- MPI solution ---*/ - - InitiateComms(geometry, config, SOLUTION); - CompleteComms(geometry, config, SOLUTION); - - /*--- Initializate quantities for SlidingMesh Interface ---*/ - - SlidingState.resize(nMarker); - SlidingStateNodes.resize(nMarker); - - for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) { - if (config->GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE) { - SlidingState[iMarker].resize(nVertex[iMarker], nPrimVar+1) = nullptr; - SlidingStateNodes[iMarker].resize(nVertex[iMarker],0); - } - } - - /*-- Allocation of inlets has to happen in derived classes (not CTurbSolver), - due to arbitrary number of turbulence variables ---*/ - - Inlet_TurbVars.resize(nMarker); - for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) { - Inlet_TurbVars[iMarker].resize(nVertex[iMarker],nVar); - for (unsigned long iVertex = 0; iVertex < nVertex[iMarker]; ++iVertex) { - Inlet_TurbVars[iMarker](iVertex,0) = Intermittency_Inf; - Inlet_TurbVars[iMarker](iVertex,1) = ReThetaT_Inf; - } - } - - const su2double CFL = config->GetCFL(MGLevel)*config->GetCFLRedCoeff_Turb(); - for (iPoint = 0; iPoint < nPoint; iPoint++) { - nodes->SetLocalCFL(iPoint, CFL); - } - Min_CFL_Local = CFL; - Max_CFL_Local = CFL; - Avg_CFL_Local = CFL; - - /*--- Add the solver name (max 8 characters) ---*/ - SolverName = "LM model"; - -} - -void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, - unsigned short iMesh, unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output) { - SU2_OMP_SAFE_GLOBAL_ACCESS(config->SetGlobalParam(config->GetKind_Solver(), RunTime_EqSystem);) - - /*--- Upwind second order reconstruction and gradients ---*/ - CommonPreprocessing(geometry, config, Output); -} - -void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh) { - - /*--- Compute LM model gradients. ---*/ - - if (config->GetKind_Gradient_Method() == GREEN_GAUSS) { - SetSolution_Gradient_GG(geometry, config); - } - if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) { - SetSolution_Gradient_LS(geometry, config); - } - - AD::StartNoSharedReading(); - auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); - auto* turbNodes = su2staticcast_p(solver_container[TURB_SOL]->GetNodes()); - - SU2_OMP_FOR_STAT(omp_chunk_size) - for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { - - // Here the nodes already have the new solution, thus I have to compute everything from scratch - - const su2double rho = flowNodes->GetDensity(iPoint); - const su2double mu = flowNodes->GetLaminarViscosity(iPoint); - const su2double muT = turbNodes->GetmuT(iPoint); - const su2double dist = geometry->nodes->GetWall_Distance(iPoint); - su2double VorticityMag = GeometryToolbox::Norm(3, flowNodes->GetVorticity(iPoint)); - su2double StrainMag =flowNodes->GetStrainMag(iPoint); - VorticityMag = max(VorticityMag, 1e-12); - StrainMag = max(StrainMag, 1e-12); // safety against division by zero - const su2double Intermittency = nodes->GetSolution(iPoint,0); - const su2double Re_t = nodes->GetSolution(iPoint,1); - const su2double Re_v = rho*dist*dist*StrainMag/mu; - const su2double vel_u = flowNodes->GetVelocity(iPoint, 0); - const su2double vel_v = flowNodes->GetVelocity(iPoint, 1); - const su2double vel_w = (nDim ==3) ? flowNodes->GetVelocity(iPoint, 2) : 0.0; - const su2double VelocityMag = sqrt(vel_u*vel_u + vel_v*vel_v + vel_w*vel_w); - su2double omega = 0.0; - su2double k = 0.0; - if(TurbFamily == TURB_FAMILY::KW){ - omega = turbNodes->GetSolution(iPoint,1); - k = turbNodes->GetSolution(iPoint,0); - } - su2double Tu = 1.0; - if(TurbFamily == TURB_FAMILY::KW) - Tu = max(100.0*sqrt( 2.0 * k / 3.0 ) / VelocityMag,0.027); - if(TurbFamily == TURB_FAMILY::SA) - Tu = config->GetTurbulenceIntensity_FreeStream()*100; - - const su2double Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, Re_t); - - su2double R_t = 1.0; - if(TurbFamily == TURB_FAMILY::KW) - R_t = rho*k/ mu/ omega; - if(TurbFamily == TURB_FAMILY::SA) - R_t = muT/ mu; - - const su2double f_reattach = exp(-pow(R_t/20,4)); - su2double f_wake = 0.0; - if(TurbFamily == TURB_FAMILY::KW){ - const su2double re_omega = rho*omega*dist*dist/mu; - f_wake = exp(-pow(re_omega/(1.0e+05),2)); - } - if(TurbFamily == TURB_FAMILY::SA) - f_wake = 1.0; - - const su2double theta_bl = Re_t*mu / rho /VelocityMag; - const su2double delta_bl = 7.5*theta_bl; - const su2double delta = 50.0*VorticityMag*dist/VelocityMag*delta_bl + 1e-20; - const su2double var1 = (Intermittency-1.0/50.0)/(1.0-1.0/50.0); - const su2double var2 = 1.0 - pow(var1,2.0); - const su2double f_theta = min(max(f_wake*exp(-pow(dist/delta, 4)), var2), 1.0); - su2double Intermittency_Sep = 2.0*max(0.0, Re_v/(3.235*Corr_Rec)-1.0)*f_reattach; - Intermittency_Sep = min(Intermittency_Sep,2.0)*f_theta; - Intermittency_Sep = min(max(0.0, Intermittency_Sep), 2.0); - nodes -> SetIntermittencySep(iPoint, Intermittency_Sep); - nodes -> SetIntermittencyEff(iPoint, Intermittency_Sep); - - } - END_SU2_OMP_FOR - - AD::EndNoSharedReading(); -} - - -void CTransLMSolver::Viscous_Residual(unsigned long iEdge, CGeometry* geometry, CSolver** solver_container, - CNumerics* numerics, CConfig* config) { - - /*--- Define an object to set solver specific numerics contribution. ---*/ - - auto SolverSpecificNumerics = [&](unsigned long iPoint, unsigned long jPoint) {}; - - /*--- Now instantiate the generic implementation with the functor above. ---*/ - - Viscous_Residual_impl(SolverSpecificNumerics, iEdge, geometry, solver_container, numerics, config); -} - - -void CTransLMSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { - - const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); - - auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); - //auto* turbNodes = su2staticcast_p(solver_container[TURB_SOL]->GetNodes()); - CVariable* turbNodes = solver_container[TURB_SOL]->GetNodes(); - - /*--- Pick one numerics object per thread. ---*/ - auto* numerics = numerics_container[SOURCE_FIRST_TERM + omp_get_thread_num()*MAX_TERMS]; - - /*--- Loop over all points. ---*/ - - AD::StartNoSharedReading(); - - SU2_OMP_FOR_DYN(omp_chunk_size) - for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { - - - - /*--- Conservative variables w/o reconstruction ---*/ - - numerics->SetPrimitive(flowNodes->GetPrimitive(iPoint), nullptr); - - /*--- Gradient of the primitive and conservative variables ---*/ - - numerics->SetPrimVarGradient(flowNodes->GetGradient_Primitive(iPoint), nullptr); - - /*--- Turbulent variables w/o reconstruction, and its gradient ---*/ - /*--- ScalarVar & ScalarVarGradient : Turbulence model solution(k&w) ---*/ - - numerics->SetScalarVar(turbNodes->GetSolution(iPoint), nullptr); - numerics->SetScalarVarGradient(turbNodes->GetGradient(iPoint), nullptr); - - /*--- Transition variables w/o reconstruction, and its gradient ---*/ - - numerics->SetTransVar(nodes->GetSolution(iPoint), nullptr); - numerics->SetTransVarGradient(nodes->GetGradient(iPoint), nullptr); - - /*--- Set volume ---*/ - - numerics->SetVolume(geometry->nodes->GetVolume(iPoint)); - - /*--- Set distance to the surface ---*/ - - numerics->SetDistance(geometry->nodes->GetWall_Distance(iPoint), 0.0); - - /*--- Set vorticity and strain rate magnitude ---*/ - - numerics->SetVorticity(flowNodes->GetVorticity(iPoint), nullptr); - - numerics->SetStrainMag(flowNodes->GetStrainMag(iPoint), 0.0); - - /*--- Set coordinate (for debugging) ---*/ - numerics->SetCoord(geometry->nodes->GetCoord(iPoint), nullptr); - - if (options.LM2015) { - /*--- Set local grid length (for LM2015)*/ - numerics->SetLocalGridLength(geometry->nodes->GetMaxLength(iPoint)); - } - - /*--- Compute the source term ---*/ - - auto residual = numerics->ComputeResidual(config); - - /*--- Subtract residual and the Jacobian ---*/ - - LinSysRes.SubtractBlock(iPoint, residual); - if (implicit) Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); - - } - END_SU2_OMP_FOR - - AD::EndNoSharedReading(); - -} - -void CTransLMSolver::Source_Template(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, - CConfig *config, unsigned short iMesh) { -} - -void CTransLMSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, - CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { - - const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); - - SU2_OMP_FOR_STAT(OMP_MIN_SIZE) - for (auto iVertex = 0u; iVertex < geometry->nVertex[val_marker]; iVertex++) { - - const auto iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); - - /*--- Check if the node belongs to the domain (i.e, not a halo node) ---*/ - - if (geometry->nodes->GetDomain(iPoint)) { - - /*--- Allocate the value at the infinity ---*/ - - auto V_infty = solver_container[FLOW_SOL]->GetCharacPrimVar(val_marker, iVertex); - - /*--- Retrieve solution at the farfield boundary node ---*/ - - auto V_domain = solver_container[FLOW_SOL]->GetNodes()->GetPrimitive(iPoint); - - conv_numerics->SetPrimitive(V_domain, V_infty); - - /*--- Set turbulent variable at the wall, and at infinity ---*/ - - conv_numerics->SetScalarVar(nodes->GetSolution(iPoint), Solution_Inf); - - /*--- Set Normal (it is necessary to change the sign) ---*/ - /*--- It's mean wall normal zero flux. */ - - su2double Normal[MAXNDIM] = {0.0}; - for (auto iDim = 0u; iDim < nDim; iDim++) - Normal[iDim] = -geometry->vertex[val_marker][iVertex]->GetNormal(iDim); - conv_numerics->SetNormal(Normal); - - /*--- Grid Movement ---*/ - - if (dynamic_grid) - conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), - geometry->nodes->GetGridVel(iPoint)); - - /*--- Compute residuals and Jacobians ---*/ - - auto residual = conv_numerics->ComputeResidual(config); - - /*--- Add residuals and Jacobians ---*/ - - LinSysRes.AddBlock(iPoint, residual); - if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); - } - } - END_SU2_OMP_FOR - -} - -void CTransLMSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, - CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { - - BC_HeatFlux_Wall(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker); - -} - -void CTransLMSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, - unsigned short val_marker) { - const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); - - /*--- Loop over all the vertices on this boundary marker ---*/ - - SU2_OMP_FOR_STAT(OMP_MIN_SIZE) - for (auto iVertex = 0u; iVertex < geometry->nVertex[val_marker]; iVertex++) { - - const auto iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); - - /*--- Check if the node belongs to the domain (i.e., not a halo node) ---*/ - - if (geometry->nodes->GetDomain(iPoint)) { - - /*--- Normal vector for this vertex (negate for outward convention) ---*/ - - su2double Normal[MAXNDIM] = {0.0}; - for (auto iDim = 0u; iDim < nDim; iDim++) - Normal[iDim] = -geometry->vertex[val_marker][iVertex]->GetNormal(iDim); - conv_numerics->SetNormal(Normal); - - /*--- Allocate the value at the inlet ---*/ - - auto V_inlet = solver_container[FLOW_SOL]->GetCharacPrimVar(val_marker, iVertex); - - /*--- Retrieve solution at the farfield boundary node ---*/ - - auto V_domain = solver_container[FLOW_SOL]->GetNodes()->GetPrimitive(iPoint); - - /*--- Set various quantities in the solver class ---*/ - - conv_numerics->SetPrimitive(V_domain, V_inlet); - - /*--- Non-dimensionalize Inlet_TurbVars if Inlet-Files are used. ---*/ - su2double Inlet_Vars[MAXNVAR]; - Inlet_Vars[0] = Inlet_TurbVars[val_marker][iVertex][0]; - Inlet_Vars[1] = Inlet_TurbVars[val_marker][iVertex][1]; - if (config->GetInlet_Profile_From_File()) { - Inlet_Vars[0] /= pow(config->GetVelocity_Ref(), 2); - Inlet_Vars[1] *= config->GetViscosity_Ref() / (config->GetDensity_Ref() * pow(config->GetVelocity_Ref(), 2)); - } - - /*--- Set the LM variable states. ---*/ - /*--- Load the inlet transition LM model variables (uniform by default). ---*/ - - conv_numerics->SetScalarVar(nodes->GetSolution(iPoint), Inlet_Vars); - - /*--- Set various other quantities in the solver class ---*/ - - if (dynamic_grid) - conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), - geometry->nodes->GetGridVel(iPoint)); - - /*--- Compute the residual using an upwind scheme ---*/ - - auto residual = conv_numerics->ComputeResidual(config); - LinSysRes.AddBlock(iPoint, residual); - - /*--- Jacobian contribution for implicit integration ---*/ - - if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); - } - } - END_SU2_OMP_FOR - -} - -void CTransLMSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, - CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { - BC_Far_Field(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker); -} - -void CTransLMSolver::LoadRestart(CGeometry** geometry, CSolver*** solver, CConfig* config, int val_iter, - bool val_update_geo) { - - const string restart_filename = config->GetFilename(config->GetSolution_FileName(), "", val_iter); - - /*--- To make this routine safe to call in parallel most of it can only be executed by one thread. ---*/ - BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS { - /*--- Read the restart data from either an ASCII or binary SU2 file. ---*/ - - if (config->GetRead_Binary_Restart()) { - Read_SU2_Restart_Binary(geometry[MESH_0], config, restart_filename); - } else { - Read_SU2_Restart_ASCII(geometry[MESH_0], config, restart_filename); - } - - /*--- Skip flow variables ---*/ - - unsigned short skipVars = nDim + solver[MESH_0][FLOW_SOL]->GetnVar() + solver[MESH_0][TURB_SOL] ->GetnVar(); - - /*--- Adjust the number of solution variables in the incompressible - restart. We always carry a space in nVar for the energy equation in the - mean flow solver, but we only write it to the restart if it is active. - Therefore, we must reduce skipVars here if energy is inactive so that - the turbulent variables are read correctly. ---*/ - - const bool incompressible = (config->GetKind_Regime() == ENUM_REGIME::INCOMPRESSIBLE); - const bool energy = config->GetEnergy_Equation(); - const bool weakly_coupled_heat = config->GetWeakly_Coupled_Heat(); - - if (incompressible && ((!energy) && (!weakly_coupled_heat))) skipVars--; - - /*--- Load data from the restart into correct containers. ---*/ - - unsigned long counter = 0; - for (auto iPoint_Global = 0ul; iPoint_Global < geometry[MESH_0]->GetGlobal_nPointDomain(); iPoint_Global++) { - /*--- Retrieve local index. If this node from the restart file lives - on the current processor, we will load and instantiate the vars. ---*/ - - const auto iPoint_Local = geometry[MESH_0]->GetGlobal_to_Local_Point(iPoint_Global); - - if (iPoint_Local > -1) { - /*--- We need to store this point's data, so jump to the correct - offset in the buffer of data from the restart file and load it. ---*/ - - const auto index = counter * Restart_Vars[1] + skipVars; - for (auto iVar = 0u; iVar < nVar; iVar++) nodes->SetSolution(iPoint_Local, iVar, Restart_Data[index + iVar]); - nodes ->SetIntermittencySep(iPoint_Local, Restart_Data[index + 2]); - nodes ->SetIntermittencyEff(iPoint_Local, Restart_Data[index + 3]); - - /*--- Increment the overall counter for how many points have been loaded. ---*/ - counter++; - } - } - - /*--- Detect a wrong solution file ---*/ - - if (counter != nPointDomain) { - SU2_MPI::Error(string("The solution file ") + restart_filename + string(" does not match with the mesh file!\n") + - string("This can be caused by empty lines at the end of the file."), - CURRENT_FUNCTION); - } - - } // end SU2_OMP_MASTER, pre and postprocessing are thread-safe. - END_SU2_OMP_SAFE_GLOBAL_ACCESS - - /*--- MPI solution and compute the eddy viscosity ---*/ - - solver[MESH_0][TRANS_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION); - solver[MESH_0][TRANS_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION); - - /*--- For turbulent+species simulations the solver Pre-/Postprocessing is done by the species solver. ---*/ - if (config->GetKind_Species_Model() == SPECIES_MODEL::NONE) { - solver[MESH_0][FLOW_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER, - RUNTIME_FLOW_SYS, false); - solver[MESH_0][TURB_SOL]->Postprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0); - solver[MESH_0][TRANS_SOL]->Postprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0); - } - - /*--- Interpolate the solution down to the coarse multigrid levels ---*/ - - for (auto iMesh = 1u; iMesh <= config->GetnMGLevels(); iMesh++) { - - MultigridRestriction(*geometry[iMesh - 1], solver[iMesh - 1][TRANS_SOL]->GetNodes()->GetSolution(), - *geometry[iMesh], solver[iMesh][TRANS_SOL]->GetNodes()->GetSolution()); - solver[iMesh][TRANS_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION); - solver[iMesh][TRANS_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION); - - if (config->GetKind_Species_Model() == SPECIES_MODEL::NONE) { - solver[iMesh][FLOW_SOL]->Preprocessing(geometry[iMesh], solver[iMesh], config, iMesh, NO_RK_ITER, RUNTIME_FLOW_SYS, - false); - solver[iMesh][TRANS_SOL]->Postprocessing(geometry[iMesh], solver[iMesh], config, iMesh); - } - } - - /*--- Go back to single threaded execution. ---*/ - BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS { - /*--- Delete the class memory that is used to load the restart. ---*/ - - delete[] Restart_Vars; - Restart_Vars = nullptr; - delete[] Restart_Data; - Restart_Data = nullptr; - } - END_SU2_OMP_SAFE_GLOBAL_ACCESS - -} \ No newline at end of file From d03742af36f37757e1a2eff2182cf02f11af2c7c Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 27 Jan 2023 19:17:58 +0100 Subject: [PATCH 03/61] - Modify number of variables if SLM option is used --- SU2_CFD/src/solvers/CSolverFactory.cpp | 2 +- SU2_CFD/src/solvers/CTransLMSolver.cpp | 46 ++++++++++++++-------- SU2_CFD/src/variables/CTransLMVariable.cpp | 5 ++- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/SU2_CFD/src/solvers/CSolverFactory.cpp b/SU2_CFD/src/solvers/CSolverFactory.cpp index 9ee374d254b3..11726796d69c 100644 --- a/SU2_CFD/src/solvers/CSolverFactory.cpp +++ b/SU2_CFD/src/solvers/CSolverFactory.cpp @@ -381,7 +381,7 @@ CSolver* CSolverFactory::CreateTransSolver(TURB_TRANS_MODEL kindTransModel, CSol solver[FLOW_SOL]->Preprocessing(geometry, solver, config, iMGLevel, NO_RK_ITER, RUNTIME_FLOW_SYS, false); transSolver->Postprocessing(geometry, solver, config, iMGLevel); solver[FLOW_SOL]->Preprocessing(geometry, solver, config, iMGLevel, NO_RK_ITER, RUNTIME_FLOW_SYS, false); - break; + break; case TURB_TRANS_MODEL::NONE: break; } diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 01a254e98b7a..0ceb3d86992f 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -60,11 +60,17 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh nDim = geometry->GetnDim(); - /*--- Define variables needed for transition from config file */ + /*--- Define variables needed for transition from config file ---*/ options = config->GetLMParsedOptions(); TransCorrelations.SetOptions(options); TurbFamily = TurbModelFamily(config->GetKind_Turb_Model()); + /*--- Check if Simplified version is used ---*/ + if (options.SLM) { + nVar = 1; + nPrimVar = 1; + } + /*--- Single grid simulation ---*/ if (iMesh == MESH_0) { @@ -101,33 +107,41 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh lowerlimit[0] = 1.0e-4; upperlimit[0] = 5.0; - lowerlimit[1] = 1.0e-4; - upperlimit[1] = 1.0e15; + if (!options.SLM) { + lowerlimit[1] = 1.0e-4; + upperlimit[1] = 1.0e15; + } /*--- Far-field flow state quantities and initialization. ---*/ const su2double Intensity = config->GetTurbulenceIntensity_FreeStream()*100.0; const su2double Intermittency_Inf = 1.0; - su2double ReThetaT_Inf = 100.0; + Solution_Inf[0] = Intermittency_Inf; - /*--- Momentum thickness Reynolds number, initialized from freestream turbulent intensity*/ - if (Intensity <= 1.3) { - if(Intensity >=0.027) { - ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(Intensity*Intensity)); + su2double ReThetaT_Inf = 0.0; + + if (!options.SLM) { + su2double ReThetaT_Inf = 100.0; + + /*--- Momentum thickness Reynolds number, initialized from freestream turbulent intensity*/ + if (Intensity <= 1.3) { + if(Intensity >=0.027) { + ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(Intensity*Intensity)); + } + else { + ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(0.27*0.27)); + } } - else { - ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(0.27*0.27)); + else if(Intensity>1.3) { + ReThetaT_Inf = 331.5*pow(Intensity-0.5658,-0.671); } - } - else if(Intensity>1.3) { - ReThetaT_Inf = 331.5*pow(Intensity-0.5658,-0.671); - } - Solution_Inf[0] = Intermittency_Inf; - Solution_Inf[1] = ReThetaT_Inf; + Solution_Inf[1] = ReThetaT_Inf; + } /*--- Initialize the solution to the far-field state everywhere. ---*/ nodes = new CTransLMVariable(Intermittency_Inf, ReThetaT_Inf, 1.0, 1.0, nPoint, nDim, nVar, config); + SetBaseClassPointerToNodes(); /*--- MPI solution ---*/ diff --git a/SU2_CFD/src/variables/CTransLMVariable.cpp b/SU2_CFD/src/variables/CTransLMVariable.cpp index df345c23aef7..ce73c451942b 100644 --- a/SU2_CFD/src/variables/CTransLMVariable.cpp +++ b/SU2_CFD/src/variables/CTransLMVariable.cpp @@ -31,10 +31,13 @@ CTransLMVariable::CTransLMVariable(su2double Intermittency, su2double ReThetaT, su2double gammaSep, su2double gammaEff, unsigned long npoint, unsigned long ndim, unsigned long nvar, CConfig *config) : CTurbVariable(npoint, ndim, nvar, config) { + LM_ParsedOptions options = config->GetLMParsedOptions(); + for(unsigned long iPoint=0; iPoint Date: Tue, 31 Jan 2023 18:26:43 +0100 Subject: [PATCH 04/61] - Updates on the transition model. - Added correlations for Simplified LM. - There is a bug on the computation of grad(n*U)*n --- Common/include/geometry/dual_grid/CPoint.hpp | 12 ++ Common/include/option_structure.hpp | 43 +++- Common/src/CConfig.cpp | 26 ++- SU2_CFD/include/numerics/CNumerics.hpp | 19 ++ .../turbulent/transition/trans_convection.hpp | 7 + .../transition/trans_correlations.hpp | 103 ++++++++++ .../turbulent/transition/trans_diffusion.hpp | 69 +++++++ .../turbulent/transition/trans_sources.hpp | 189 +++++++++++++++++- .../numerics/turbulent/turb_sources.hpp | 10 + .../include/variables/CTransLMVariable.hpp | 33 +++ SU2_CFD/include/variables/CVariable.hpp | 20 ++ SU2_CFD/src/drivers/CDriver.cpp | 30 ++- SU2_CFD/src/output/CFlowOutput.cpp | 46 +++-- SU2_CFD/src/solvers/CTransLMSolver.cpp | 129 ++++++++++-- SU2_CFD/src/variables/CTransLMVariable.cpp | 35 +++- 15 files changed, 726 insertions(+), 45 deletions(-) diff --git a/Common/include/geometry/dual_grid/CPoint.hpp b/Common/include/geometry/dual_grid/CPoint.hpp index b5750ddb4d25..82489486acd8 100644 --- a/Common/include/geometry/dual_grid/CPoint.hpp +++ b/Common/include/geometry/dual_grid/CPoint.hpp @@ -456,6 +456,18 @@ class CPoint { } inline void SetWall_Distance(unsigned long iPoint, su2double distance) { Wall_Distance(iPoint) = distance; } + /*! + * \brief Get the index of the closest wall element. + * \param[in] iPoint - Index of the point. + */ + inline unsigned long GetClosestWall_Elem(unsigned long iPoint) {return ClosestWall_Elem(iPoint);} + + /*! + * \brief Get the marker of the closest wall marker. + * \param[in] iPoint - Index of the point. + */ + inline unsigned long GetClosestWall_Marker(unsigned long iPoint) {return ClosestWall_Marker(iPoint);} + /*! * \brief Get the value of the distance to the nearest wall. * \param[in] iPoint - Index of the point. diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp index 6fe937973638..63f2676ffdec 100644 --- a/Common/include/option_structure.hpp +++ b/Common/include/option_structure.hpp @@ -1175,6 +1175,7 @@ enum class LM_OPTIONS { NONE, /*!< \brief No option / default. */ LM2015, /*!< \brief Cross-flow corrections. */ SLM, /*!< \brief Simplified version. */ + PRODLIM, /*!< \brief Add production term to Pk. */ MALAN, /*!< \brief Kind of transition correlation model (Malan). */ SULUKSNA, /*!< \brief Kind of transition correlation model (Suluksna). */ KRAUSE, /*!< \brief Kind of transition correlation model (Krause). */ @@ -1182,6 +1183,9 @@ enum class LM_OPTIONS { MEDIDA_BAEDER,/*!< \brief Kind of transition correlation model (Medida-Baeder). */ MEDIDA, /*!< \brief Kind of transition correlation model (Medida). */ MENTER_LANGTRY, /*!< \brief Kind of transition correlation model (Menter-Langtry). */ + MENTER_SLM, /*!< \brief Kind of transition correlation model (Menter Simplified LM model). */ + CODER_SLM, /*!< \brief Kind of transition correlation model (Coder Simplified LM model). */ + MOD_EPPLER_SLM, /*!< \brief Kind of transition correlation model (Modified Eppler Simplified LM model). */ DEFAULT /*!< \brief Kind of transition correlation model (Menter-Langtry if SST, MALAN if SA). */ }; @@ -1189,12 +1193,16 @@ static const MapType LM_Options_Map = { MakePair("NONE", LM_OPTIONS::NONE) MakePair("LM2015", LM_OPTIONS::LM2015) MakePair("SLM", LM_OPTIONS::SLM) + MakePair("PRODLIM", LM_OPTIONS::PRODLIM) MakePair("MALAN", LM_OPTIONS::MALAN) MakePair("SULUKSNA", LM_OPTIONS::SULUKSNA) MakePair("KRAUSE", LM_OPTIONS::KRAUSE) MakePair("KRAUSE_HYPER", LM_OPTIONS::KRAUSE_HYPER) MakePair("MEDIDA_BAEDER", LM_OPTIONS::MEDIDA_BAEDER) MakePair("MENTER_LANGTRY", LM_OPTIONS::MENTER_LANGTRY) + MakePair("MENTER_SLM", LM_OPTIONS::MENTER_SLM) + MakePair("CODER_SLM", LM_OPTIONS::CODER_SLM) + MakePair("MOD_EPPLER_SLM", LM_OPTIONS::MOD_EPPLER_SLM) MakePair("DEFAULT", LM_OPTIONS::DEFAULT) }; @@ -1212,14 +1220,26 @@ enum class TURB_TRANS_CORRELATION { DEFAULT /*!< \brief Kind of transition correlation model (Menter-Langtry if SST, MALAN if SA). */ }; +/*! + * \brief Types of transition correlations for Simplified LM model + */ +enum class TURB_TRANS_CORRELATION_SLM { + MENTER_SLM, /*!< \brief Kind of transition correlation model (Menter Simplified LM model). */ + CODER_SLM, /*!< \brief Kind of transition correlation model (Coder Simplified LM model). */ + MOD_EPPLER_SLM, /*!< \brief Kind of transition correlation model (Modified Eppler Simplified LM model). */ + DEFAULT /*!< \brief Kind of transition correlation model. */ +}; + /*! * \brief Structure containing parsed LM options. */ struct LM_ParsedOptions { LM_OPTIONS version = LM_OPTIONS::NONE; /*!< \brief LM base model. */ bool LM2015 = false; /*!< \brief Use cross-flow corrections. */ - bool SLM = false; /*!< \brief Use simplified version. */ + bool SLM = false; /*!< \brief Use simplified version. */ + bool ProdLim = false; /*!< \brief Add production term to Pk. */ TURB_TRANS_CORRELATION Correlation = TURB_TRANS_CORRELATION::DEFAULT; + TURB_TRANS_CORRELATION_SLM Correlation_SLM = TURB_TRANS_CORRELATION_SLM::DEFAULT; }; /*! @@ -1239,8 +1259,10 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh LMParsedOptions.LM2015 = IsPresent(LM_OPTIONS::LM2015); LMParsedOptions.SLM = IsPresent(LM_OPTIONS::SLM); + LMParsedOptions.ProdLim = IsPresent(LM_OPTIONS::PRODLIM); int NFoundCorrelations = 0; + int NFoundCorrelations_SLM = 0; if (IsPresent(LM_OPTIONS::MALAN)) { LMParsedOptions.Correlation = TURB_TRANS_CORRELATION::MALAN; NFoundCorrelations++; @@ -1269,10 +1291,25 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh LMParsedOptions.Correlation = TURB_TRANS_CORRELATION::MENTER_LANGTRY; NFoundCorrelations++; } + if (IsPresent(LM_OPTIONS::MENTER_SLM)) { + LMParsedOptions.Correlation_SLM = TURB_TRANS_CORRELATION_SLM::MENTER_SLM; + NFoundCorrelations_SLM++; + } + if (IsPresent(LM_OPTIONS::CODER_SLM)) { + LMParsedOptions.Correlation_SLM = TURB_TRANS_CORRELATION_SLM::CODER_SLM; + NFoundCorrelations_SLM++; + } + if (IsPresent(LM_OPTIONS::MOD_EPPLER_SLM)) { + LMParsedOptions.Correlation_SLM = TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM; + NFoundCorrelations_SLM++; + } if (NFoundCorrelations > 1) { SU2_MPI::Error("Two correlations selected for LM_OPTIONS. Please choose only one.", CURRENT_FUNCTION); } + if (NFoundCorrelations_SLM > 1) { + SU2_MPI::Error("Two correlations selected for Simplified model into LM_OPTIONS. Please choose only one.", CURRENT_FUNCTION); + } if (LMParsedOptions.Correlation == TURB_TRANS_CORRELATION::DEFAULT){ if (Kind_Turb_Model == TURB_MODEL::SST) { @@ -1282,6 +1319,10 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh } } + if (LMParsedOptions.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::DEFAULT){ + LMParsedOptions.Correlation_SLM = TURB_TRANS_CORRELATION_SLM::MENTER_SLM; + } + return LMParsedOptions; } diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 0357290120fe..04ce1bc67349 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -6113,11 +6113,26 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { switch (Kind_Trans_Model) { case TURB_TRANS_MODEL::NONE: break; case TURB_TRANS_MODEL::LM: { - cout << "Transition model: Langtry and Menter's 4 equation model"; + int NTurbEqs = 0; + switch (Kind_Turb_Model) { + case TURB_MODEL::SA: NTurbEqs = 1; break; + case TURB_MODEL::SST: NTurbEqs = 2; break; + } + if (!lmParsedOptions.SLM) { + int NEquations = 2; + cout << "Transition model: Langtry and Menter's "<< NEquations+NTurbEqs <<" equation model"; + } else { + int NEquations = 1; + cout << "Transition model: Simplified Langtry and Menter's "<< NEquations+NTurbEqs <<" equation model"; + } if (lmParsedOptions.LM2015) { cout << " w/ cross-flow corrections (2015)" << endl; } else { - cout << " (2009)" << endl; + if (!lmParsedOptions.SLM) { + cout << " (2009)" << endl; + } else { + cout << " (2015)" << endl; + } } break; } @@ -6141,6 +6156,13 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { } break; } + cout << "Correlation Functions for Simplified LM model: "; + switch (lmParsedOptions.Correlation_SLM) { + case TURB_TRANS_CORRELATION_SLM::CODER_SLM: cout << "Coder et al. (2012)" << endl; break; + case TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM: cout << "Modified Eppler (from Coder et al. 2012)" << endl; break; + case TURB_TRANS_CORRELATION_SLM::MENTER_SLM: + case TURB_TRANS_CORRELATION_SLM::DEFAULT: cout << "Menter et al. (2015)" << endl; break; + } } cout << "Hybrid RANS/LES: "; switch (Kind_HybridRANSLES) { diff --git a/SU2_CFD/include/numerics/CNumerics.hpp b/SU2_CFD/include/numerics/CNumerics.hpp index 4eea7d9debd0..4b4c9c6224fa 100644 --- a/SU2_CFD/include/numerics/CNumerics.hpp +++ b/SU2_CFD/include/numerics/CNumerics.hpp @@ -734,6 +734,25 @@ class CNumerics { */ su2double GetIntermittencyEff() const { return intermittency_eff_i; } + /*! + * \brief Get the value of the Transition Momentum Thickness Reynolds number from correlations. + * \param[in] Corr_Rec_i - Value of the Transition Momentum Thickness Reynolds number at point i. + */ + inline virtual su2double GetCorr_Rec() {return 0.0;} + + /*! + * \brief Get the value of the Momentum Thickness Reynolds number. + * \param[in] Corr_Rec_i - Value of the Momentum Thickness Reynolds number at point i. + */ + inline virtual su2double GetRe_t() {return 0.0;} + + /*! + * \brief Set the gradient of the auxiliary variables. + * \param[in] val_auxvar_grad_i - Gradient of the auxiliary variable at point i. + * \param[in] val_auxvar_grad_j - Gradient of the auxiliary variable at point j. + */ + inline virtual void SetAuxVar(su2double val_AuxVar) {} + /*! * \brief Set the gradient of the auxiliary variables. * \param[in] val_auxvar_grad_i - Gradient of the auxiliary variable at point i. diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_convection.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_convection.hpp index 88de5a666e25..ebcb0257af9f 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_convection.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_convection.hpp @@ -38,3 +38,10 @@ template using CUpwSca_TransLM = CUpwSca_TurbSST; +/*! + * \class CUpwSca_TransSLM + * \brief Re-use the SA convective fluxes for the scalar upwind discretization of Simplified LM transition model equations. + * \ingroup ConvDiscr + */ +template +using CUpwSca_TransSLM = CUpwSca_TurbSA; diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp index bb80218ac6dc..a4f9f663fbd3 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp @@ -25,6 +25,7 @@ */ #pragma once +//#include /*! * \class TransLMCorrelations @@ -189,4 +190,106 @@ class TransLMCorrelations { return F_length1; } + + /*! + * \brief Compute Re_theta_c from correlations for the Simplified LM model. + * \param[in] Tu - Turbulence intensity. + * \param[in] du_ds - Streamwise velocity gradient. + * \param[out] rethetac - Corrected value for Re_theta. + */ + su2double ReThetaC_Correlations_SLM(const su2double Tu_L, const su2double du_ds, const su2double wall_dist, const su2double Laminar_Viscosity, const su2double Density, const su2double VorticityMag, const su2double VelocityMag) const { + + su2double rethetac = 0.0; + + switch (options.Correlation_SLM) { + case TURB_TRANS_CORRELATION_SLM::MENTER_SLM: { + + /*-- Thwaites parameter ---*/ + su2double lambda_theta_local = 7.57e-3 * du_ds * wall_dist * wall_dist * Density / Laminar_Viscosity + 0.0128; + lambda_theta_local = min(max(lambda_theta_local, -1.0), 1.0); + + /*-- Function to sensitize the transition onset to the streamwise pressure gradient ---*/ + su2double FPG = 0.0; + const su2double C_PG1 = 14.68; + const su2double C_PG1_lim = 1.5; + const su2double C_PG2 = -7.34; + const su2double C_PG2_lim = 3.0; + const su2double C_PG3 = 0.0; + if (lambda_theta_local >= 0.0) { + FPG = min(1+ C_PG1 * lambda_theta_local, C_PG1_lim); + } else { + const su2double FirstTerm = C_PG2 * lambda_theta_local; + const su2double SecondTerm = C_PG3 * min(lambda_theta_local + 0.0681, 0.0); + FPG = min(1 + FirstTerm + SecondTerm, C_PG2_lim); + } + + FPG = max(FPG, 0.0); + + const su2double C_TU1 = 100.0; + const su2double C_TU2 = 1000.0; + const su2double C_TU3 = 1.0; + rethetac = C_TU1 + C_TU2 * exp(-C_TU3 * Tu_L * FPG); + + break; + } case TURB_TRANS_CORRELATION_SLM::CODER_SLM: { + + /*-- Local pressure gradient parameter ---*/ + const su2double H_c = max(min(wall_dist * VorticityMag / VelocityMag, 1.1542), 0.3823); + + /*-- Thwaites parameter ---*/ + su2double lambda_theta_local = 0.0; + const su2double H_c_delta = 0.587743 - H_c; + if ( H_c >= 0.587743 ) { + const su2double FirstTerm = 0.1919 * pow(H_c_delta, 3.0); + const su2double SecondTerm = 0.4182 * pow(H_c_delta, 2.0); + const su2double ThirdTerm = 0.2959 * H_c_delta; + lambda_theta_local = FirstTerm + SecondTerm + ThirdTerm; + } else { + const su2double FirstTerm = 4.7596 * pow(H_c_delta, 3.0); + const su2double SecondTerm = -0.3837 * pow(H_c_delta, 2.0); + const su2double ThirdTerm = 0.3575 * H_c_delta; + lambda_theta_local = FirstTerm + SecondTerm + ThirdTerm; + } + + /*-- Function to sensitize the transition onset to the streamwise pressure gradient ---*/ + su2double FPG = 0.0; + if (lambda_theta_local <= 0.0) { + const su2double FirstTerm = -12.986 * lambda_theta_local; + const su2double SecondTerm = -123.66 * pow(lambda_theta_local, 2.0); + const su2double ThirdTerm = -405.689 * pow(lambda_theta_local, 3.0); + FPG = 1 - (FirstTerm + SecondTerm + ThirdTerm) * exp(-pow(Tu_L/1.5,1.5)); + } else { + FPG = 1 + 0.275 * (1 - exp(-35.0 * lambda_theta_local)) * exp(-Tu_L/0.5); + } + + // This is not reported in the paper + //FPG = max(FPG, 0.0); + + const su2double C_TU1 = 100.0; + const su2double C_TU2 = 1000.0; + const su2double C_TU3 = 1.0; + rethetac = C_TU1 + C_TU2 * exp(-C_TU3 * Tu_L * FPG); + + break; + } case TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM: { + + /*-- Local pressure gradient parameter ---*/ + const su2double H_c = max(min(wall_dist * VorticityMag / VelocityMag, 1.1542), 0.3823); + + /*-- H_32 Shape factor --*/ + const su2double H_32 = 1.515095 + 0.2041 * pow((1.1542 - H_c), 2.0956); + + rethetac = exp(127.94 * pow((H_32-1.515095), 2.0) + 6.774224); + + break; + } + case TURB_TRANS_CORRELATION_SLM::DEFAULT: + SU2_MPI::Error("Transition correlation for Simplified LM model is set to DEFAULT but no default value has ben set in the code.", + CURRENT_FUNCTION); + break; + } + + return rethetac; + } + }; diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp index 0ad86cf349de..6deafc31f7c2 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp @@ -103,3 +103,72 @@ class CAvgGrad_TransLM final : public CAvgGrad_Scalar { } }; + + +/*! + * \class CAvgGrad_TransSLM + * \brief Class for computing viscous term using average of gradient with correction (Simplified LM transition model). + * \ingroup ViscDiscr + * \author S. Kang. + */ +template +class CAvgGrad_TransSLM final : public CAvgGrad_Scalar { +private: + using Base = CAvgGrad_Scalar; + using Base::Laminar_Viscosity_i; + using Base::Laminar_Viscosity_j; + using Base::Eddy_Viscosity_i; + using Base::Eddy_Viscosity_j; + using Base::Density_i; + using Base::Density_j; + using Base::ScalarVar_i; + using Base::ScalarVar_j; + using Base::Proj_Mean_GradScalarVar; + using Base::proj_vector_ij; + using Base::Flux; + using Base::Jacobian_i; + using Base::Jacobian_j; + + /*! + * \brief Adds any extra variables to AD + */ + void ExtraADPreaccIn() override {} + + /*! + * \brief LM transition model specific steps in the ComputeResidual method + * \param[in] config - Definition of the particular problem. + */ + void FinishResidualCalc(const CConfig* config) override { + const bool implicit = config->GetKind_TimeIntScheme() == EULER_IMPLICIT; + + /*--- Compute mean effective dynamic viscosity ---*/ + const su2double diff_i_gamma = Laminar_Viscosity_i + Eddy_Viscosity_i; + const su2double diff_j_gamma = Laminar_Viscosity_j + Eddy_Viscosity_j; + + const su2double diff_gamma = 0.5*(diff_i_gamma + diff_j_gamma); + + Flux[0] = diff_gamma*Proj_Mean_GradScalarVar[0]; + + /*--- For Jacobians -> Use of TSL (Thin Shear Layer) approx. to compute derivatives of the gradients ---*/ + if (implicit) { + const su2double proj_on_rho_i = proj_vector_ij/Density_i; + Jacobian_i[0][0] = -diff_gamma*proj_on_rho_i; + + const su2double proj_on_rho_j = proj_vector_ij/Density_j; + Jacobian_j[0][0] = diff_gamma*proj_on_rho_j; + } + } + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] correct_grad - Whether to correct gradient for skewness. + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_TransSLM(unsigned short val_nDim, unsigned short val_nVar, bool correct_grad, const CConfig* config) + : CAvgGrad_Scalar(val_nDim, val_nVar, correct_grad, config){ + } + +}; diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index de013fb1a671..bcce973c240c 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -92,7 +92,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. */ ResidualType<> ComputeResidual(const CConfig* config) override { - /*--- ScalarVar[0] = k, ScalarVar[0] = w, TransVar[0] = gamma, and TransVar[0] = ReThetaT ---*/ + /*--- ScalarVar[0] = k, ScalarVar[0] = w, TransVar[0] = gamma, and TransVar[1] = ReThetaT ---*/ /*--- dU/dx = PrimVar_Grad[1][0] ---*/ AD::StartPreacc(); AD::SetPreaccIn(StrainMag_i); @@ -323,3 +323,190 @@ class CSourcePieceWise_TransLM final : public CNumerics { return ResidualType<>(Residual, Jacobian_i, nullptr); } }; + + +/*! + * \class CSourcePieceWise_TranSLM + * \brief Class for integrating the source terms of the Simplified LM transition model equations. + * \ingroup SourceDiscr + * \author S. Kang. + */ +template +class CSourcePieceWise_TransSLM final : public CNumerics { + private: + const FlowIndices idx; /*!< \brief Object to manage the access to the flow primitives. */ + + const LM_ParsedOptions options; + + /*--- LM Closure constants ---*/ + const su2double c_e1 = 1.0; + const su2double c_a1 = 2.0; + const su2double c_e2 = 50.0; + const su2double c_a2 = 0.06; + const su2double sigmaf = 1.0; + const su2double s1 = 2.0; + const su2double c_theta = 0.03; + const su2double c_CF = 0.6; + const su2double sigmat = 2.0; + + TURB_FAMILY TurbFamily; + su2double hRoughness; + + su2double IntermittencySep = 1.0; + su2double IntermittencyEff = 1.0; + + su2double Re_t; + su2double Corr_Rec; + su2double AuxVar; + + su2double Residual; + su2double* Jacobian_i; + su2double Jacobian_Buffer; // Static storage for the Jacobian (which needs to be pointer for return type). + + TransLMCorrelations TransCorrelations; + + public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourcePieceWise_TransSLM(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) + : CNumerics(val_nDim, 1, config), idx(val_nDim, config->GetnSpecies()), options(config->GetLMParsedOptions()){ + /*--- "Allocate" the Jacobian using the static buffer. ---*/ + Jacobian_i = &Jacobian_Buffer; + + TurbFamily = TurbModelFamily(config->GetKind_Turb_Model()); + + hRoughness = config->GethRoughness(); + + TransCorrelations.SetOptions(options); + + } + + /*! + * \brief Residual for source term integration. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override { + /*--- ScalarVar[0] = k, ScalarVar[0] = w, TransVar[0] = gamma ---*/ + /*--- dU/dx = PrimVar_Grad[1][0] ---*/ + AD::StartPreacc(); + AD::SetPreaccIn(StrainMag_i); + AD::SetPreaccIn(ScalarVar_i, nVar); + AD::SetPreaccIn(ScalarVar_Grad_i, nVar, nDim); + AD::SetPreaccIn(TransVar_i, nVar); + AD::SetPreaccIn(TransVar_Grad_i, nVar, nDim); + AD::SetPreaccIn(Volume); + AD::SetPreaccIn(dist_i); + AD::SetPreaccIn(&V_i[idx.Velocity()], nDim); + AD::SetPreaccIn(PrimVar_Grad_i, nDim + idx.Velocity(), nDim); + AD::SetPreaccIn(Vorticity_i, 3); + + su2double VorticityMag = + sqrt(Vorticity_i[0] * Vorticity_i[0] + Vorticity_i[1] * Vorticity_i[1] + Vorticity_i[2] * Vorticity_i[2]); + + const su2double vel_u = V_i[idx.Velocity()]; + const su2double vel_v = V_i[1 + idx.Velocity()]; + const su2double vel_w = (nDim == 3) ? V_i[2 + idx.Velocity()] : 0.0; + + const su2double Velocity_Mag = sqrt(vel_u * vel_u + vel_v * vel_v + vel_w * vel_w); + + AD::SetPreaccIn(V_i[idx.Density()], V_i[idx.LaminarViscosity()], V_i[idx.EddyViscosity()]); + + Density_i = V_i[idx.Density()]; + Laminar_Viscosity_i = V_i[idx.LaminarViscosity()]; + Eddy_Viscosity_i = V_i[idx.EddyViscosity()]; + + Residual = 0.0; + Jacobian_i[0] = 0.0; + + if (dist_i > 1e-10) { + su2double Tu_L = 1.0; + if (TurbFamily == TURB_FAMILY::KW) Tu_L = max(min(100.0 * sqrt(2.0 * ScalarVar_i[0] / 3.0) / (ScalarVar_i[1]*dist_i), 100.0), 0.027); + if (TurbFamily == TURB_FAMILY::SA) Tu_L = config->GetTurbulenceIntensity_FreeStream() * 100; + + /*--- F_length ---*/ + su2double F_length = 100.0; + + /*--- F_onset ---*/ + su2double R_t = 1.0; + if (TurbFamily == TURB_FAMILY::KW) R_t = Density_i * ScalarVar_i[0] / Laminar_Viscosity_i / ScalarVar_i[1]; + if (TurbFamily == TURB_FAMILY::SA) R_t = Eddy_Viscosity_i / Laminar_Viscosity_i; + + /*-- Gradient of velocity magnitude ---*/ + + su2double dU_dx = 0.5 / Velocity_Mag * (2. * vel_u * PrimVar_Grad_i[1][0] + 2. * vel_v * PrimVar_Grad_i[2][0]); + if (nDim == 3) dU_dx += 0.5 / Velocity_Mag * (2. * vel_w * PrimVar_Grad_i[3][0]); + + su2double dU_dy = 0.5 / Velocity_Mag * (2. * vel_u * PrimVar_Grad_i[1][1] + 2. * vel_v * PrimVar_Grad_i[2][1]); + if (nDim == 3) dU_dy += 0.5 / Velocity_Mag * (2. * vel_w * PrimVar_Grad_i[3][1]); + + su2double dU_dz = 0.0; + if (nDim == 3) + dU_dz = + 0.5 / Velocity_Mag * + (2. * vel_u * PrimVar_Grad_i[1][2] + 2. * vel_v * PrimVar_Grad_i[2][2] + 2. * vel_w * PrimVar_Grad_i[3][2]); + + su2double du_ds = vel_u / Velocity_Mag * dU_dx + vel_v / Velocity_Mag * dU_dy; + if (nDim == 3) du_ds += vel_w / Velocity_Mag * dU_dz; + + /*--- Corr_RetC correlation*/ + //Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, du_ds, dist_i, Laminar_Viscosity_i, Density_i, VorticityMag, Velocity_Mag); + Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, AuxVar, dist_i, Laminar_Viscosity_i, Density_i, VorticityMag, Velocity_Mag); + + if (options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::CODER_SLM || options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM) { + // If these correlations are used, then the value of Corr_Rec has to be used instead of the TransVar[1] of the original LM model + F_length = TransCorrelations.FLength_Correlations(Tu_L, Re_t); + Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu_L, Re_t); + } + if (options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) Corr_Rec = Re_t; + + + const su2double Re_v = Density_i * dist_i * dist_i * StrainMag_i / Laminar_Viscosity_i; + const su2double F_onset1 = Re_v / (2.2 * Corr_Rec); + su2double F_onset2 = 1.0; + su2double F_onset3 = 1.0; + if (TurbFamily == TURB_FAMILY::KW) { + F_onset2 = min(F_onset1, 2.0); + F_onset3 = max(1.0 - pow(R_t / 3.5, 3.0), 0.0); + } + if (TurbFamily == TURB_FAMILY::SA) { + F_onset2 = min(max(F_onset1, pow(F_onset1, 4.0)), 4.0); + F_onset3 = max(2.0 - pow(R_t / 2.5, 3.0), 0.0); + } + const su2double F_onset = max(F_onset2 - F_onset3, 0.0); + + const su2double f_turb = exp(-pow(R_t / 4, 4)); + + /*-- production term of Intermeittency(Gamma) --*/ + const su2double Pg = + F_length * Density_i * StrainMag_i * F_onset * TransVar_i[0] * (1.0 - TransVar_i[0]); + + /*-- destruction term of Intermeittency(Gamma) --*/ + const su2double Dg = c_a2 * Density_i * VorticityMag * TransVar_i[0] * f_turb * (c_e2 * TransVar_i[0] - 1.0); + + /*--- Source ---*/ + Residual += (Pg - Dg) * Volume; + + /*--- Implicit part ---*/ + Jacobian_i[0] = (F_length * StrainMag_i * F_onset * (1 - 2*TransVar_i[0]) - + c_a2 * VorticityMag * f_turb * (2.0 * c_e2 * TransVar_i[0] - 1.0)) * + Volume; + + } + + AD::SetPreaccOut(Residual, nVar); + AD::EndPreacc(); + + return ResidualType<>(&Residual, &Jacobian_i, nullptr); + + } + + inline su2double GetRe_t() override {return Re_t;} + inline su2double GetCorr_Rec() override {return Corr_Rec;} + inline void SetAuxVar(su2double val_AuxVar) override { AuxVar = val_AuxVar;} + +}; diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index e11880bb41ed..810245a2b433 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -831,6 +831,16 @@ class CSourcePieceWise_TurbSST final : public CNumerics { /*--- LM model coupling with production and dissipation term for k transport equation---*/ if (config->GetKind_Trans_Model() == TURB_TRANS_MODEL::LM) { pk = pk * eff_intermittency; + // Check if the Prod_lim_k has to be introduced based on input options + if ((config->GetLMParsedOptions()).ProdLim) { + const su2double Re_theta_c_lim = 1100.0; + const su2double C_k = 1.0; + const su2double C_SEP = 1.0; + const su2double Re_v = Density_i * dist_i * dist_i * StrainMag_i / Laminar_Viscosity_i; + const su2double F_on_lim = min(max(Re_v/(2.2*Re_theta_c_lim)-1.0, 0.0), 3.0); + const su2double IntermittencyRelated = max(eff_intermittency-0.2, 0.0) * (1.0 - eff_intermittency); + pk = pk + 5*C_k * IntermittencyRelated * F_on_lim * max(3.0*C_SEP*Laminar_Viscosity_i - Eddy_Viscosity_i, 0.0) * StrainMag_i * VorticityMag; + } dk = min(max(eff_intermittency, 0.1), 1.0) * dk; } diff --git a/SU2_CFD/include/variables/CTransLMVariable.hpp b/SU2_CFD/include/variables/CTransLMVariable.hpp index c3893023d550..6c18eb03b59a 100644 --- a/SU2_CFD/include/variables/CTransLMVariable.hpp +++ b/SU2_CFD/include/variables/CTransLMVariable.hpp @@ -40,6 +40,8 @@ class CTransLMVariable final : public CTurbVariable { protected: VectorType Intermittency_Eff; VectorType Intermittency_Sep; + VectorType Corr_Rec; + VectorType Re_t; public: /*! @@ -55,6 +57,18 @@ class CTransLMVariable final : public CTurbVariable { */ CTransLMVariable(su2double Intermittency, su2double ReThetaT, su2double gammaSep, su2double gammaEff, unsigned long npoint, unsigned long ndim, unsigned long nvar, CConfig *config); + /*! + * \brief Constructor of the class. + * \param[in] Intermittency - intermittency(gamma) (initialization value). + * \param[in] gammaSep - separation intermittency(gamma) (initialization value). + * \param[in] gammaEff - effective intermittency(gamma) (initialization value). + * \param[in] npoint - Number of points/nodes/vertices in the domain. + * \param[in] ndim - Number of dimensions of the problem. + * \param[in] nvar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CTransLMVariable(su2double Intermittency, su2double gammaSep, su2double gammaEff, unsigned long npoint, unsigned long ndim, unsigned long nvar, CConfig *config); + /*! * \brief Destructor of the class. */ @@ -70,6 +84,16 @@ class CTransLMVariable final : public CTurbVariable { */ void SetIntermittencyEff(unsigned long iPoint, su2double val_Intermittency_sep) override; + /*! + * \brief Set Value of Transition Momentum Thickness Reynolds number from correlations. + */ + void SetCorr_Rec(unsigned long iPoint, su2double val_Corr_Rec) override; + + /*! + * \brief Set Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). + */ + void SetRe_t(unsigned long iPoint, su2double val_Re_t) override; + /*! * \brief Calculate effective intermittency. */ @@ -80,4 +104,13 @@ class CTransLMVariable final : public CTurbVariable { */ inline su2double GetIntermittencySep(unsigned long iPoint) const override { return Intermittency_Sep(iPoint); } + /*! + * \brief Get Value of Transition Momentum Thickness Reynolds number from correlations. + */ + inline su2double GetCorr_Rec(unsigned long iPoint) const override { return Corr_Rec(iPoint); } + + /*! + * \brief Get Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). + */ + inline su2double GetRe_t(unsigned long iPoint) const override { return Re_t(iPoint); } }; diff --git a/SU2_CFD/include/variables/CVariable.hpp b/SU2_CFD/include/variables/CVariable.hpp index 73ac61075d6c..099988e1a2b9 100644 --- a/SU2_CFD/include/variables/CVariable.hpp +++ b/SU2_CFD/include/variables/CVariable.hpp @@ -1713,6 +1713,26 @@ class CVariable { */ inline virtual void SetIntermittencyEff(unsigned long iPoint, su2double val_Intermittency_eff) {} + /*! + * \brief Set Value of Transition Momentum Thickness Reynolds number from correlations. + */ + inline virtual void SetCorr_Rec(unsigned long iPoint, su2double val_Corr_Rec) {}; + + /*! + * \brief Get Value of Transition Momentum Thickness Reynolds number from correlations. + */ + inline virtual su2double GetCorr_Rec(unsigned long iPoint) const { return 0.0; } + + /*! + * \brief Set Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). + */ + inline virtual void SetRe_t(unsigned long iPoint, su2double val_Re_t) {}; + + /*! + * \brief Get Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). + */ + inline virtual su2double GetRe_t(unsigned long iPoint) const { return 0.0; } + /*! * \brief Set the value of the eddy viscosity. * \param[in] val_muT diff --git a/SU2_CFD/src/drivers/CDriver.cpp b/SU2_CFD/src/drivers/CDriver.cpp index 0b2c5d94aab4..5c39743c64b6 100644 --- a/SU2_CFD/src/drivers/CDriver.cpp +++ b/SU2_CFD/src/drivers/CDriver.cpp @@ -1346,6 +1346,8 @@ void CDriver::InstantiateTransitionNumerics(unsigned short nVar_Trans, int offse const int visc_bound_term = VISC_BOUND_TERM + offset; const bool LM = config->GetKind_Trans_Model() == TURB_TRANS_MODEL::LM; + LM_ParsedOptions options; + if(LM) options = config->GetLMParsedOptions(); /*--- Definition of the convective scheme for each equation and mesh level ---*/ @@ -1355,7 +1357,10 @@ void CDriver::InstantiateTransitionNumerics(unsigned short nVar_Trans, int offse break; case SPACE_UPWIND : for (auto iMGlevel = 0u; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - if (LM) numerics[iMGlevel][TRANS_SOL][conv_term] = new CUpwSca_TransLM(nDim, nVar_Trans, config); + if (LM){ + if (!options.SLM) numerics[iMGlevel][TRANS_SOL][conv_term] = new CUpwSca_TransLM(nDim, nVar_Trans, config); + if (options.SLM) numerics[iMGlevel][TRANS_SOL][conv_term] = new CUpwSca_TransSLM(nDim, nVar_Trans, config); + } } break; default: @@ -1366,7 +1371,10 @@ void CDriver::InstantiateTransitionNumerics(unsigned short nVar_Trans, int offse /*--- Definition of the viscous scheme for each equation and mesh level ---*/ for (auto iMGlevel = 0u; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - if (LM) numerics[iMGlevel][TRANS_SOL][visc_term] = new CAvgGrad_TransLM(nDim, nVar_Trans, true, config); + if (LM){ + if (!options.SLM) numerics[iMGlevel][TRANS_SOL][visc_term] = new CAvgGrad_TransLM(nDim, nVar_Trans, true, config); + if (options.SLM) numerics[iMGlevel][TRANS_SOL][visc_term] = new CAvgGrad_TransSLM(nDim, nVar_Trans, true, config); + } } /*--- Definition of the source term integration scheme for each equation and mesh level ---*/ @@ -1374,17 +1382,25 @@ void CDriver::InstantiateTransitionNumerics(unsigned short nVar_Trans, int offse for (auto iMGlevel = 0u; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { auto& trans_source_first_term = numerics[iMGlevel][TRANS_SOL][source_first_term]; - if (LM) trans_source_first_term = new CSourcePieceWise_TransLM(nDim, nVar_Trans, config); - + if (LM){ + if (!options.SLM) trans_source_first_term = new CSourcePieceWise_TransLM(nDim, nVar_Trans, config); + if (options.SLM) trans_source_first_term = new CSourcePieceWise_TransSLM(nDim, nVar_Trans, config); + } numerics[iMGlevel][TRANS_SOL][source_second_term] = new CSourceNothing(nDim, nVar_Trans, config); } /*--- Definition of the boundary condition method ---*/ for (auto iMGlevel = 0u; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - if (LM) { - numerics[iMGlevel][TRANS_SOL][conv_bound_term] = new CUpwSca_TransLM(nDim, nVar_Trans, config); - numerics[iMGlevel][TRANS_SOL][visc_bound_term] = new CAvgGrad_TransLM(nDim, nVar_Trans, false, config); + if (LM) { + if (!options.SLM) { + numerics[iMGlevel][TRANS_SOL][conv_bound_term] = new CUpwSca_TransLM(nDim, nVar_Trans, config); + numerics[iMGlevel][TRANS_SOL][visc_bound_term] = new CAvgGrad_TransLM(nDim, nVar_Trans, false, config); + } else { + numerics[iMGlevel][TRANS_SOL][conv_bound_term] = new CUpwSca_TransSLM(nDim, nVar_Trans, config); + numerics[iMGlevel][TRANS_SOL][visc_bound_term] = new CAvgGrad_TransSLM(nDim, nVar_Trans, false, config); + } + } } } diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index cb88b9f9f265..00236d8e588a 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -873,8 +873,10 @@ void CFlowOutput::AddHistoryOutputFields_ScalarRMS_RES(const CConfig* config) { case TURB_TRANS_MODEL::LM: /// DESCRIPTION: Root-mean square residual of the intermittency (LM model). AddHistoryOutput("RMS_INTERMITTENCY", "rms[LM_1]", ScreenOutputFormat::FIXED, "RMS_RES", "Root-mean square residual of intermittency (LM model).", HistoryFieldType::RESIDUAL); - /// DESCRIPTION: Root-mean square residual of the momentum thickness Reynolds number (LM model). - AddHistoryOutput("RMS_RE_THETA_T", "rms[LM_2]", ScreenOutputFormat::FIXED, "RMS_RES", "Root-mean square residual of momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + if (!(config->GetLMParsedOptions()).SLM) { + /// DESCRIPTION: Root-mean square residual of the momentum thickness Reynolds number (LM model). + AddHistoryOutput("RMS_RE_THETA_T", "rms[LM_2]", ScreenOutputFormat::FIXED, "RMS_RES", "Root-mean square residual of momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + } break; case TURB_TRANS_MODEL::NONE: break; @@ -910,8 +912,10 @@ void CFlowOutput::AddHistoryOutputFields_ScalarMAX_RES(const CConfig* config) { case TURB_TRANS_MODEL::LM: /// DESCRIPTION: Maximum residual of the intermittency (LM model). AddHistoryOutput("MAX_INTERMITTENCY", "max[LM_1]", ScreenOutputFormat::FIXED, "MAX_RES", "Maximum residual of the intermittency (LM model).", HistoryFieldType::RESIDUAL); - /// DESCRIPTION: Maximum residual of the momentum thickness Reynolds number (LM model). - AddHistoryOutput("MAX_RE_THETA_T", "max[LM_2]", ScreenOutputFormat::FIXED, "MAX_RES", "Maximum residual of the momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + if (!(config->GetLMParsedOptions()).SLM) { + /// DESCRIPTION: Maximum residual of the momentum thickness Reynolds number (LM model). + AddHistoryOutput("MAX_RE_THETA_T", "max[LM_2]", ScreenOutputFormat::FIXED, "MAX_RES", "Maximum residual of the momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + } break; case TURB_TRANS_MODEL::NONE: @@ -948,8 +952,10 @@ void CFlowOutput::AddHistoryOutputFields_ScalarBGS_RES(const CConfig* config) { case TURB_TRANS_MODEL::LM: /// DESCRIPTION: Maximum residual of the intermittency (LM model). AddHistoryOutput("BGS_INTERMITTENCY", "bgs[LM_1]", ScreenOutputFormat::FIXED, "BGS_RES", "BGS residual of the intermittency (LM model).", HistoryFieldType::RESIDUAL); - /// DESCRIPTION: Maximum residual of the momentum thickness Reynolds number (LM model). - AddHistoryOutput("BGS_RE_THETA_T", "bgs[LM_2]", ScreenOutputFormat::FIXED, "BGS_RES", "BGS residual of the momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + if (!(config->GetLMParsedOptions()).SLM) { + /// DESCRIPTION: Maximum residual of the momentum thickness Reynolds number (LM model). + AddHistoryOutput("BGS_RE_THETA_T", "bgs[LM_2]", ScreenOutputFormat::FIXED, "BGS_RES", "BGS residual of the momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + } break; case TURB_TRANS_MODEL::NONE: break; @@ -1012,12 +1018,16 @@ void CFlowOutput::LoadHistoryData_Scalar(const CConfig* config, const CSolver* c switch (config->GetKind_Trans_Model()) { case TURB_TRANS_MODEL::LM: SetHistoryOutputValue("RMS_INTERMITTENCY", log10(solver[TRANS_SOL]->GetRes_RMS(0))); - SetHistoryOutputValue("RMS_RE_THETA_T",log10(solver[TRANS_SOL]->GetRes_RMS(1))); SetHistoryOutputValue("MAX_INTERMITTENCY", log10(solver[TRANS_SOL]->GetRes_Max(0))); - SetHistoryOutputValue("MAX_RE_THETA_T", log10(solver[TRANS_SOL]->GetRes_Max(1))); + if (!(config->GetLMParsedOptions()).SLM) { + SetHistoryOutputValue("RMS_RE_THETA_T",log10(solver[TRANS_SOL]->GetRes_RMS(1))); + SetHistoryOutputValue("MAX_RE_THETA_T", log10(solver[TRANS_SOL]->GetRes_Max(1))); + } if (multiZone) { SetHistoryOutputValue("BGS_INTERMITTENCY", log10(solver[TRANS_SOL]->GetRes_BGS(0))); - SetHistoryOutputValue("BGS_RE_THETA_T", log10(solver[TRANS_SOL]->GetRes_BGS(1))); + if (!(config->GetLMParsedOptions()).SLM) { + SetHistoryOutputValue("BGS_RE_THETA_T", log10(solver[TRANS_SOL]->GetRes_BGS(1))); + } } SetHistoryOutputValue("LINSOL_ITER_TRANS", solver[TRANS_SOL]->GetIterLinSolver()); SetHistoryOutputValue("LINSOL_RESIDUAL_TRANS", log10(solver[TRANS_SOL]->GetResLinSolver())); @@ -1059,6 +1069,9 @@ void CFlowOutput::SetVolumeOutputFields_ScalarSolution(const CConfig* config){ case TURB_TRANS_MODEL::LM: AddVolumeOutput("INTERMITTENCY", "LM_gamma", "SOLUTION", "LM intermittency"); AddVolumeOutput("RE_THETA_T", "LM_Re_t", "SOLUTION", "LM RE_THETA_T"); + if ((config->GetLMParsedOptions()).SLM) { + AddVolumeOutput("RE_THETA_CORR", "LM_Corr_Rec", "SOLUTION", "LM RE_THETA_CORR"); + } AddVolumeOutput("INTERMITTENCY_SEP", "LM_gamma_sep", "PRIMITIVE", "LM intermittency"); AddVolumeOutput("INTERMITTENCY_EFF", "LM_gamma_eff", "PRIMITIVE", "LM RE_THETA_T"); AddVolumeOutput("TURB_INDEX", "Turb_index", "PRIMITIVE", "Turbulence index"); @@ -1092,7 +1105,9 @@ void CFlowOutput::SetVolumeOutputFields_ScalarResidual(const CConfig* config) { switch (config->GetKind_Trans_Model()) { case TURB_TRANS_MODEL::LM: AddVolumeOutput("RES_INTERMITTENCY", "Residual_LM_intermittency", "RESIDUAL", "Residual of LM intermittency"); - AddVolumeOutput("RES_RE_THETA_T", "Residual_LM_RE_THETA_T", "RESIDUAL", "Residual of LM RE_THETA_T"); + if (!(config->GetLMParsedOptions()).SLM) { + AddVolumeOutput("RES_RE_THETA_T", "Residual_LM_RE_THETA_T", "RESIDUAL", "Residual of LM RE_THETA_T"); + } break; case TURB_TRANS_MODEL::NONE: @@ -1212,12 +1227,19 @@ void CFlowOutput::LoadVolumeData_Scalar(const CConfig* config, const CSolver* co switch (config->GetKind_Trans_Model()) { case TURB_TRANS_MODEL::LM: SetVolumeOutputValue("INTERMITTENCY", iPoint, Node_Trans->GetSolution(iPoint, 0)); - SetVolumeOutputValue("RE_THETA_T", iPoint, Node_Trans->GetSolution(iPoint, 1)); + if (!(config->GetLMParsedOptions()).SLM) { + SetVolumeOutputValue("RE_THETA_T", iPoint, Node_Trans->GetSolution(iPoint, 1)); + } else { + SetVolumeOutputValue("RE_THETA_T", iPoint, Node_Trans->GetRe_t(iPoint)); + SetVolumeOutputValue("RE_THETA_CORR", iPoint, Node_Trans->GetCorr_Rec(iPoint)); + } SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); SetVolumeOutputValue("TURB_INDEX", iPoint, Node_Turb->GetTurbIndex(iPoint)); SetVolumeOutputValue("RES_INTERMITTENCY", iPoint, trans_solver->LinSysRes(iPoint, 0)); - SetVolumeOutputValue("RES_RE_THETA_T", iPoint, trans_solver->LinSysRes(iPoint, 1)); + if (!(config->GetLMParsedOptions()).SLM) { + SetVolumeOutputValue("RES_RE_THETA_T", iPoint, trans_solver->LinSysRes(iPoint, 1)); + } break; case TURB_TRANS_MODEL::NONE: break; diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 0ceb3d86992f..8e06e2961544 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -49,6 +49,14 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh /*--- Dimension of the problem --> 2 Transport equations (intermittency, Reth) ---*/ nVar = 2; nPrimVar = 2; + + /*--- Check if Simplified version is used ---*/ + options = config->GetLMParsedOptions(); + if (options.SLM) { + nVar = 1; + nPrimVar = 1; + } + nPoint = geometry->GetnPoint(); nPointDomain = geometry->GetnPointDomain(); @@ -61,16 +69,9 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh nDim = geometry->GetnDim(); /*--- Define variables needed for transition from config file ---*/ - options = config->GetLMParsedOptions(); TransCorrelations.SetOptions(options); TurbFamily = TurbModelFamily(config->GetKind_Turb_Model()); - /*--- Check if Simplified version is used ---*/ - if (options.SLM) { - nVar = 1; - nPrimVar = 1; - } - /*--- Single grid simulation ---*/ if (iMesh == MESH_0) { @@ -121,7 +122,8 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh su2double ReThetaT_Inf = 0.0; if (!options.SLM) { - su2double ReThetaT_Inf = 100.0; + + ReThetaT_Inf = 100.0; /*--- Momentum thickness Reynolds number, initialized from freestream turbulent intensity*/ if (Intensity <= 1.3) { @@ -140,7 +142,10 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh } /*--- Initialize the solution to the far-field state everywhere. ---*/ - nodes = new CTransLMVariable(Intermittency_Inf, ReThetaT_Inf, 1.0, 1.0, nPoint, nDim, nVar, config); + nodes = new CTransLMVariable(Intermittency_Inf, 1.0, 1.0, nPoint, nDim, nVar, config); + if (!options.SLM) { + nodes = new CTransLMVariable(Intermittency_Inf, ReThetaT_Inf, 1.0, 1.0, nPoint, nDim, nVar, config); + } SetBaseClassPointerToNodes(); @@ -169,7 +174,7 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh Inlet_TurbVars[iMarker].resize(nVertex[iMarker],nVar); for (unsigned long iVertex = 0; iVertex < nVertex[iMarker]; ++iVertex) { Inlet_TurbVars[iMarker](iVertex,0) = Intermittency_Inf; - Inlet_TurbVars[iMarker](iVertex,1) = ReThetaT_Inf; + if (!options.SLM) Inlet_TurbVars[iMarker](iVertex,1) = ReThetaT_Inf; } } @@ -192,6 +197,70 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain /*--- Upwind second order reconstruction and gradients ---*/ CommonPreprocessing(geometry, config, Output); + + + ///////////////////// + // ATTENZIONE! Forse devo farlo solamente per i punti che sono nello strato limite! Quindi magari nelle sources devo usare la function che mi definisce lo strato limite! + // Al di fuori di essa devo usare la solita du/ds? Perchè altrimenti il contorno più vicino ad un certo punto diventa il farfield, e non ha senso! + // UPDATE: Mi sa che la wall distance è rispetto alla parete, quindi effettivamente l'elemento più vicino è sempre a parete. + ///////////////////// + + cout << "Sono qui" << endl; + //if (rank == MASTER_NODE) { + if (options.SLM) { + /*--- Reconstructon of auxiliary variables gradient ---*/ + su2double Normal[nPoint][nDim]; + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + for (auto iDim = 0u; iDim < nDim; iDim++) + Normal[iPoint][iDim] = 0.0; + + // Extract nearest wall element and wall marker + unsigned long NearestWallElement = geometry->nodes->GetClosestWall_Elem(iPoint); + unsigned short NearestWallMarker = geometry->nodes->GetClosestWall_Marker(iPoint); + + // Cycle on all of the points of the wall element + for (unsigned short iNode = 0; iNode < geometry->bound[NearestWallMarker][NearestWallElement]->GetnNodes(); iNode++) { + // Extract global coordinate of the node + unsigned long iPointHere = geometry->bound[NearestWallMarker][NearestWallElement]->GetNode(iNode); + long iVertexHere = geometry->nodes->GetVertex(iPointHere, NearestWallMarker); + for (auto iDim = 0u; iDim < nDim; iDim++) + Normal[iPoint][iDim] += geometry->vertex[NearestWallMarker][iVertexHere]->GetNormal(iDim); + } + for (auto iDim = 0u; iDim < nDim; iDim++) + Normal[iPoint][iDim] /= geometry->bound[NearestWallMarker][NearestWallElement]->GetnNodes(); + + nodes->SetAuxVar(iPoint, 0, nodes->GetProjVel(iPoint, Normal[iPoint])); + } + END_SU2_OMP_FOR + + //SU2_OMP_BARRIER + + cout << "primo for" << endl; + + if (config->GetKind_Gradient_Method() == GREEN_GAUSS) { + SetAuxVar_Gradient_GG(geometry, config); + } + if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) { + SetAuxVar_Gradient_LS(geometry, config); + } + + //SU2_OMP_BARRIER + + cout << "Dopo Gradienti" << endl; + + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + su2double AuxVarHere = 0.0; + for (auto iDim = 0u; iDim < nDim; iDim++) + AuxVarHere += Normal[iPoint][iDim] * nodes->GetAuxVarGradient(iPoint, 0, iDim); + nodes->SetAuxVar(iPoint, 0, AuxVarHere); + } + END_SU2_OMP_FOR + + cout << "Ho finito" << endl; + } + } void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh) { @@ -223,7 +292,6 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai VorticityMag = max(VorticityMag, 1e-12); StrainMag = max(StrainMag, 1e-12); // safety against division by zero const su2double Intermittency = nodes->GetSolution(iPoint,0); - const su2double Re_t = nodes->GetSolution(iPoint,1); const su2double Re_v = rho*dist*dist*StrainMag/mu; const su2double vel_u = flowNodes->GetVelocity(iPoint, 0); const su2double vel_v = flowNodes->GetVelocity(iPoint, 1); @@ -231,17 +299,28 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai const su2double VelocityMag = sqrt(vel_u*vel_u + vel_v*vel_v + vel_w*vel_w); su2double omega = 0.0; su2double k = 0.0; - if(TurbFamily == TURB_FAMILY::KW){ - omega = turbNodes->GetSolution(iPoint,1); - k = turbNodes->GetSolution(iPoint,0); + + su2double Corr_Rec = 0.0; + su2double Re_t = 0.0; + if (!options.SLM) { + Re_t = nodes->GetSolution(iPoint,1); + if(TurbFamily == TURB_FAMILY::KW){ + omega = turbNodes->GetSolution(iPoint,1); + k = turbNodes->GetSolution(iPoint,0); + } + su2double Tu = 1.0; + if(TurbFamily == TURB_FAMILY::KW) + Tu = max(100.0*sqrt( 2.0 * k / 3.0 ) / VelocityMag,0.027); + if(TurbFamily == TURB_FAMILY::SA) + Tu = config->GetTurbulenceIntensity_FreeStream()*100; + + Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, Re_t); } - su2double Tu = 1.0; - if(TurbFamily == TURB_FAMILY::KW) - Tu = max(100.0*sqrt( 2.0 * k / 3.0 ) / VelocityMag,0.027); - if(TurbFamily == TURB_FAMILY::SA) - Tu = config->GetTurbulenceIntensity_FreeStream()*100; - const su2double Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, Re_t); + if (options.SLM) { + Re_t = nodes->GetRe_t(iPoint); + Corr_Rec = nodes->GetCorr_Rec(iPoint); + } su2double R_t = 1.0; if(TurbFamily == TURB_FAMILY::KW) @@ -352,10 +431,19 @@ void CTransLMSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta numerics->SetLocalGridLength(geometry->nodes->GetMaxLength(iPoint)); } + if(options.SLM) { + numerics->SetAuxVar(nodes->GetAuxVar(iPoint, 0)); + } + /*--- Compute the source term ---*/ auto residual = numerics->ComputeResidual(config); + if(options.SLM) { + nodes->SetRe_t(iPoint, numerics->GetRe_t()); + nodes->SetCorr_Rec(iPoint, numerics->GetCorr_Rec()); + } + /*--- Subtract residual and the Jacobian ---*/ LinSysRes.SubtractBlock(iPoint, residual); @@ -554,6 +642,7 @@ void CTransLMSolver::LoadRestart(CGeometry** geometry, CSolver*** solver, CConfi const auto index = counter * Restart_Vars[1] + skipVars; for (auto iVar = 0u; iVar < nVar; iVar++) nodes->SetSolution(iPoint_Local, iVar, Restart_Data[index + iVar]); + // I am really not sure about these, I have to check if they are actually saved nodes ->SetIntermittencySep(iPoint_Local, Restart_Data[index + 2]); nodes ->SetIntermittencyEff(iPoint_Local, Restart_Data[index + 3]); diff --git a/SU2_CFD/src/variables/CTransLMVariable.cpp b/SU2_CFD/src/variables/CTransLMVariable.cpp index ce73c451942b..1e7d09f75da1 100644 --- a/SU2_CFD/src/variables/CTransLMVariable.cpp +++ b/SU2_CFD/src/variables/CTransLMVariable.cpp @@ -36,8 +36,7 @@ CTransLMVariable::CTransLMVariable(su2double Intermittency, su2double ReThetaT, for(unsigned long iPoint=0; iPointGetLMParsedOptions(); + + for(unsigned long iPoint=0; iPoint Date: Tue, 31 Jan 2023 19:57:24 +0100 Subject: [PATCH 05/61] - Added Cross flow effects for SLM - Modified LM_OPTIONS to include cross-flow effects: from LM2015 to CROSSFLOW --- Common/include/option_structure.hpp | 8 +- Common/src/CConfig.cpp | 11 +- .../transition/trans_correlations.hpp | 5 +- .../turbulent/transition/trans_sources.hpp | 69 +++++++++-- SU2_CFD/src/output/CFlowOutput.cpp | 2 +- SU2_CFD/src/solvers/CTransLMSolver.cpp | 112 +++++++++--------- config_template.cfg | 2 +- 7 files changed, 132 insertions(+), 77 deletions(-) diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp index 63f2676ffdec..f927d5b30d05 100644 --- a/Common/include/option_structure.hpp +++ b/Common/include/option_structure.hpp @@ -1173,7 +1173,7 @@ static const MapType Trans_Model_Map = { */ enum class LM_OPTIONS { NONE, /*!< \brief No option / default. */ - LM2015, /*!< \brief Cross-flow corrections. */ + CROSSFLOW, /*!< \brief Cross-flow corrections. */ SLM, /*!< \brief Simplified version. */ PRODLIM, /*!< \brief Add production term to Pk. */ MALAN, /*!< \brief Kind of transition correlation model (Malan). */ @@ -1191,7 +1191,7 @@ enum class LM_OPTIONS { static const MapType LM_Options_Map = { MakePair("NONE", LM_OPTIONS::NONE) - MakePair("LM2015", LM_OPTIONS::LM2015) + MakePair("CROSSFLOW", LM_OPTIONS::CROSSFLOW) MakePair("SLM", LM_OPTIONS::SLM) MakePair("PRODLIM", LM_OPTIONS::PRODLIM) MakePair("MALAN", LM_OPTIONS::MALAN) @@ -1235,7 +1235,7 @@ enum class TURB_TRANS_CORRELATION_SLM { */ struct LM_ParsedOptions { LM_OPTIONS version = LM_OPTIONS::NONE; /*!< \brief LM base model. */ - bool LM2015 = false; /*!< \brief Use cross-flow corrections. */ + bool CrossFlow = false; /*!< \brief Use cross-flow corrections. */ bool SLM = false; /*!< \brief Use simplified version. */ bool ProdLim = false; /*!< \brief Add production term to Pk. */ TURB_TRANS_CORRELATION Correlation = TURB_TRANS_CORRELATION::DEFAULT; @@ -1257,7 +1257,7 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh return std::find(LM_Options, lm_options_end, option) != lm_options_end; }; - LMParsedOptions.LM2015 = IsPresent(LM_OPTIONS::LM2015); + LMParsedOptions.CrossFlow = IsPresent(LM_OPTIONS::CROSSFLOW); LMParsedOptions.SLM = IsPresent(LM_OPTIONS::SLM); LMParsedOptions.ProdLim = IsPresent(LM_OPTIONS::PRODLIM); diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 04ce1bc67349..ca78af64e6e5 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -3471,9 +3471,9 @@ void CConfig::SetPostprocessing(SU2_COMPONENT val_software, unsigned short val_i if (Kind_Trans_Model == TURB_TRANS_MODEL::LM) { lmParsedOptions = ParseLMOptions(LM_Options, nLM_Options, rank, Kind_Turb_Model); - /*--- Check if problem is 2D and LM2015 has been selected ---*/ - if (lmParsedOptions.LM2015 && val_nDim == 2) { - SU2_MPI::Error("LM2015 is available only for 3D problems", CURRENT_FUNCTION); + /*--- Check if problem is 2D and CrossFlow has been selected ---*/ + if (lmParsedOptions.CrossFlow && val_nDim == 2) { + SU2_MPI::Error("Cross-flow corrections are available only for 3D problems", CURRENT_FUNCTION); } } @@ -6117,6 +6117,7 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { switch (Kind_Turb_Model) { case TURB_MODEL::SA: NTurbEqs = 1; break; case TURB_MODEL::SST: NTurbEqs = 2; break; + case TURB_MODEL::NONE: SU2_MPI::Error("No turbulence model has been selected but LM transition model is active.", CURRENT_FUNCTION); break; } if (!lmParsedOptions.SLM) { int NEquations = 2; @@ -6125,8 +6126,8 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { int NEquations = 1; cout << "Transition model: Simplified Langtry and Menter's "<< NEquations+NTurbEqs <<" equation model"; } - if (lmParsedOptions.LM2015) { - cout << " w/ cross-flow corrections (2015)" << endl; + if (lmParsedOptions.CrossFlow) { + cout << " w/ cross-flow corrections" << endl; } else { if (!lmParsedOptions.SLM) { cout << " (2009)" << endl; diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp index a4f9f663fbd3..ecd569984ed8 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp @@ -197,7 +197,7 @@ class TransLMCorrelations { * \param[in] du_ds - Streamwise velocity gradient. * \param[out] rethetac - Corrected value for Re_theta. */ - su2double ReThetaC_Correlations_SLM(const su2double Tu_L, const su2double du_ds, const su2double wall_dist, const su2double Laminar_Viscosity, const su2double Density, const su2double VorticityMag, const su2double VelocityMag) const { + su2double ReThetaC_Correlations_SLM(const su2double Tu_L, const su2double lambda_theta, const su2double wall_dist, const su2double VorticityMag, const su2double VelocityMag) const { su2double rethetac = 0.0; @@ -205,7 +205,8 @@ class TransLMCorrelations { case TURB_TRANS_CORRELATION_SLM::MENTER_SLM: { /*-- Thwaites parameter ---*/ - su2double lambda_theta_local = 7.57e-3 * du_ds * wall_dist * wall_dist * Density / Laminar_Viscosity + 0.0128; + // su2double lambda_theta_local = 7.57e-3 * du_ds * wall_dist * wall_dist * Density / Laminar_Viscosity + 0.0128; + su2double lambda_theta_local = lambda_theta; lambda_theta_local = min(max(lambda_theta_local, -1.0), 1.0); /*-- Function to sensitize the transition onset to the streamwise pressure gradient ---*/ diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index bcce973c240c..1bdc5c959cc9 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -186,7 +186,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { /*-- Calculate blending function f_theta --*/ su2double time_scale = 500.0 * Laminar_Viscosity_i / Density_i / Velocity_Mag / Velocity_Mag; - if (options.LM2015) + if (options.CrossFlow) time_scale = min(time_scale, Density_i * LocalGridLength_i * LocalGridLength_i / (Laminar_Viscosity_i + Eddy_Viscosity_i)); const su2double theta_bl = TransVar_i[1] * Laminar_Viscosity_i / Density_i / Velocity_Mag; @@ -206,7 +206,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { const su2double f_turb = exp(-pow(R_t / 4, 4)); su2double f_theta_2 = 0.0; - if (options.LM2015) + if (options.CrossFlow) f_theta_2 = min(f_wake * exp(-pow(dist_i / delta, 4.0)), 1.0); /*--- Corr_Ret correlation*/ @@ -247,7 +247,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { /*-- Corr_RetT_SCF Correlations--*/ su2double ReThetat_SCF = 0.0; - if (options.LM2015) { + if (options.CrossFlow) { su2double VelocityNormalized[3]; VelocityNormalized[0] = vel_u / Velocity_Mag; VelocityNormalized[1] = vel_v / Velocity_Mag; @@ -298,7 +298,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { /*-- destruction term of ReThetaT --*/ // It should not be with the minus sign but I put for consistency su2double DRethetat = 0.0; - if (options.LM2015) + if (options.CrossFlow) DRethetat = -c_theta * (Density_i / time_scale) * c_CF * min(ReThetat_SCF - TransVar_i[1], 0.0) * f_theta_2; /*--- Source ---*/ @@ -313,7 +313,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { Jacobian_i[0][1] = 0.0; Jacobian_i[1][0] = 0.0; Jacobian_i[1][1] = -c_theta / time_scale * (1.0 - f_theta) * Volume; - if (options.LM2015 && ReThetat_SCF - TransVar_i[1] < 0) + if (options.CrossFlow && ReThetat_SCF - TransVar_i[1] < 0) Jacobian_i[1][1] += (c_theta / time_scale) * c_CF * f_theta_2 * Volume; } @@ -453,9 +453,12 @@ class CSourcePieceWise_TransSLM final : public CNumerics { su2double du_ds = vel_u / Velocity_Mag * dU_dx + vel_v / Velocity_Mag * dU_dy; if (nDim == 3) du_ds += vel_w / Velocity_Mag * dU_dz; + const su2double lambda_theta = 7.57e-3 * du_ds * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128; + // const su2double lambda_theta = 7.57e-3 * AuxVar * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128; + /*--- Corr_RetC correlation*/ - //Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, du_ds, dist_i, Laminar_Viscosity_i, Density_i, VorticityMag, Velocity_Mag); - Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, AuxVar, dist_i, Laminar_Viscosity_i, Density_i, VorticityMag, Velocity_Mag); + Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, lambda_theta, dist_i, VorticityMag, Velocity_Mag); + // Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, lambda_theta, dist_i, VorticityMag, Velocity_Mag); if (options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::CODER_SLM || options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM) { // If these correlations are used, then the value of Corr_Rec has to be used instead of the TransVar[1] of the original LM model @@ -477,7 +480,57 @@ class CSourcePieceWise_TransSLM final : public CNumerics { F_onset2 = min(max(F_onset1, pow(F_onset1, 4.0)), 4.0); F_onset3 = max(2.0 - pow(R_t / 2.5, 3.0), 0.0); } - const su2double F_onset = max(F_onset2 - F_onset3, 0.0); + su2double F_onset = max(F_onset2 - F_onset3, 0.0); + + if (options.CrossFlow) { + + // Computation of shape factor + const su2double k = 0.25 - lambda_theta; + const su2double FirstTerm = 4.14 * k; + const su2double SecondTerm = 83.5 * pow(k, 2.0); + const su2double ThirdTerm = 854 * pow(k, 3.0); + const su2double ForthTerm = 3337 * pow(k, 4.0); + const su2double FifthTerm = 4576 * pow(k, 5.0); + const su2double H = min(2.0 + FirstTerm - SecondTerm + ThirdTerm - ForthTerm + FifthTerm, 2.7); + + // Computation of critical cross flow Reynolds number + su2double Re_Crit_CF = 0.0; + if(H < 2.3) { + Re_Crit_CF = 150.0; + } else { + Re_Crit_CF = -(300.0/PI_NUMBER) * atan(0.106/(pow(H-2.3, 2.05))); + } + + // Helicity computation + su2double VelocityNormalized[3]; + VelocityNormalized[0] = vel_u / Velocity_Mag; + VelocityNormalized[1] = vel_v / Velocity_Mag; + if (nDim == 3) VelocityNormalized[2] = vel_w / Velocity_Mag; + + su2double StreamwiseVort = 0.0; + for (auto iDim = 0u; iDim < nDim; iDim++) { + StreamwiseVort += VelocityNormalized[iDim] * Vorticity_i[iDim]; + } + StreamwiseVort = abs(StreamwiseVort); + + const su2double H_CF = StreamwiseVort * dist_i / Velocity_Mag; + + // Computation of Delta_H_CF. Here I have included directly R_t as the ration between turb and lam viscosity + const su2double Delta_H_CF = H_CF * (1.0 + min(R_t, 0.4)); + + // Take into account for roughness + const su2double h_0 = 0.25e-6; + const su2double C_r = 2.0 - pow(0.5, config->GethRoughness()/h_0); + + // Construct Cross flow activation function + const su2double C_CF = 1.0; + const su2double f_CF = (C_CF * C_r * Delta_H_CF * Corr_Rec) / Re_Crit_CF; + const su2double F_onset_CF = min(max(0.0, f_CF - 1.0), 1.0); + + // Adjust onset function for intermittency + F_onset = max(F_onset, F_onset_CF); + + } const su2double f_turb = exp(-pow(R_t / 4, 4)); diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index 00236d8e588a..1c0d1e8f39a1 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -2295,7 +2295,7 @@ void CFlowOutput::WriteForcesBreakdown(const CConfig* config, const CSolver* flo case TURB_TRANS_MODEL::NONE: break; case TURB_TRANS_MODEL::LM: file << "Langtry and Menter's transition"; - if (config->GetLMParsedOptions().LM2015) { + if (config->GetLMParsedOptions().CrossFlow) { file << " w/ cross-flow corrections (2015)\n"; } else { file << " (2009)\n"; diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 8e06e2961544..505cac4f7139 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -205,61 +205,61 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain // UPDATE: Mi sa che la wall distance è rispetto alla parete, quindi effettivamente l'elemento più vicino è sempre a parete. ///////////////////// - cout << "Sono qui" << endl; + // cout << "Sono qui" << endl; //if (rank == MASTER_NODE) { - if (options.SLM) { - /*--- Reconstructon of auxiliary variables gradient ---*/ - su2double Normal[nPoint][nDim]; - SU2_OMP_FOR_STAT(omp_chunk_size) - for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { - for (auto iDim = 0u; iDim < nDim; iDim++) - Normal[iPoint][iDim] = 0.0; - - // Extract nearest wall element and wall marker - unsigned long NearestWallElement = geometry->nodes->GetClosestWall_Elem(iPoint); - unsigned short NearestWallMarker = geometry->nodes->GetClosestWall_Marker(iPoint); - - // Cycle on all of the points of the wall element - for (unsigned short iNode = 0; iNode < geometry->bound[NearestWallMarker][NearestWallElement]->GetnNodes(); iNode++) { - // Extract global coordinate of the node - unsigned long iPointHere = geometry->bound[NearestWallMarker][NearestWallElement]->GetNode(iNode); - long iVertexHere = geometry->nodes->GetVertex(iPointHere, NearestWallMarker); - for (auto iDim = 0u; iDim < nDim; iDim++) - Normal[iPoint][iDim] += geometry->vertex[NearestWallMarker][iVertexHere]->GetNormal(iDim); - } - for (auto iDim = 0u; iDim < nDim; iDim++) - Normal[iPoint][iDim] /= geometry->bound[NearestWallMarker][NearestWallElement]->GetnNodes(); - - nodes->SetAuxVar(iPoint, 0, nodes->GetProjVel(iPoint, Normal[iPoint])); - } - END_SU2_OMP_FOR - - //SU2_OMP_BARRIER - - cout << "primo for" << endl; - - if (config->GetKind_Gradient_Method() == GREEN_GAUSS) { - SetAuxVar_Gradient_GG(geometry, config); - } - if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) { - SetAuxVar_Gradient_LS(geometry, config); - } - - //SU2_OMP_BARRIER - - cout << "Dopo Gradienti" << endl; - - SU2_OMP_FOR_STAT(omp_chunk_size) - for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { - su2double AuxVarHere = 0.0; - for (auto iDim = 0u; iDim < nDim; iDim++) - AuxVarHere += Normal[iPoint][iDim] * nodes->GetAuxVarGradient(iPoint, 0, iDim); - nodes->SetAuxVar(iPoint, 0, AuxVarHere); - } - END_SU2_OMP_FOR - - cout << "Ho finito" << endl; - } + // if (options.SLM) { + // /*--- Reconstructon of auxiliary variables gradient ---*/ + // su2double Normal[nPoint][nDim]; + // SU2_OMP_FOR_STAT(omp_chunk_size) + // for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + // for (auto iDim = 0u; iDim < nDim; iDim++) + // Normal[iPoint][iDim] = 0.0; + + // // Extract nearest wall element and wall marker + // unsigned long NearestWallElement = geometry->nodes->GetClosestWall_Elem(iPoint); + // unsigned short NearestWallMarker = geometry->nodes->GetClosestWall_Marker(iPoint); + + // // Cycle on all of the points of the wall element + // for (unsigned short iNode = 0; iNode < geometry->bound[NearestWallMarker][NearestWallElement]->GetnNodes(); iNode++) { + // // Extract global coordinate of the node + // unsigned long iPointHere = geometry->bound[NearestWallMarker][NearestWallElement]->GetNode(iNode); + // long iVertexHere = geometry->nodes->GetVertex(iPointHere, NearestWallMarker); + // for (auto iDim = 0u; iDim < nDim; iDim++) + // Normal[iPoint][iDim] += geometry->vertex[NearestWallMarker][iVertexHere]->GetNormal(iDim); + // } + // for (auto iDim = 0u; iDim < nDim; iDim++) + // Normal[iPoint][iDim] /= geometry->bound[NearestWallMarker][NearestWallElement]->GetnNodes(); + + // nodes->SetAuxVar(iPoint, 0, nodes->GetProjVel(iPoint, Normal[iPoint])); + // } + // END_SU2_OMP_FOR + + // //SU2_OMP_BARRIER + + // cout << "primo for" << endl; + + // if (config->GetKind_Gradient_Method() == GREEN_GAUSS) { + // SetAuxVar_Gradient_GG(geometry, config); + // } + // if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) { + // SetAuxVar_Gradient_LS(geometry, config); + // } + + // //SU2_OMP_BARRIER + + // cout << "Dopo Gradienti" << endl; + + // SU2_OMP_FOR_STAT(omp_chunk_size) + // for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + // su2double AuxVarHere = 0.0; + // for (auto iDim = 0u; iDim < nDim; iDim++) + // AuxVarHere += Normal[iPoint][iDim] * nodes->GetAuxVarGradient(iPoint, 0, iDim); + // nodes->SetAuxVar(iPoint, 0, AuxVarHere); + // } + // END_SU2_OMP_FOR + + // cout << "Ho finito" << endl; + // } } @@ -426,8 +426,8 @@ void CTransLMSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta /*--- Set coordinate (for debugging) ---*/ numerics->SetCoord(geometry->nodes->GetCoord(iPoint), nullptr); - if (options.LM2015) { - /*--- Set local grid length (for LM2015)*/ + if (options.CrossFlow && !options.SLM) { + /*--- Set local grid length (for LM2015 cross-flow corrections)*/ numerics->SetLocalGridLength(geometry->nodes->GetMaxLength(iPoint)); } diff --git a/config_template.cfg b/config_template.cfg index a7d0c468d8ed..8c468371198b 100644 --- a/config_template.cfg +++ b/config_template.cfg @@ -29,7 +29,7 @@ SA_OPTIONS= NONE % % Transition model (NONE, LM) KIND_TRANS_MODEL= NONE -% Specify versions/correlations of the LM model (LM2015, MALAN, SULUKSNA, KRAUSE, KRAUSE_HYPER, MEDIDA, MEDIDA_BAEDER, MENTER_LANGTRY) +% Specify versions/correlations of the LM model (CROSSFLOW, MALAN, SULUKSNA, KRAUSE, KRAUSE_HYPER, MEDIDA, MEDIDA_BAEDER, MENTER_LANGTRY) LM_OPTIONS= NONE % % Specify subgrid scale model(NONE, IMPLICIT_LES, SMAGORINSKY, WALE, VREMAN) From 04cd56dc1fb6f3d7958b505948c000a31e1b977e Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 2 Feb 2023 15:28:05 +0100 Subject: [PATCH 06/61] - Fixed Intermittency_Sep computation for SLM. --- Common/include/geometry/dual_grid/CPoint.hpp | 4 +- .../include/variables/CTransLMVariable.hpp | 12 ----- SU2_CFD/src/solvers/CTransLMSolver.cpp | 47 ++++++++++--------- SU2_CFD/src/variables/CTransLMVariable.cpp | 43 +++++++---------- 4 files changed, 45 insertions(+), 61 deletions(-) diff --git a/Common/include/geometry/dual_grid/CPoint.hpp b/Common/include/geometry/dual_grid/CPoint.hpp index 82489486acd8..6fee192b8525 100644 --- a/Common/include/geometry/dual_grid/CPoint.hpp +++ b/Common/include/geometry/dual_grid/CPoint.hpp @@ -459,12 +459,14 @@ class CPoint { /*! * \brief Get the index of the closest wall element. * \param[in] iPoint - Index of the point. - */ + * \param[out] ClosestWall_Elem - ID of the closest element on a wall boundary. + */ inline unsigned long GetClosestWall_Elem(unsigned long iPoint) {return ClosestWall_Elem(iPoint);} /*! * \brief Get the marker of the closest wall marker. * \param[in] iPoint - Index of the point. + * \param[out] ClosestWall_Marker - MarkerID of the closest wall boundary. */ inline unsigned long GetClosestWall_Marker(unsigned long iPoint) {return ClosestWall_Marker(iPoint);} diff --git a/SU2_CFD/include/variables/CTransLMVariable.hpp b/SU2_CFD/include/variables/CTransLMVariable.hpp index 6c18eb03b59a..fc6a2f654484 100644 --- a/SU2_CFD/include/variables/CTransLMVariable.hpp +++ b/SU2_CFD/include/variables/CTransLMVariable.hpp @@ -57,18 +57,6 @@ class CTransLMVariable final : public CTurbVariable { */ CTransLMVariable(su2double Intermittency, su2double ReThetaT, su2double gammaSep, su2double gammaEff, unsigned long npoint, unsigned long ndim, unsigned long nvar, CConfig *config); - /*! - * \brief Constructor of the class. - * \param[in] Intermittency - intermittency(gamma) (initialization value). - * \param[in] gammaSep - separation intermittency(gamma) (initialization value). - * \param[in] gammaEff - effective intermittency(gamma) (initialization value). - * \param[in] npoint - Number of points/nodes/vertices in the domain. - * \param[in] ndim - Number of dimensions of the problem. - * \param[in] nvar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CTransLMVariable(su2double Intermittency, su2double gammaSep, su2double gammaEff, unsigned long npoint, unsigned long ndim, unsigned long nvar, CConfig *config); - /*! * \brief Destructor of the class. */ diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 505cac4f7139..14fa20c37b3a 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -119,33 +119,27 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh const su2double Intermittency_Inf = 1.0; Solution_Inf[0] = Intermittency_Inf; - su2double ReThetaT_Inf = 0.0; + su2double ReThetaT_Inf = 100.0; - if (!options.SLM) { - - ReThetaT_Inf = 100.0; - - /*--- Momentum thickness Reynolds number, initialized from freestream turbulent intensity*/ - if (Intensity <= 1.3) { - if(Intensity >=0.027) { - ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(Intensity*Intensity)); - } - else { - ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(0.27*0.27)); - } + /*--- Momentum thickness Reynolds number, initialized from freestream turbulent intensity*/ + if (Intensity <= 1.3) { + if(Intensity >=0.027) { + ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(Intensity*Intensity)); } - else if(Intensity>1.3) { - ReThetaT_Inf = 331.5*pow(Intensity-0.5658,-0.671); + else { + ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(0.27*0.27)); } + } + else if(Intensity>1.3) { + ReThetaT_Inf = 331.5*pow(Intensity-0.5658,-0.671); + } + if (!options.SLM) { Solution_Inf[1] = ReThetaT_Inf; } /*--- Initialize the solution to the far-field state everywhere. ---*/ - nodes = new CTransLMVariable(Intermittency_Inf, 1.0, 1.0, nPoint, nDim, nVar, config); - if (!options.SLM) { - nodes = new CTransLMVariable(Intermittency_Inf, ReThetaT_Inf, 1.0, 1.0, nPoint, nDim, nVar, config); - } + nodes = new CTransLMVariable(Intermittency_Inf, ReThetaT_Inf, 1.0, 1.0, nPoint, nDim, nVar, config); SetBaseClassPointerToNodes(); @@ -299,15 +293,15 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai const su2double VelocityMag = sqrt(vel_u*vel_u + vel_v*vel_v + vel_w*vel_w); su2double omega = 0.0; su2double k = 0.0; + if(TurbFamily == TURB_FAMILY::KW){ + omega = turbNodes->GetSolution(iPoint,1); + k = turbNodes->GetSolution(iPoint,0); + } su2double Corr_Rec = 0.0; su2double Re_t = 0.0; if (!options.SLM) { Re_t = nodes->GetSolution(iPoint,1); - if(TurbFamily == TURB_FAMILY::KW){ - omega = turbNodes->GetSolution(iPoint,1); - k = turbNodes->GetSolution(iPoint,0); - } su2double Tu = 1.0; if(TurbFamily == TURB_FAMILY::KW) Tu = max(100.0*sqrt( 2.0 * k / 3.0 ) / VelocityMag,0.027); @@ -322,6 +316,9 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai Corr_Rec = nodes->GetCorr_Rec(iPoint); } + // cout << Re_t << " " << Corr_Rec << endl; + // if (geometry->nodes->GetDomain(iPoint)) cout << "Point is on boundary" << endl; + su2double R_t = 1.0; if(TurbFamily == TURB_FAMILY::KW) R_t = rho*k/ mu/ omega; @@ -329,6 +326,7 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai R_t = muT/ mu; const su2double f_reattach = exp(-pow(R_t/20,4)); + su2double f_wake = 0.0; if(TurbFamily == TURB_FAMILY::KW){ const su2double re_omega = rho*omega*dist*dist/mu; @@ -337,6 +335,8 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai if(TurbFamily == TURB_FAMILY::SA) f_wake = 1.0; + //cout << "StrainMag = " << StrainMag << " rho = " << rho << " dist = " << dist << " Re_v = " << Re_v << " Corr_Rec = " << Corr_Rec << endl; + const su2double theta_bl = Re_t*mu / rho /VelocityMag; const su2double delta_bl = 7.5*theta_bl; const su2double delta = 50.0*VorticityMag*dist/VelocityMag*delta_bl + 1e-20; @@ -344,6 +344,7 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai const su2double var2 = 1.0 - pow(var1,2.0); const su2double f_theta = min(max(f_wake*exp(-pow(dist/delta, 4)), var2), 1.0); su2double Intermittency_Sep = 2.0*max(0.0, Re_v/(3.235*Corr_Rec)-1.0)*f_reattach; + //if (Intermittency_Sep>1.0) cout << "StrainMag = " << StrainMag << " rho = " << rho << " dist = " << dist << " Re_v = " << Re_v << " Corr_Rec = " << Corr_Rec << " Intermittency: " << Intermittency_Sep << " f_reattach = " << f_reattach << endl; Intermittency_Sep = min(Intermittency_Sep,2.0)*f_theta; Intermittency_Sep = min(max(0.0, Intermittency_Sep), 2.0); nodes -> SetIntermittencySep(iPoint, Intermittency_Sep); diff --git a/SU2_CFD/src/variables/CTransLMVariable.cpp b/SU2_CFD/src/variables/CTransLMVariable.cpp index 1e7d09f75da1..29fdd45d2add 100644 --- a/SU2_CFD/src/variables/CTransLMVariable.cpp +++ b/SU2_CFD/src/variables/CTransLMVariable.cpp @@ -33,10 +33,17 @@ CTransLMVariable::CTransLMVariable(su2double Intermittency, su2double ReThetaT, LM_ParsedOptions options = config->GetLMParsedOptions(); - for(unsigned long iPoint=0; iPointGetLMParsedOptions(); - - for(unsigned long iPoint=0; iPoint Date: Fri, 24 Feb 2023 14:10:07 +0100 Subject: [PATCH 07/61] - Added computation for normals of grid points - Added variables only for debug --- Common/include/geometry/dual_grid/CPoint.hpp | 7 + Common/include/option_structure.hpp | 3 +- SU2_CFD/include/numerics/CNumerics.hpp | 20 +- .../transition/trans_correlations.hpp | 14 +- .../turbulent/transition/trans_sources.hpp | 119 +++++- .../numerics/turbulent/turb_sources.hpp | 2 +- SU2_CFD/include/solvers/CTransLMSolver.hpp | 1 + .../include/variables/CTransLMVariable.hpp | 35 ++ .../include/variables/CTurbSSTVariable.hpp | 1 + SU2_CFD/include/variables/CVariable.hpp | 22 ++ SU2_CFD/src/output/CFlowOutput.cpp | 52 ++- SU2_CFD/src/solvers/CTransLMSolver.cpp | 345 +++++++++++------- SU2_CFD/src/variables/CIncNSVariable.cpp | 1 - SU2_CFD/src/variables/CTransLMVariable.cpp | 51 ++- SU2_CFD/src/variables/CTurbSSTVariable.cpp | 1 + 15 files changed, 507 insertions(+), 167 deletions(-) diff --git a/Common/include/geometry/dual_grid/CPoint.hpp b/Common/include/geometry/dual_grid/CPoint.hpp index 6fee192b8525..795ee519a2e8 100644 --- a/Common/include/geometry/dual_grid/CPoint.hpp +++ b/Common/include/geometry/dual_grid/CPoint.hpp @@ -470,6 +470,13 @@ class CPoint { */ inline unsigned long GetClosestWall_Marker(unsigned long iPoint) {return ClosestWall_Marker(iPoint);} + /*! + * \brief Get the rank of the closest wall marker. + * \param[in] iPoint - Index of the point. + * \param[out] ClosestWall_Rank - RankID of the closest wall boundary. + */ + inline unsigned long GetClosestWall_Rank(unsigned long iPoint) {return ClosestWall_Rank(iPoint);} + /*! * \brief Get the value of the distance to the nearest wall. * \param[in] iPoint - Index of the point. diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp index f927d5b30d05..29940f0e21b3 100644 --- a/Common/include/option_structure.hpp +++ b/Common/include/option_structure.hpp @@ -1262,7 +1262,6 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh LMParsedOptions.ProdLim = IsPresent(LM_OPTIONS::PRODLIM); int NFoundCorrelations = 0; - int NFoundCorrelations_SLM = 0; if (IsPresent(LM_OPTIONS::MALAN)) { LMParsedOptions.Correlation = TURB_TRANS_CORRELATION::MALAN; NFoundCorrelations++; @@ -1291,6 +1290,8 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh LMParsedOptions.Correlation = TURB_TRANS_CORRELATION::MENTER_LANGTRY; NFoundCorrelations++; } + + int NFoundCorrelations_SLM = 0; if (IsPresent(LM_OPTIONS::MENTER_SLM)) { LMParsedOptions.Correlation_SLM = TURB_TRANS_CORRELATION_SLM::MENTER_SLM; NFoundCorrelations_SLM++; diff --git a/SU2_CFD/include/numerics/CNumerics.hpp b/SU2_CFD/include/numerics/CNumerics.hpp index 4b4c9c6224fa..837223daa591 100644 --- a/SU2_CFD/include/numerics/CNumerics.hpp +++ b/SU2_CFD/include/numerics/CNumerics.hpp @@ -736,15 +736,31 @@ class CNumerics { /*! * \brief Get the value of the Transition Momentum Thickness Reynolds number from correlations. - * \param[in] Corr_Rec_i - Value of the Transition Momentum Thickness Reynolds number at point i. + * \param[out] Corr_Rec_i - Value of the Transition Momentum Thickness Reynolds number at point i. */ inline virtual su2double GetCorr_Rec() {return 0.0;} /*! * \brief Get the value of the Momentum Thickness Reynolds number. - * \param[in] Corr_Rec_i - Value of the Momentum Thickness Reynolds number at point i. + * \param[out] re_t - Value of the Momentum Thickness Reynolds number at point i. */ inline virtual su2double GetRe_t() {return 0.0;} + inline virtual su2double GetTu() {return 0.0;} + inline virtual su2double GetLambda_theta() {return 0.0;} + inline virtual su2double Getduds() {return 0.0;} + inline virtual su2double GetRe_v() {return 0.0;} + inline virtual su2double GetProd() {return 0.0;} + inline virtual su2double GetDestr() {return 0.0;} + inline virtual su2double GetF_onset1() {return 0.0;} + inline virtual su2double GetF_onset2() {return 0.0;} + inline virtual su2double GetF_onset3() {return 0.0;} + inline virtual su2double GetF_onset() {return 0.0;} + + /*! + * \brief Set the value of the F2 blending function into SLM transition model. + * \param[in] val_F2 - F2 blending function. + */ + inline virtual void SetF2(su2double val_F2) {} /*! * \brief Set the gradient of the auxiliary variables. diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp index ecd569984ed8..acfe282beec9 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp @@ -205,9 +205,7 @@ class TransLMCorrelations { case TURB_TRANS_CORRELATION_SLM::MENTER_SLM: { /*-- Thwaites parameter ---*/ - // su2double lambda_theta_local = 7.57e-3 * du_ds * wall_dist * wall_dist * Density / Laminar_Viscosity + 0.0128; su2double lambda_theta_local = lambda_theta; - lambda_theta_local = min(max(lambda_theta_local, -1.0), 1.0); /*-- Function to sensitize the transition onset to the streamwise pressure gradient ---*/ su2double FPG = 0.0; @@ -266,10 +264,14 @@ class TransLMCorrelations { // This is not reported in the paper //FPG = max(FPG, 0.0); - const su2double C_TU1 = 100.0; - const su2double C_TU2 = 1000.0; - const su2double C_TU3 = 1.0; - rethetac = C_TU1 + C_TU2 * exp(-C_TU3 * Tu_L * FPG); + if (Tu_L <= 1.3) { + const su2double FirstTerm = -589.428 * Tu_L; + const su2double SecondTerm = 0.2196 / max(pow(Tu_L, 2.0), 1e-12); + rethetac = 1173.51 + FirstTerm + SecondTerm; + } else { + rethetac = 331.50 * pow(Tu_L-0.5658, -0.671); + } + rethetac = rethetac * FPG; break; } case TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM: { diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index 1bdc5c959cc9..14daac3d81a6 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -56,6 +56,17 @@ class CSourcePieceWise_TransLM final : public CNumerics { TURB_FAMILY TurbFamily; su2double hRoughness; + su2double Re_v_Here; + su2double Corr_Rec_Here; + su2double Prod_Here = 0.0; + su2double Destr_Here = 0.0; + su2double F_onset1_Here = 0.0; + su2double F_onset2_Here = 0.0; + su2double F_onset3_Here = 0.0; + su2double F_onset_Here = 0.0; + su2double lambda_theta_Here = 0.0; + su2double duds_Here = 0.0; + su2double IntermittencySep = 1.0; su2double IntermittencyEff = 1.0; @@ -135,6 +146,8 @@ class CSourcePieceWise_TransLM final : public CNumerics { /*--- Corr_RetC correlation*/ const su2double Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, TransVar_i[1]); + // AGGIUNTO PER DEBUG + Corr_Rec_Here = Corr_Rec; /*--- F_length correlation*/ const su2double Corr_F_length = TransCorrelations.FLength_Correlations(Tu, TransVar_i[1]); @@ -154,6 +167,11 @@ class CSourcePieceWise_TransLM final : public CNumerics { if (TurbFamily == TURB_FAMILY::SA) R_t = Eddy_Viscosity_i / Laminar_Viscosity_i; const su2double Re_v = Density_i * dist_i * dist_i * StrainMag_i / Laminar_Viscosity_i; + + // AGGIUNTO PER DEBUG + Re_v_Here = Re_v; + + const su2double F_onset1 = Re_v / (2.193 * Corr_Rec); su2double F_onset2 = 1.0; su2double F_onset3 = 1.0; @@ -166,6 +184,10 @@ class CSourcePieceWise_TransLM final : public CNumerics { F_onset3 = max(2.0 - pow(R_t / 2.5, 3.0), 0.0); } const su2double F_onset = max(F_onset2 - F_onset3, 0.0); + F_onset1_Here = F_onset1; + F_onset2_Here = F_onset2; + F_onset3_Here = F_onset3; + F_onset_Here = F_onset; /*-- Gradient of velocity magnitude ---*/ @@ -245,6 +267,9 @@ class CSourcePieceWise_TransLM final : public CNumerics { Retheta_old = Corr_Ret; } + lambda_theta_Here = lambda; + duds_Here = du_ds; + /*-- Corr_RetT_SCF Correlations--*/ su2double ReThetat_SCF = 0.0; if (options.CrossFlow) { @@ -292,6 +317,9 @@ class CSourcePieceWise_TransLM final : public CNumerics { /*-- destruction term of Intermeittency(Gamma) --*/ const su2double Dg = c_a2 * Density_i * VorticityMag * TransVar_i[0] * f_turb * (c_e2 * TransVar_i[0] - 1.0); + Prod_Here = Pg; + Destr_Here = Dg; + /*-- production term of ReThetaT --*/ const su2double PRethetat = c_theta * Density_i / time_scale * (Corr_Ret - TransVar_i[1]) * (1.0 - f_theta); @@ -322,6 +350,19 @@ class CSourcePieceWise_TransLM final : public CNumerics { return ResidualType<>(Residual, Jacobian_i, nullptr); } + + + inline su2double GetRe_v() override {return Re_v_Here;} + inline su2double GetCorr_Rec() override {return Corr_Rec_Here;} + inline su2double GetProd() override {return Prod_Here;} + inline su2double GetDestr() override {return Destr_Here;} + inline su2double GetF_onset1() override {return F_onset1_Here;} + inline su2double GetF_onset2() override {return F_onset2_Here;} + inline su2double GetF_onset3() override {return F_onset3_Here;} + inline su2double GetF_onset() override {return F_onset_Here;} + inline su2double GetLambda_theta() override {return lambda_theta_Here;} + inline su2double Getduds() override {return duds_Here;} + }; @@ -358,6 +399,17 @@ class CSourcePieceWise_TransSLM final : public CNumerics { su2double Re_t; su2double Corr_Rec; su2double AuxVar; + su2double F2; + su2double Tu_Here = 0.0; + su2double duds_Here = 0.0; + su2double lambda_theta_Here = 0.0; + su2double Re_v_Here = 0.0; + su2double Prod_Here = 0.0; + su2double Destr_Here = 0.0; + su2double F_onset1_Here = 0.0; + su2double F_onset2_Here = 0.0; + su2double F_onset3_Here = 0.0; + su2double F_onset_Here = 0.0; su2double Residual; su2double* Jacobian_i; @@ -412,7 +464,13 @@ class CSourcePieceWise_TransSLM final : public CNumerics { const su2double vel_v = V_i[1 + idx.Velocity()]; const su2double vel_w = (nDim == 3) ? V_i[2 + idx.Velocity()] : 0.0; - const su2double Velocity_Mag = sqrt(vel_u * vel_u + vel_v * vel_v + vel_w * vel_w); + su2double Velocity[nDim]; + Velocity[0] = vel_u; + Velocity[1] = vel_v; + if(nDim == 3) Velocity[2] = vel_w; + + + const su2double Velocity_Mag = max(sqrt(vel_u * vel_u + vel_v * vel_v + vel_w * vel_w), 1e-20); AD::SetPreaccIn(V_i[idx.Density()], V_i[idx.LaminarViscosity()], V_i[idx.EddyViscosity()]); @@ -425,50 +483,51 @@ class CSourcePieceWise_TransSLM final : public CNumerics { if (dist_i > 1e-10) { su2double Tu_L = 1.0; - if (TurbFamily == TURB_FAMILY::KW) Tu_L = max(min(100.0 * sqrt(2.0 * ScalarVar_i[0] / 3.0) / (ScalarVar_i[1]*dist_i), 100.0), 0.027); + if (TurbFamily == TURB_FAMILY::KW) Tu_L = min(100.0 * sqrt(2.0 * ScalarVar_i[0] / 3.0) / (ScalarVar_i[1]*dist_i), 100.0); + // if (TurbFamily == TURB_FAMILY::KW) Tu_L = min(100.0 * sqrt(2.0 * ScalarVar_i[0] / 3.0) / (Velocity_Mag), 100.0); if (TurbFamily == TURB_FAMILY::SA) Tu_L = config->GetTurbulenceIntensity_FreeStream() * 100; + Tu_Here = Tu_L; + /*--- F_length ---*/ su2double F_length = 100.0; /*--- F_onset ---*/ su2double R_t = 1.0; - if (TurbFamily == TURB_FAMILY::KW) R_t = Density_i * ScalarVar_i[0] / Laminar_Viscosity_i / ScalarVar_i[1]; + if (TurbFamily == TURB_FAMILY::KW) R_t = Density_i * ScalarVar_i[0] / (Laminar_Viscosity_i * ScalarVar_i[1]); if (TurbFamily == TURB_FAMILY::SA) R_t = Eddy_Viscosity_i / Laminar_Viscosity_i; /*-- Gradient of velocity magnitude ---*/ - su2double dU_dx = 0.5 / Velocity_Mag * (2. * vel_u * PrimVar_Grad_i[1][0] + 2. * vel_v * PrimVar_Grad_i[2][0]); - if (nDim == 3) dU_dx += 0.5 / Velocity_Mag * (2. * vel_w * PrimVar_Grad_i[3][0]); - - su2double dU_dy = 0.5 / Velocity_Mag * (2. * vel_u * PrimVar_Grad_i[1][1] + 2. * vel_v * PrimVar_Grad_i[2][1]); - if (nDim == 3) dU_dy += 0.5 / Velocity_Mag * (2. * vel_w * PrimVar_Grad_i[3][1]); - - su2double dU_dz = 0.0; - if (nDim == 3) - dU_dz = - 0.5 / Velocity_Mag * - (2. * vel_u * PrimVar_Grad_i[1][2] + 2. * vel_v * PrimVar_Grad_i[2][2] + 2. * vel_w * PrimVar_Grad_i[3][2]); + // su2double du_ds = 0.0; + // for (int i = 0; i < nDim; i++) + // for (int j = 0; j < nDim; j++) + // du_ds = du_ds + Velocity[i]*Velocity[j]*PrimVar_Grad_i[i][j]; - su2double du_ds = vel_u / Velocity_Mag * dU_dx + vel_v / Velocity_Mag * dU_dy; - if (nDim == 3) du_ds += vel_w / Velocity_Mag * dU_dz; + // du_ds = du_ds/(Velocity_Mag*Velocity_Mag); - const su2double lambda_theta = 7.57e-3 * du_ds * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128; + // const su2double lambda_theta = -7.57e-3 * du_ds * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128; + const su2double lambda_theta = max(min(-7.57e-3 * AuxVar * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128, 1.0), -1.0); + // const su2double lambda_theta = du_ds * dist_i * dist_i * Density_i / Laminar_Viscosity_i; + // duds_Here = du_ds; + duds_Here = AuxVar; + lambda_theta_Here = lambda_theta; + // const su2double lambda_theta = 7.57e-3 * AuxVar * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128; /*--- Corr_RetC correlation*/ Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, lambda_theta, dist_i, VorticityMag, Velocity_Mag); - // Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, lambda_theta, dist_i, VorticityMag, Velocity_Mag); + Corr_Rec = Re_t; // If the MENTER_SLM correlation is used then they are the same thing if (options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::CODER_SLM || options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM) { // If these correlations are used, then the value of Corr_Rec has to be used instead of the TransVar[1] of the original LM model F_length = TransCorrelations.FLength_Correlations(Tu_L, Re_t); Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu_L, Re_t); } - if (options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) Corr_Rec = Re_t; const su2double Re_v = Density_i * dist_i * dist_i * StrainMag_i / Laminar_Viscosity_i; + Re_v_Here = Re_v; const su2double F_onset1 = Re_v / (2.2 * Corr_Rec); su2double F_onset2 = 1.0; su2double F_onset3 = 1.0; @@ -482,6 +541,11 @@ class CSourcePieceWise_TransSLM final : public CNumerics { } su2double F_onset = max(F_onset2 - F_onset3, 0.0); + F_onset1_Here = F_onset1; + F_onset2_Here = F_onset2; + F_onset3_Here = F_onset3; + F_onset_Here = F_onset; + if (options.CrossFlow) { // Computation of shape factor @@ -532,7 +596,7 @@ class CSourcePieceWise_TransSLM final : public CNumerics { } - const su2double f_turb = exp(-pow(R_t / 4, 4)); + const su2double f_turb = exp(-pow(R_t / 2, 4)); /*-- production term of Intermeittency(Gamma) --*/ const su2double Pg = @@ -540,6 +604,9 @@ class CSourcePieceWise_TransSLM final : public CNumerics { /*-- destruction term of Intermeittency(Gamma) --*/ const su2double Dg = c_a2 * Density_i * VorticityMag * TransVar_i[0] * f_turb * (c_e2 * TransVar_i[0] - 1.0); + + Prod_Here = Pg; + Destr_Here = Dg; /*--- Source ---*/ Residual += (Pg - Dg) * Volume; @@ -560,6 +627,18 @@ class CSourcePieceWise_TransSLM final : public CNumerics { inline su2double GetRe_t() override {return Re_t;} inline su2double GetCorr_Rec() override {return Corr_Rec;} + inline su2double GetTu() override {return Tu_Here;} + inline su2double GetLambda_theta() override {return lambda_theta_Here;} + inline su2double Getduds() override {return duds_Here;} + inline su2double GetRe_v() override {return Re_v_Here;} + inline su2double GetProd() override {return Prod_Here;} + inline su2double GetDestr() override {return Destr_Here;} + inline su2double GetF_onset1() override {return F_onset1_Here;} + inline su2double GetF_onset2() override {return F_onset2_Here;} + inline su2double GetF_onset3() override {return F_onset3_Here;} + inline su2double GetF_onset() override {return F_onset_Here;} inline void SetAuxVar(su2double val_AuxVar) override { AuxVar = val_AuxVar;} + // non serve più + inline void SetF2(su2double val_F2) override { F2 = val_F2;} }; diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index 810245a2b433..8283018dd6ac 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -832,7 +832,7 @@ class CSourcePieceWise_TurbSST final : public CNumerics { if (config->GetKind_Trans_Model() == TURB_TRANS_MODEL::LM) { pk = pk * eff_intermittency; // Check if the Prod_lim_k has to be introduced based on input options - if ((config->GetLMParsedOptions()).ProdLim) { + if ((config->GetLMParsedOptions()).SLM) { const su2double Re_theta_c_lim = 1100.0; const su2double C_k = 1.0; const su2double C_SEP = 1.0; diff --git a/SU2_CFD/include/solvers/CTransLMSolver.hpp b/SU2_CFD/include/solvers/CTransLMSolver.hpp index acdf90fb9a47..176e7b602e46 100644 --- a/SU2_CFD/include/solvers/CTransLMSolver.hpp +++ b/SU2_CFD/include/solvers/CTransLMSolver.hpp @@ -42,6 +42,7 @@ class CTransLMSolver final : public CTurbSolver { LM_ParsedOptions options; TURB_FAMILY TurbFamily; + bool isSepNeeded; TransLMCorrelations TransCorrelations; diff --git a/SU2_CFD/include/variables/CTransLMVariable.hpp b/SU2_CFD/include/variables/CTransLMVariable.hpp index fc6a2f654484..8478b84d5502 100644 --- a/SU2_CFD/include/variables/CTransLMVariable.hpp +++ b/SU2_CFD/include/variables/CTransLMVariable.hpp @@ -42,6 +42,19 @@ class CTransLMVariable final : public CTurbVariable { VectorType Intermittency_Sep; VectorType Corr_Rec; VectorType Re_t; + VectorType Tu; + VectorType Lambda_theta; + VectorType duds; + VectorType Re_v; + VectorType Prod; + VectorType Destr; + VectorType F_onset1; + VectorType F_onset2; + VectorType F_onset3; + VectorType F_onset; + + VectorType normal_x; + VectorType normal_y; public: /*! @@ -81,6 +94,17 @@ class CTransLMVariable final : public CTurbVariable { * \brief Set Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). */ void SetRe_t(unsigned long iPoint, su2double val_Re_t) override; + void SetTu(unsigned long iPoint, su2double val_Tu) override; + void SetLambda_theta(unsigned long iPoint, su2double val_Lambda_theta) override; + void Setduds(unsigned long iPoint, su2double val_duds) override; + void SetRe_v(unsigned long iPoint, su2double val_Re_v) override; + void SetProd(unsigned long iPoint, su2double val_Prod) override; + void SetDestr(unsigned long iPoint, su2double val_Destr) override; + void SetF_onset1(unsigned long iPoint, su2double val_F_onset1) override; + void SetF_onset2(unsigned long iPoint, su2double val_F_onset2) override; + void SetF_onset3(unsigned long iPoint, su2double val_F_onset3) override; + void SetF_onset(unsigned long iPoint, su2double val_F_onset) override; + void SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y) override; /*! * \brief Calculate effective intermittency. @@ -101,4 +125,15 @@ class CTransLMVariable final : public CTurbVariable { * \brief Get Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). */ inline su2double GetRe_t(unsigned long iPoint) const override { return Re_t(iPoint); } + inline su2double GetTu(unsigned long iPoint) const override { return Tu(iPoint); } + inline su2double GetLambda_theta(unsigned long iPoint) const override { return Lambda_theta(iPoint); } + inline su2double Getduds(unsigned long iPoint) const override { return duds(iPoint); } + inline su2double GetRe_v(unsigned long iPoint) const override { return Re_v(iPoint); } + inline su2double GetProd(unsigned long iPoint) const override { return Prod(iPoint); } + inline su2double GetDestr(unsigned long iPoint) const override { return Destr(iPoint); } + inline su2double GetF_onset1(unsigned long iPoint) const override { return F_onset1(iPoint); } + inline su2double GetF_onset2(unsigned long iPoint) const override { return F_onset2(iPoint); } + inline su2double GetF_onset3(unsigned long iPoint) const override { return F_onset3(iPoint); } + inline su2double GetF_onset(unsigned long iPoint) const override { return F_onset(iPoint); } + inline pair GetNormal(unsigned long iPoint) const override {return make_pair(normal_x(iPoint), normal_y(iPoint));}; }; diff --git a/SU2_CFD/include/variables/CTurbSSTVariable.hpp b/SU2_CFD/include/variables/CTurbSSTVariable.hpp index e8a5d4559aad..159a110eb9be 100644 --- a/SU2_CFD/include/variables/CTurbSSTVariable.hpp +++ b/SU2_CFD/include/variables/CTurbSSTVariable.hpp @@ -45,6 +45,7 @@ class CTurbSSTVariable final : public CTurbVariable { VectorType F2; /*!< \brief Menter blending function for blending of k-w and k-eps. */ VectorType CDkw; /*!< \brief Cross-diffusion. */ SST_ParsedOptions sstParsedOptions; + LM_ParsedOptions lmParsedOptions; public: /*! * \brief Constructor of the class. diff --git a/SU2_CFD/include/variables/CVariable.hpp b/SU2_CFD/include/variables/CVariable.hpp index 099988e1a2b9..9fb1cac05566 100644 --- a/SU2_CFD/include/variables/CVariable.hpp +++ b/SU2_CFD/include/variables/CVariable.hpp @@ -1717,11 +1717,33 @@ class CVariable { * \brief Set Value of Transition Momentum Thickness Reynolds number from correlations. */ inline virtual void SetCorr_Rec(unsigned long iPoint, su2double val_Corr_Rec) {}; + inline virtual void SetTu(unsigned long iPoint, su2double val_Tu) {}; + inline virtual void SetLambda_theta(unsigned long iPoint, su2double val_Lambda_theta) {}; + inline virtual void Setduds(unsigned long iPoint, su2double val_duds) {}; + inline virtual void SetRe_v(unsigned long iPoint, su2double val_Re_v) {}; + inline virtual void SetProd(unsigned long iPoint, su2double val_Prod) {}; + inline virtual void SetDestr(unsigned long iPoint, su2double val_Destr) {}; + inline virtual void SetF_onset1(unsigned long iPoint, su2double val_F_onset1) {}; + inline virtual void SetF_onset2(unsigned long iPoint, su2double val_F_onset2) {}; + inline virtual void SetF_onset3(unsigned long iPoint, su2double val_F_onset3) {}; + inline virtual void SetF_onset(unsigned long iPoint, su2double val_F_onset1) {}; + inline virtual void SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y) {}; /*! * \brief Get Value of Transition Momentum Thickness Reynolds number from correlations. */ inline virtual su2double GetCorr_Rec(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetTu(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetLambda_theta(unsigned long iPoint) const { return 0.0; } + inline virtual su2double Getduds(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetRe_v(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetProd(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetDestr(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetF_onset1(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetF_onset2(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetF_onset3(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetF_onset(unsigned long iPoint) const { return 0.0; } + inline virtual pair GetNormal(unsigned long iPoint) const { return make_pair(0.0, 0.0); } /*! * \brief Set Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index 1c0d1e8f39a1..0ba43a94a989 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -1069,11 +1069,31 @@ void CFlowOutput::SetVolumeOutputFields_ScalarSolution(const CConfig* config){ case TURB_TRANS_MODEL::LM: AddVolumeOutput("INTERMITTENCY", "LM_gamma", "SOLUTION", "LM intermittency"); AddVolumeOutput("RE_THETA_T", "LM_Re_t", "SOLUTION", "LM RE_THETA_T"); + AddVolumeOutput("RE_V", "Re_v", "DEBUG", "LM Re_v"); + AddVolumeOutput("RE_THETA_CORR", "LM_Corr_Rec", "DEBUG", "LM RE_THETA_CORR"); + AddVolumeOutput("PROD", "LM_Prod", "DEBUG", "LM PROD"); + AddVolumeOutput("DESTR", "LM_Destr", "DEBUG", "LM DESTR"); + AddVolumeOutput("F_ONSET1", "LM_F_onset1", "DEBUG", "LM F_ONSET1"); + AddVolumeOutput("F_ONSET2", "LM_F_onset2", "DEBUG", "LM F_ONSET2"); + AddVolumeOutput("F_ONSET3", "LM_F_onset3", "DEBUG", "LM F_ONSET3"); + AddVolumeOutput("F_ONSET", "LM_F_onset", "DEBUG", "LM F_ONSET"); + AddVolumeOutput("STRAINMAG", "StrainMag", "DEBUG", "LM STRAINMAG"); + AddVolumeOutput("LAMBDA_THETA", "Lambda_theta", "DEBUG", "LM Lambda_theta"); + AddVolumeOutput("DU_DS", "du_ds", "DEBUG", "LM du_ds"); if ((config->GetLMParsedOptions()).SLM) { - AddVolumeOutput("RE_THETA_CORR", "LM_Corr_Rec", "SOLUTION", "LM RE_THETA_CORR"); + AddVolumeOutput("TU", "Tu", "SOLUTION", "LM Tu"); + AddVolumeOutput("NORMAL_X", "Normal_x", "DEBUG", "LM Normal_x"); + AddVolumeOutput("NORMAL_Y", "Normal_y", "DEBUG", "LM Normal_y"); + AddVolumeOutput("NORMAL_Z", "Normal_z", "DEBUG", "LM Normal_z"); + if (TurbModelFamily(config->GetKind_Turb_Model()) == TURB_FAMILY::SA) { + AddVolumeOutput("INTERMITTENCY_SEP", "LM_gamma_sep", "PRIMITIVE", "LM intermittency"); + AddVolumeOutput("INTERMITTENCY_EFF", "LM_gamma_eff", "PRIMITIVE", "LM RE_THETA_T"); + } + } + if (!(config->GetLMParsedOptions()).SLM) { + AddVolumeOutput("INTERMITTENCY_SEP", "LM_gamma_sep", "PRIMITIVE", "LM intermittency"); + AddVolumeOutput("INTERMITTENCY_EFF", "LM_gamma_eff", "PRIMITIVE", "LM RE_THETA_T"); } - AddVolumeOutput("INTERMITTENCY_SEP", "LM_gamma_sep", "PRIMITIVE", "LM intermittency"); - AddVolumeOutput("INTERMITTENCY_EFF", "LM_gamma_eff", "PRIMITIVE", "LM RE_THETA_T"); AddVolumeOutput("TURB_INDEX", "Turb_index", "PRIMITIVE", "Turbulence index"); break; @@ -1227,14 +1247,34 @@ void CFlowOutput::LoadVolumeData_Scalar(const CConfig* config, const CSolver* co switch (config->GetKind_Trans_Model()) { case TURB_TRANS_MODEL::LM: SetVolumeOutputValue("INTERMITTENCY", iPoint, Node_Trans->GetSolution(iPoint, 0)); + SetVolumeOutputValue("RE_V", iPoint, Node_Trans->GetRe_v(iPoint)); + SetVolumeOutputValue("RE_THETA_CORR", iPoint, Node_Trans->GetCorr_Rec(iPoint)); + SetVolumeOutputValue("PROD", iPoint, Node_Trans->GetProd(iPoint)); + SetVolumeOutputValue("DESTR", iPoint, Node_Trans->GetDestr(iPoint)); + SetVolumeOutputValue("F_ONSET1", iPoint, Node_Trans->GetF_onset1(iPoint)); + SetVolumeOutputValue("F_ONSET2", iPoint, Node_Trans->GetF_onset2(iPoint)); + SetVolumeOutputValue("F_ONSET3", iPoint, Node_Trans->GetF_onset3(iPoint)); + SetVolumeOutputValue("F_ONSET", iPoint, Node_Trans->GetF_onset(iPoint)); + SetVolumeOutputValue("STRAINMAG", iPoint, Node_Flow->GetStrainMag(iPoint)); + SetVolumeOutputValue("LAMBDA_THETA", iPoint, Node_Trans->GetLambda_theta(iPoint)); + SetVolumeOutputValue("DU_DS", iPoint, Node_Trans->Getduds(iPoint)); if (!(config->GetLMParsedOptions()).SLM) { SetVolumeOutputValue("RE_THETA_T", iPoint, Node_Trans->GetSolution(iPoint, 1)); } else { SetVolumeOutputValue("RE_THETA_T", iPoint, Node_Trans->GetRe_t(iPoint)); - SetVolumeOutputValue("RE_THETA_CORR", iPoint, Node_Trans->GetCorr_Rec(iPoint)); + SetVolumeOutputValue("TU", iPoint, Node_Trans->GetTu(iPoint)); + SetVolumeOutputValue("NORMAL_X", iPoint, (Node_Trans->GetNormal(iPoint)).first); + SetVolumeOutputValue("NORMAL_Y", iPoint, (Node_Trans->GetNormal(iPoint)).second); + SetVolumeOutputValue("NORMAL_Z", iPoint, 0.0); + if (TurbModelFamily(config->GetKind_Turb_Model()) == TURB_FAMILY::SA) { + SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); + SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); + } + } + if (!(config->GetLMParsedOptions()).SLM) { + SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); + SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); } - SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); - SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); SetVolumeOutputValue("TURB_INDEX", iPoint, Node_Turb->GetTurbIndex(iPoint)); SetVolumeOutputValue("RES_INTERMITTENCY", iPoint, trans_solver->LinSysRes(iPoint, 0)); if (!(config->GetLMParsedOptions()).SLM) { diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 14fa20c37b3a..bc44dca07f9e 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -71,6 +71,11 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh /*--- Define variables needed for transition from config file ---*/ TransCorrelations.SetOptions(options); TurbFamily = TurbModelFamily(config->GetKind_Turb_Model()); + isSepNeeded = true; + // If the Simplified model is used coupled with SST then we do not need the separation induced intermittency + // due to the added production term to k equation + if (options.SLM && TurbFamily == TURB_FAMILY::KW) isSepNeeded = false; + /*--- Single grid simulation ---*/ @@ -200,60 +205,115 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain ///////////////////// // cout << "Sono qui" << endl; - //if (rank == MASTER_NODE) { - // if (options.SLM) { - // /*--- Reconstructon of auxiliary variables gradient ---*/ - // su2double Normal[nPoint][nDim]; - // SU2_OMP_FOR_STAT(omp_chunk_size) - // for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { - // for (auto iDim = 0u; iDim < nDim; iDim++) - // Normal[iPoint][iDim] = 0.0; - - // // Extract nearest wall element and wall marker - // unsigned long NearestWallElement = geometry->nodes->GetClosestWall_Elem(iPoint); - // unsigned short NearestWallMarker = geometry->nodes->GetClosestWall_Marker(iPoint); - - // // Cycle on all of the points of the wall element - // for (unsigned short iNode = 0; iNode < geometry->bound[NearestWallMarker][NearestWallElement]->GetnNodes(); iNode++) { - // // Extract global coordinate of the node - // unsigned long iPointHere = geometry->bound[NearestWallMarker][NearestWallElement]->GetNode(iNode); - // long iVertexHere = geometry->nodes->GetVertex(iPointHere, NearestWallMarker); - // for (auto iDim = 0u; iDim < nDim; iDim++) - // Normal[iPoint][iDim] += geometry->vertex[NearestWallMarker][iVertexHere]->GetNormal(iDim); - // } - // for (auto iDim = 0u; iDim < nDim; iDim++) - // Normal[iPoint][iDim] /= geometry->bound[NearestWallMarker][NearestWallElement]->GetnNodes(); - - // nodes->SetAuxVar(iPoint, 0, nodes->GetProjVel(iPoint, Normal[iPoint])); - // } - // END_SU2_OMP_FOR - - // //SU2_OMP_BARRIER - - // cout << "primo for" << endl; - - // if (config->GetKind_Gradient_Method() == GREEN_GAUSS) { - // SetAuxVar_Gradient_GG(geometry, config); - // } - // if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) { - // SetAuxVar_Gradient_LS(geometry, config); - // } - - // //SU2_OMP_BARRIER - - // cout << "Dopo Gradienti" << endl; - - // SU2_OMP_FOR_STAT(omp_chunk_size) - // for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { - // su2double AuxVarHere = 0.0; - // for (auto iDim = 0u; iDim < nDim; iDim++) - // AuxVarHere += Normal[iPoint][iDim] * nodes->GetAuxVarGradient(iPoint, 0, iDim); - // nodes->SetAuxVar(iPoint, 0, AuxVarHere); - // } - // END_SU2_OMP_FOR - - // cout << "Ho finito" << endl; - // } + if (options.SLM && options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) { + /*--- Reconstructon of auxiliary variables gradient ---*/ + + // Each rank collects all normals + + vector>> WallNormal; + WallNormal.resize(config->GetnMarker_All()); + for (auto iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++){ + if (config->GetViscous_Wall(iMarker)) { + WallNormal[iMarker].resize(geometry->GetnElem_Bound(iMarker)); + + // cout << "geometry->nVertex[iMarker] = " << geometry->nVertex[iMarker] << endl; + for (auto iElem = 0u; iElem < geometry->GetnElem_Bound(iMarker); iElem++) { + vector NormalHere(nDim, 0.0); + + for (unsigned short iNode = 0; iNode < geometry->bound[iMarker][iElem]->GetnNodes(); iNode++) { + // Extract global coordinate of the node + unsigned long iPointHere = geometry->bound[iMarker][iElem]->GetNode(iNode); + long iVertexHere = geometry->nodes->GetVertex(iPointHere, iMarker); + for (auto iDim = 0u; iDim < nDim; iDim++) + NormalHere[iDim] += geometry->vertex[iMarker][iElem]->GetNormal(iDim); + //cout << "NormalHere(x, y, z) = " << NormalHere[0] << ", " << NormalHere[1] << ", " << NormalHere[2] << endl; + } + + for (auto iDim = 0u; iDim < nDim; iDim++) + NormalHere[iDim] /= geometry->bound[iMarker][iElem]->GetnNodes(); + su2double NormalMag = 0.0; + for (auto iDim = 0u; iDim < nDim; iDim++) + NormalMag += NormalHere[iDim]*NormalHere[iDim]; + NormalMag = sqrt(NormalMag); + + for (auto iDim = 0u; iDim < nDim; iDim++) + NormalHere[iDim] /= NormalMag; + + // cout << "FianlNormalHere(x, y, z) = " << NormalHere[0] << ", " << NormalHere[1] << ", " << NormalHere[2] << endl << endl; + + WallNormal[iMarker][iElem] = NormalHere; + } + } else { + WallNormal[iMarker].resize(1); + WallNormal[iMarker][0].resize(3); + WallNormal[iMarker][0][0] = 0.0; + WallNormal[iMarker][0][1] = 0.0; + WallNormal[iMarker][0][2] = 0.0; + } + } + + auto normal_i = + make_pair( config->GetnMarker_All(), [config,geometry,WallNormal](unsigned long iMarker){ + auto nElem_Bou = geometry->GetnElem_Bound(iMarker); + if (!config->GetViscous_Wall(iMarker)) nElem_Bou = 1; + + return make_pair(nElem_Bou, [WallNormal,iMarker](unsigned long iElem){ + const auto dimensions = 3; + + return make_pair(dimensions, [WallNormal,iMarker,iElem](unsigned short iDim){ + // cout << "iMarker = " << iMarker << " iElem = " << iElem << " iDim = " << iDim << endl; + return WallNormal[iMarker][iElem][iDim]; + }); + }); + }); + + NdFlattener<3>Normals_Local(normal_i); + NdFlattener<4> Normals_global(Nd_MPI_Environment(), Normals_Local); + su2double** NormalPerPoint = new su2double* [nPoint]; + + auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + + // Extract nearest wall element and wall marker + int NearestWallRank = geometry->nodes->GetClosestWall_Rank(iPoint); + unsigned long NearestWallElement = geometry->nodes->GetClosestWall_Elem(iPoint); + unsigned short NearestWallMarker = geometry->nodes->GetClosestWall_Marker(iPoint); + + NormalPerPoint[iPoint] = new su2double [MAXNDIM]; + for(auto iDim = 0; iDim < nDim; iDim++) + NormalPerPoint[iPoint][iDim] = Normals_global[NearestWallRank][NearestWallMarker][NearestWallMarker][iDim]; + + nodes->SetAuxVar(iPoint, 0, flowNodes->GetProjVel(iPoint, NormalPerPoint[iPoint])); + nodes->SetNormal(iPoint, NormalPerPoint[iPoint][0], NormalPerPoint[iPoint][1]); + } + END_SU2_OMP_FOR + + + // cout << "primo for" << endl; + + if (config->GetKind_Gradient_Method() == GREEN_GAUSS) { + SetAuxVar_Gradient_GG(geometry, config); + } + if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) { + SetAuxVar_Gradient_LS(geometry, config); + } + + //SU2_OMP_BARRIER + + // cout << "Dopo Gradienti" << endl; + + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + su2double AuxVarHere = 0.0; + for (auto iDim = 0u; iDim < nDim; iDim++) + AuxVarHere += NormalPerPoint[iPoint][iDim] * nodes->GetAuxVarGradient(iPoint, 0, iDim); + nodes->SetAuxVar(iPoint, 0, AuxVarHere); + } + END_SU2_OMP_FOR + + // cout << "Ho finito" << endl; + } } @@ -269,89 +329,104 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai } AD::StartNoSharedReading(); - auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); - auto* turbNodes = su2staticcast_p(solver_container[TURB_SOL]->GetNodes()); - - SU2_OMP_FOR_STAT(omp_chunk_size) - for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { - - // Here the nodes already have the new solution, thus I have to compute everything from scratch - - const su2double rho = flowNodes->GetDensity(iPoint); - const su2double mu = flowNodes->GetLaminarViscosity(iPoint); - const su2double muT = turbNodes->GetmuT(iPoint); - const su2double dist = geometry->nodes->GetWall_Distance(iPoint); - su2double VorticityMag = GeometryToolbox::Norm(3, flowNodes->GetVorticity(iPoint)); - su2double StrainMag =flowNodes->GetStrainMag(iPoint); - VorticityMag = max(VorticityMag, 1e-12); - StrainMag = max(StrainMag, 1e-12); // safety against division by zero - const su2double Intermittency = nodes->GetSolution(iPoint,0); - const su2double Re_v = rho*dist*dist*StrainMag/mu; - const su2double vel_u = flowNodes->GetVelocity(iPoint, 0); - const su2double vel_v = flowNodes->GetVelocity(iPoint, 1); - const su2double vel_w = (nDim ==3) ? flowNodes->GetVelocity(iPoint, 2) : 0.0; - const su2double VelocityMag = sqrt(vel_u*vel_u + vel_v*vel_v + vel_w*vel_w); - su2double omega = 0.0; - su2double k = 0.0; - if(TurbFamily == TURB_FAMILY::KW){ - omega = turbNodes->GetSolution(iPoint,1); - k = turbNodes->GetSolution(iPoint,0); - } - su2double Corr_Rec = 0.0; - su2double Re_t = 0.0; - if (!options.SLM) { - Re_t = nodes->GetSolution(iPoint,1); - su2double Tu = 1.0; - if(TurbFamily == TURB_FAMILY::KW) - Tu = max(100.0*sqrt( 2.0 * k / 3.0 ) / VelocityMag,0.027); - if(TurbFamily == TURB_FAMILY::SA) - Tu = config->GetTurbulenceIntensity_FreeStream()*100; + if(isSepNeeded){ + + AD::StartNoSharedReading(); + auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); + auto* turbNodes = su2staticcast_p(solver_container[TURB_SOL]->GetNodes()); + + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + + // Here the nodes already have the new solution, thus I have to compute everything from scratch + + const su2double rho = flowNodes->GetDensity(iPoint); + const su2double mu = flowNodes->GetLaminarViscosity(iPoint); + const su2double muT = turbNodes->GetmuT(iPoint); + const su2double dist = geometry->nodes->GetWall_Distance(iPoint); + su2double VorticityMag = GeometryToolbox::Norm(3, flowNodes->GetVorticity(iPoint)); + su2double StrainMag =flowNodes->GetStrainMag(iPoint); + VorticityMag = max(VorticityMag, 1e-12); + StrainMag = max(StrainMag, 1e-12); // safety against division by zero + const su2double Intermittency = nodes->GetSolution(iPoint,0); + const su2double Re_v = rho*dist*dist*StrainMag/mu; + const su2double vel_u = flowNodes->GetVelocity(iPoint, 0); + const su2double vel_v = flowNodes->GetVelocity(iPoint, 1); + const su2double vel_w = (nDim ==3) ? flowNodes->GetVelocity(iPoint, 2) : 0.0; + const su2double VelocityMag = sqrt(vel_u*vel_u + vel_v*vel_v + vel_w*vel_w); + su2double omega = 0.0; + su2double k = 0.0; + if(TurbFamily == TURB_FAMILY::KW){ + omega = turbNodes->GetSolution(iPoint,1); + k = turbNodes->GetSolution(iPoint,0); + } - Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, Re_t); - } + su2double Re_t = 0.0; + su2double Corr_Rec = 0.0; + + if (options.SLM && TurbFamily == TURB_FAMILY::SA) { + Re_t = nodes->GetRe_t(iPoint); + Corr_Rec = nodes->GetCorr_Rec(iPoint); + } else { + Re_t = nodes->GetSolution(iPoint,1); + su2double Tu = 1.0; + if(TurbFamily == TURB_FAMILY::KW) + Tu = max(100.0*sqrt( 2.0 * k / 3.0 ) / VelocityMag,0.027); + if(TurbFamily == TURB_FAMILY::SA) + Tu = config->GetTurbulenceIntensity_FreeStream()*100; + + Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, Re_t); + } - if (options.SLM) { - Re_t = nodes->GetRe_t(iPoint); - Corr_Rec = nodes->GetCorr_Rec(iPoint); - } - // cout << Re_t << " " << Corr_Rec << endl; - // if (geometry->nodes->GetDomain(iPoint)) cout << "Point is on boundary" << endl; + // cout << Re_t << " " << Corr_Rec << endl; + // if (geometry->nodes->GetDomain(iPoint)) cout << "Point is on boundary" << endl; - su2double R_t = 1.0; - if(TurbFamily == TURB_FAMILY::KW) - R_t = rho*k/ mu/ omega; - if(TurbFamily == TURB_FAMILY::SA) - R_t = muT/ mu; + su2double R_t = 1.0; + if(TurbFamily == TURB_FAMILY::KW) + R_t = rho*k/ mu/ omega; + if(TurbFamily == TURB_FAMILY::SA) + R_t = muT/ mu; + + const su2double f_reattach = exp(-pow(R_t/20,4)); - const su2double f_reattach = exp(-pow(R_t/20,4)); + su2double f_wake = 0.0; + if(TurbFamily == TURB_FAMILY::KW){ + const su2double re_omega = rho*omega*dist*dist/mu; + f_wake = exp(-pow(re_omega/(1.0e+05),2)); + } + if(TurbFamily == TURB_FAMILY::SA) + f_wake = 1.0; + + //cout << "StrainMag = " << StrainMag << " rho = " << rho << " dist = " << dist << " Re_v = " << Re_v << " Corr_Rec = " << Corr_Rec << endl; + + const su2double theta_bl = Re_t*mu / rho /VelocityMag; + const su2double delta_bl = 7.5*theta_bl; + const su2double delta = 50.0*VorticityMag*dist/VelocityMag*delta_bl + 1e-20; + const su2double var1 = (Intermittency-1.0/50.0)/(1.0-1.0/50.0); + const su2double var2 = 1.0 - pow(var1,2.0); + const su2double f_theta = min(max(f_wake*exp(-pow(dist/delta, 4)), var2), 1.0); + su2double Intermittency_Sep = 2.0*max(0.0, Re_v/(3.235*Corr_Rec)-1.0)*f_reattach; + //if (Intermittency_Sep>1.0) cout << "StrainMag = " << StrainMag << " rho = " << rho << " dist = " << dist << " Re_v = " << Re_v << " Corr_Rec = " << Corr_Rec << " Intermittency: " << Intermittency_Sep << " f_reattach = " << f_reattach << endl; + Intermittency_Sep = min(Intermittency_Sep,2.0)*f_theta; + Intermittency_Sep = min(max(0.0, Intermittency_Sep), 2.0); + nodes -> SetIntermittencySep(iPoint, Intermittency_Sep); + nodes -> SetIntermittencyEff(iPoint, Intermittency_Sep); - su2double f_wake = 0.0; - if(TurbFamily == TURB_FAMILY::KW){ - const su2double re_omega = rho*omega*dist*dist/mu; - f_wake = exp(-pow(re_omega/(1.0e+05),2)); } - if(TurbFamily == TURB_FAMILY::SA) - f_wake = 1.0; - - //cout << "StrainMag = " << StrainMag << " rho = " << rho << " dist = " << dist << " Re_v = " << Re_v << " Corr_Rec = " << Corr_Rec << endl; - - const su2double theta_bl = Re_t*mu / rho /VelocityMag; - const su2double delta_bl = 7.5*theta_bl; - const su2double delta = 50.0*VorticityMag*dist/VelocityMag*delta_bl + 1e-20; - const su2double var1 = (Intermittency-1.0/50.0)/(1.0-1.0/50.0); - const su2double var2 = 1.0 - pow(var1,2.0); - const su2double f_theta = min(max(f_wake*exp(-pow(dist/delta, 4)), var2), 1.0); - su2double Intermittency_Sep = 2.0*max(0.0, Re_v/(3.235*Corr_Rec)-1.0)*f_reattach; - //if (Intermittency_Sep>1.0) cout << "StrainMag = " << StrainMag << " rho = " << rho << " dist = " << dist << " Re_v = " << Re_v << " Corr_Rec = " << Corr_Rec << " Intermittency: " << Intermittency_Sep << " f_reattach = " << f_reattach << endl; - Intermittency_Sep = min(Intermittency_Sep,2.0)*f_theta; - Intermittency_Sep = min(max(0.0, Intermittency_Sep), 2.0); - nodes -> SetIntermittencySep(iPoint, Intermittency_Sep); - nodes -> SetIntermittencyEff(iPoint, Intermittency_Sep); + END_SU2_OMP_FOR } - END_SU2_OMP_FOR + else { + + // Effective intermittency and separation intermittency are not taken into account here! There is the added production term in the k-equation + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + nodes -> SetIntermittencyEff(iPoint, nodes->GetSolution(iPoint,0)); + } + END_SU2_OMP_FOR + } AD::EndNoSharedReading(); } @@ -433,7 +508,8 @@ void CTransLMSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta } if(options.SLM) { - numerics->SetAuxVar(nodes->GetAuxVar(iPoint, 0)); + if (options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) numerics->SetAuxVar(nodes->GetAuxVar(iPoint, 0)); + numerics->SetF2(turbNodes->GetF2blending(iPoint)); } /*--- Compute the source term ---*/ @@ -442,9 +518,20 @@ void CTransLMSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta if(options.SLM) { nodes->SetRe_t(iPoint, numerics->GetRe_t()); - nodes->SetCorr_Rec(iPoint, numerics->GetCorr_Rec()); + nodes->SetTu(iPoint, numerics->GetTu()); } + nodes->SetRe_v(iPoint, numerics->GetRe_v()); + nodes->SetCorr_Rec(iPoint, numerics->GetCorr_Rec()); + nodes->SetProd(iPoint, numerics->GetProd()); + nodes->SetDestr(iPoint, numerics->GetDestr()); + nodes->SetF_onset1(iPoint, numerics->GetF_onset1()); + nodes->SetF_onset2(iPoint, numerics->GetF_onset2()); + nodes->SetF_onset3(iPoint, numerics->GetF_onset3()); + nodes->SetF_onset(iPoint, numerics->GetF_onset()); + nodes->SetLambda_theta(iPoint, numerics->GetLambda_theta()); + nodes->Setduds(iPoint, numerics->Getduds()); + /*--- Subtract residual and the Jacobian ---*/ LinSysRes.SubtractBlock(iPoint, residual); diff --git a/SU2_CFD/src/variables/CIncNSVariable.cpp b/SU2_CFD/src/variables/CIncNSVariable.cpp index a3458a9eb46f..907ecba72934 100644 --- a/SU2_CFD/src/variables/CIncNSVariable.cpp +++ b/SU2_CFD/src/variables/CIncNSVariable.cpp @@ -100,7 +100,6 @@ bool CIncNSVariable::SetPrimVar(unsigned long iPoint, su2double eddy_visc, su2do SetVelocity(iPoint); /*--- Set laminar viscosity ---*/ - SetLaminarViscosity(iPoint, FluidModel->GetLaminarViscosity()); /*--- Set eddy viscosity locally and in the fluid model. ---*/ diff --git a/SU2_CFD/src/variables/CTransLMVariable.cpp b/SU2_CFD/src/variables/CTransLMVariable.cpp index 29fdd45d2add..bcc72b3af70b 100644 --- a/SU2_CFD/src/variables/CTransLMVariable.cpp +++ b/SU2_CFD/src/variables/CTransLMVariable.cpp @@ -53,13 +53,28 @@ CTransLMVariable::CTransLMVariable(su2double Intermittency, su2double ReThetaT, Intermittency_Sep.resize(nPoint) = gammaSep; if (options.SLM) { - Corr_Rec.resize(nPoint) = ReThetaT; Re_t.resize(nPoint) = ReThetaT; nAuxVar = 1; Grad_AuxVar.resize(nPoint, nAuxVar, nDim, 0.0); AuxVar.resize(nPoint, nAuxVar) = su2double(0.0); + Tu.resize(nPoint) = 0.0; + + normal_x.resize(nPoint) = 0.0; + normal_y.resize(nPoint) = 0.0; } + + + Re_v.resize(nPoint) = 0.0; + Corr_Rec.resize(nPoint) = 0.0; + Prod.resize(nPoint) = 0.0; + Destr.resize(nPoint) = 0.0; + F_onset1.resize(nPoint) = 0.0; + F_onset2.resize(nPoint) = 0.0; + F_onset3.resize(nPoint) = 0.0; + F_onset.resize(nPoint) = 0.0; + Lambda_theta.resize(nPoint) = 0.0; + duds.resize(nPoint) = 0.0; } @@ -81,4 +96,38 @@ void CTransLMVariable::SetCorr_Rec(unsigned long iPoint, su2double val_Corr_Rec) void CTransLMVariable::SetRe_t(unsigned long iPoint, su2double val_Re_t) { Re_t(iPoint) = val_Re_t; +} +void CTransLMVariable::SetTu(unsigned long iPoint, su2double val_Tu) { + Tu(iPoint) = val_Tu; +} +void CTransLMVariable::SetLambda_theta(unsigned long iPoint, su2double val_Lambda_theta) { + Lambda_theta(iPoint) = val_Lambda_theta; +} +void CTransLMVariable::Setduds(unsigned long iPoint, su2double val_duds) { + duds(iPoint) = val_duds; +} +void CTransLMVariable::SetRe_v(unsigned long iPoint, su2double val_Re_v) { + Re_v(iPoint) = val_Re_v; +} +void CTransLMVariable::SetProd(unsigned long iPoint, su2double val_Prod) { + Prod(iPoint) = val_Prod; +} +void CTransLMVariable::SetDestr(unsigned long iPoint, su2double val_Destr) { + Destr(iPoint) = val_Destr; +} +void CTransLMVariable::SetF_onset1(unsigned long iPoint, su2double val_F_onset1) { + F_onset1(iPoint) = val_F_onset1; +} +void CTransLMVariable::SetF_onset2(unsigned long iPoint, su2double val_F_onset2) { + F_onset2(iPoint) = val_F_onset2; +} +void CTransLMVariable::SetF_onset3(unsigned long iPoint, su2double val_F_onset3) { + F_onset3(iPoint) = val_F_onset3; +} +void CTransLMVariable::SetF_onset(unsigned long iPoint, su2double val_F_onset) { + F_onset(iPoint) = val_F_onset; +} +void CTransLMVariable::SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y) { + normal_x(iPoint) = val_normal_x; + normal_y(iPoint) = val_normal_y; } \ No newline at end of file diff --git a/SU2_CFD/src/variables/CTurbSSTVariable.cpp b/SU2_CFD/src/variables/CTurbSSTVariable.cpp index c4506529d10e..c134d7ca2e29 100644 --- a/SU2_CFD/src/variables/CTurbSSTVariable.cpp +++ b/SU2_CFD/src/variables/CTurbSSTVariable.cpp @@ -33,6 +33,7 @@ CTurbSSTVariable::CTurbSSTVariable(su2double kine, su2double omega, su2double mu : CTurbVariable(npoint, ndim, nvar, config) { sstParsedOptions = config->GetSSTParsedOptions(); + lmParsedOptions = config->GetLMParsedOptions(); for(unsigned long iPoint=0; iPoint Date: Fri, 24 Feb 2023 14:52:37 +0100 Subject: [PATCH 08/61] Fixed normal extraction from structure --- SU2_CFD/src/solvers/CTransLMSolver.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index bc44dca07f9e..add591209ff7 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -226,11 +226,11 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain long iVertexHere = geometry->nodes->GetVertex(iPointHere, iMarker); for (auto iDim = 0u; iDim < nDim; iDim++) NormalHere[iDim] += geometry->vertex[iMarker][iElem]->GetNormal(iDim); - //cout << "NormalHere(x, y, z) = " << NormalHere[0] << ", " << NormalHere[1] << ", " << NormalHere[2] << endl; } for (auto iDim = 0u; iDim < nDim; iDim++) NormalHere[iDim] /= geometry->bound[iMarker][iElem]->GetnNodes(); + su2double NormalMag = 0.0; for (auto iDim = 0u; iDim < nDim; iDim++) NormalMag += NormalHere[iDim]*NormalHere[iDim]; @@ -239,6 +239,7 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain for (auto iDim = 0u; iDim < nDim; iDim++) NormalHere[iDim] /= NormalMag; + // cout << "NormalHere(x, y, z) = " << NormalHere[0] << ", " << NormalHere[1] << ", " << NormalHere[2] << endl; // cout << "FianlNormalHere(x, y, z) = " << NormalHere[0] << ", " << NormalHere[1] << ", " << NormalHere[2] << endl << endl; WallNormal[iMarker][iElem] = NormalHere; @@ -262,6 +263,8 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain return make_pair(dimensions, [WallNormal,iMarker,iElem](unsigned short iDim){ // cout << "iMarker = " << iMarker << " iElem = " << iElem << " iDim = " << iDim << endl; + // cout << "WallNormal(x, y, z) = " << WallNormal[iMarker][iElem][0] << ", " << WallNormal[iMarker][iElem][1] << ", " << WallNormal[iMarker][iElem][2] << endl; + return WallNormal[iMarker][iElem][iDim]; }); }); @@ -279,11 +282,13 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain int NearestWallRank = geometry->nodes->GetClosestWall_Rank(iPoint); unsigned long NearestWallElement = geometry->nodes->GetClosestWall_Elem(iPoint); unsigned short NearestWallMarker = geometry->nodes->GetClosestWall_Marker(iPoint); + // cout << "NearestWallRank = " << NearestWallRank << " NearestWallElement = " << NearestWallElement << " NearestWallMarker = " << NearestWallMarker << endl; NormalPerPoint[iPoint] = new su2double [MAXNDIM]; for(auto iDim = 0; iDim < nDim; iDim++) - NormalPerPoint[iPoint][iDim] = Normals_global[NearestWallRank][NearestWallMarker][NearestWallMarker][iDim]; + NormalPerPoint[iPoint][iDim] = Normals_global[NearestWallRank][NearestWallMarker][NearestWallElement][iDim]; + // cout << "NormalHere(x, y, z) = " << NormalPerPoint[iPoint][0] << ", " << NormalPerPoint[iPoint][1] << ", " << NormalPerPoint[iPoint][2] << endl; nodes->SetAuxVar(iPoint, 0, flowNodes->GetProjVel(iPoint, NormalPerPoint[iPoint])); nodes->SetNormal(iPoint, NormalPerPoint[iPoint][0], NormalPerPoint[iPoint][1]); } From b1edf61fca342c17a93f4daca8701474f15de5e5 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 24 Feb 2023 19:20:46 +0100 Subject: [PATCH 09/61] Added computation of wall normals to the CPoint structure --- Common/include/geometry/dual_grid/CPoint.hpp | 36 ++++ Common/src/geometry/CGeometry.cpp | 76 +++++++++ Common/src/geometry/dual_grid/CPoint.cpp | 2 + SU2_CFD/src/solvers/CTransLMSolver.cpp | 169 +++++++++---------- 4 files changed, 193 insertions(+), 90 deletions(-) diff --git a/Common/include/geometry/dual_grid/CPoint.hpp b/Common/include/geometry/dual_grid/CPoint.hpp index 795ee519a2e8..efe3a81406cd 100644 --- a/Common/include/geometry/dual_grid/CPoint.hpp +++ b/Common/include/geometry/dual_grid/CPoint.hpp @@ -102,6 +102,7 @@ class CPoint { su2activevector Curvature; /*!< \brief Value of the surface curvature (SU2_GEO). */ su2activevector MaxLength; /*!< \brief The maximum cell-center to cell-center length. */ su2activevector RoughnessHeight; /*!< \brief Roughness of the nearest wall. */ + su2activematrix Normals; /*!< \brief Normal of the nearest wall element. */ su2matrix AD_InputIndex; /*!< \brief Indices of Coord variables in the adjoint vector. */ su2matrix AD_OutputIndex; /*!< \brief Indices of Coord variables in the adjoint vector after having been updated. */ @@ -499,6 +500,24 @@ class CPoint { */ inline su2double GetRoughnessHeight(unsigned long iPoint) const { return RoughnessHeight(iPoint); } + /*! + * \brief Set the value of the normal of the nearest wall element. + * \param[in] iPoint - Index of the point. + * \param[in] normal - Value of the normal. + */ + template + inline void SetNormal(unsigned long iPoint, Normals_type const&normal) { + for (unsigned long iDim = 0; iDim < nDim; iDim++) + Normals(iPoint,iDim) = normal[iDim]; + } + + /*! + * \brief Set the value of the normal of the nearest wall element. + * \param[in] iPoint - Index of the point. + * \return normal to the normal of the nearest wall element. + */ + inline su2double *GetNormal(unsigned long iPoint) { return Normals[iPoint]; } + /*! * \brief Set the value of the distance to a sharp edge. * \param[in] iPoint - Index of the point. @@ -900,4 +919,21 @@ class CPoint { } } + + /*! + * \brief Set wall normal according to stored closest wall information. + * \param[in] normals - Mapping [rank][zone][marker][element] -> normal + */ + template + void SetWallNormals(Normals_type const&normals){ + for (unsigned long iPoint=0; iPoint= 0) + SetNormal(iPoint, normals[rankID][zoneID][markerID][elementID]); + } + } + }; diff --git a/Common/src/geometry/CGeometry.cpp b/Common/src/geometry/CGeometry.cpp index 87ed7214f60d..c5436b8930d0 100644 --- a/Common/src/geometry/CGeometry.cpp +++ b/Common/src/geometry/CGeometry.cpp @@ -4106,5 +4106,81 @@ void CGeometry::ComputeWallDistance(const CConfig* const* config_container, CGeo } } } + + + su2vector>> WallNormal_container; + WallNormal_container.resize(nZone) = su2vector>(); + for (int iZone = 0; iZone < nZone; iZone++){ + const CConfig* config = config_container[iZone]; + const CGeometry* geometry = geometry_container[iZone][iInst][MESH_0]; + WallNormal_container[iZone].resize(geometry->GetnMarker()); + for (auto iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++){ + if (config->GetViscous_Wall(iMarker)) { + WallNormal_container[iZone][iMarker].resize(geometry->GetnElem_Bound(iMarker), 3); + + // cout << "geometry->nVertex[iMarker] = " << geometry->nVertex[iMarker] << endl; + for (auto iElem = 0u; iElem < geometry->GetnElem_Bound(iMarker); iElem++) { + su2vector NormalHere; + NormalHere.resize(3) = su2double(0.0); + + for (unsigned short iNode = 0; iNode < geometry->bound[iMarker][iElem]->GetnNodes(); iNode++) { + // Extract global coordinate of the node + unsigned long iPointHere = geometry->bound[iMarker][iElem]->GetNode(iNode); + long iVertexHere = geometry->nodes->GetVertex(iPointHere, iMarker); + for (auto iDim = 0u; iDim < 3; iDim++) + NormalHere[iDim] += geometry->vertex[iMarker][iElem]->GetNormal(iDim); + } + + for (auto iDim = 0u; iDim < 3; iDim++) + NormalHere[iDim] /= geometry->bound[iMarker][iElem]->GetnNodes(); + + su2double NormalMag = 0.0; + for (auto iDim = 0u; iDim < 3; iDim++) + NormalMag += NormalHere[iDim]*NormalHere[iDim]; + NormalMag = sqrt(NormalMag); + + for (auto iDim = 0u; iDim < 3; iDim++) + NormalHere[iDim] /= NormalMag; + + for (auto iDim = 0u; iDim < 3; iDim++) + WallNormal_container[iZone][iMarker](iElem, iDim) = NormalHere[iDim]; + + } + } else { + WallNormal_container[iZone][iMarker].resize(1, 3) = su2double(0.0); + } + } + } + + auto normal_i = + make_pair(nZone, [config_container,geometry_container,iInst,WallNormal_container](unsigned long iZone){ + const CConfig* config = config_container[iZone]; + const CGeometry* geometry = geometry_container[iZone][iInst][MESH_0]; + const auto nMarker = geometry->GetnMarker(); + const auto WallNormal = WallNormal_container[iZone]; + + return make_pair( nMarker, [config,geometry,WallNormal](unsigned long iMarker){ + auto nElem_Bou = geometry->GetnElem_Bound(iMarker); + if (!config->GetViscous_Wall(iMarker)) nElem_Bou = 1; + + return make_pair(nElem_Bou, [WallNormal,iMarker](unsigned long iElem){ + const auto dimensions = 3; + + return make_pair(dimensions, [WallNormal,iMarker,iElem](unsigned short iDim){ + + return WallNormal[iMarker](iElem, iDim); + }); + }); + }); + }); + + NdFlattener<4>Normals_Local(normal_i); + NdFlattener<5> Normals_global(Nd_MPI_Environment(), Normals_Local); + + + // use it to update roughnesses + for(int jZone=0; jZonenodes->SetWallNormals(Normals_global); + } } } diff --git a/Common/src/geometry/dual_grid/CPoint.cpp b/Common/src/geometry/dual_grid/CPoint.cpp index 3d392128b312..752d4df0cd6c 100644 --- a/Common/src/geometry/dual_grid/CPoint.cpp +++ b/Common/src/geometry/dual_grid/CPoint.cpp @@ -141,6 +141,8 @@ void CPoint::FullAllocation(unsigned short imesh, const CConfig *config) { RoughnessHeight.resize(npoint) = su2double(0.0); SharpEdge_Distance.resize(npoint) = su2double(0.0); + Normals.resize(npoint, 3) = su2double(0.0); + } void CPoint::SetElems(const vector >& elemsMatrix) { diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index add591209ff7..a7eda1086c20 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -198,105 +198,97 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain CommonPreprocessing(geometry, config, Output); - ///////////////////// - // ATTENZIONE! Forse devo farlo solamente per i punti che sono nello strato limite! Quindi magari nelle sources devo usare la function che mi definisce lo strato limite! - // Al di fuori di essa devo usare la solita du/ds? Perchè altrimenti il contorno più vicino ad un certo punto diventa il farfield, e non ha senso! - // UPDATE: Mi sa che la wall distance è rispetto alla parete, quindi effettivamente l'elemento più vicino è sempre a parete. - ///////////////////// - - // cout << "Sono qui" << endl; if (options.SLM && options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) { /*--- Reconstructon of auxiliary variables gradient ---*/ // Each rank collects all normals - vector>> WallNormal; - WallNormal.resize(config->GetnMarker_All()); - for (auto iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++){ - if (config->GetViscous_Wall(iMarker)) { - WallNormal[iMarker].resize(geometry->GetnElem_Bound(iMarker)); - - // cout << "geometry->nVertex[iMarker] = " << geometry->nVertex[iMarker] << endl; - for (auto iElem = 0u; iElem < geometry->GetnElem_Bound(iMarker); iElem++) { - vector NormalHere(nDim, 0.0); - - for (unsigned short iNode = 0; iNode < geometry->bound[iMarker][iElem]->GetnNodes(); iNode++) { - // Extract global coordinate of the node - unsigned long iPointHere = geometry->bound[iMarker][iElem]->GetNode(iNode); - long iVertexHere = geometry->nodes->GetVertex(iPointHere, iMarker); - for (auto iDim = 0u; iDim < nDim; iDim++) - NormalHere[iDim] += geometry->vertex[iMarker][iElem]->GetNormal(iDim); - } - - for (auto iDim = 0u; iDim < nDim; iDim++) - NormalHere[iDim] /= geometry->bound[iMarker][iElem]->GetnNodes(); - - su2double NormalMag = 0.0; - for (auto iDim = 0u; iDim < nDim; iDim++) - NormalMag += NormalHere[iDim]*NormalHere[iDim]; - NormalMag = sqrt(NormalMag); - - for (auto iDim = 0u; iDim < nDim; iDim++) - NormalHere[iDim] /= NormalMag; - - // cout << "NormalHere(x, y, z) = " << NormalHere[0] << ", " << NormalHere[1] << ", " << NormalHere[2] << endl; - // cout << "FianlNormalHere(x, y, z) = " << NormalHere[0] << ", " << NormalHere[1] << ", " << NormalHere[2] << endl << endl; - - WallNormal[iMarker][iElem] = NormalHere; - } - } else { - WallNormal[iMarker].resize(1); - WallNormal[iMarker][0].resize(3); - WallNormal[iMarker][0][0] = 0.0; - WallNormal[iMarker][0][1] = 0.0; - WallNormal[iMarker][0][2] = 0.0; - } - } - - auto normal_i = - make_pair( config->GetnMarker_All(), [config,geometry,WallNormal](unsigned long iMarker){ - auto nElem_Bou = geometry->GetnElem_Bound(iMarker); - if (!config->GetViscous_Wall(iMarker)) nElem_Bou = 1; - - return make_pair(nElem_Bou, [WallNormal,iMarker](unsigned long iElem){ - const auto dimensions = 3; - - return make_pair(dimensions, [WallNormal,iMarker,iElem](unsigned short iDim){ - // cout << "iMarker = " << iMarker << " iElem = " << iElem << " iDim = " << iDim << endl; - // cout << "WallNormal(x, y, z) = " << WallNormal[iMarker][iElem][0] << ", " << WallNormal[iMarker][iElem][1] << ", " << WallNormal[iMarker][iElem][2] << endl; + // vector>> WallNormal; + // WallNormal.resize(config->GetnMarker_All()); + // for (auto iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++){ + // if (config->GetViscous_Wall(iMarker)) { + // WallNormal[iMarker].resize(geometry->GetnElem_Bound(iMarker)); + + // // cout << "geometry->nVertex[iMarker] = " << geometry->nVertex[iMarker] << endl; + // for (auto iElem = 0u; iElem < geometry->GetnElem_Bound(iMarker); iElem++) { + // vector NormalHere(nDim, 0.0); + + // for (unsigned short iNode = 0; iNode < geometry->bound[iMarker][iElem]->GetnNodes(); iNode++) { + // // Extract global coordinate of the node + // unsigned long iPointHere = geometry->bound[iMarker][iElem]->GetNode(iNode); + // long iVertexHere = geometry->nodes->GetVertex(iPointHere, iMarker); + // for (auto iDim = 0u; iDim < nDim; iDim++) + // NormalHere[iDim] += geometry->vertex[iMarker][iElem]->GetNormal(iDim); + // } + + // for (auto iDim = 0u; iDim < nDim; iDim++) + // NormalHere[iDim] /= geometry->bound[iMarker][iElem]->GetnNodes(); + + // su2double NormalMag = 0.0; + // for (auto iDim = 0u; iDim < nDim; iDim++) + // NormalMag += NormalHere[iDim]*NormalHere[iDim]; + // NormalMag = sqrt(NormalMag); + + // for (auto iDim = 0u; iDim < nDim; iDim++) + // NormalHere[iDim] /= NormalMag; + + // WallNormal[iMarker][iElem] = NormalHere; + // } + // } else { + // WallNormal[iMarker].resize(1); + // WallNormal[iMarker][0].resize(3); + // WallNormal[iMarker][0][0] = 0.0; + // WallNormal[iMarker][0][1] = 0.0; + // WallNormal[iMarker][0][2] = 0.0; + // } + // } + + // auto normal_i = + // make_pair( config->GetnMarker_All(), [config,geometry,WallNormal](unsigned long iMarker){ + // auto nElem_Bou = geometry->GetnElem_Bound(iMarker); + // if (!config->GetViscous_Wall(iMarker)) nElem_Bou = 1; + + // return make_pair(nElem_Bou, [WallNormal,iMarker](unsigned long iElem){ + // const auto dimensions = 3; + + // return make_pair(dimensions, [WallNormal,iMarker,iElem](unsigned short iDim){ + + // return WallNormal[iMarker][iElem][iDim]; + // }); + // }); + // }); + + // NdFlattener<3>Normals_Local(normal_i); + // NdFlattener<4> Normals_global(Nd_MPI_Environment(), Normals_Local); + // su2double** NormalPerPoint = new su2double* [nPoint]; + + // auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); + // SU2_OMP_FOR_STAT(omp_chunk_size) + // for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + + // // Extract nearest wall element and wall marker + // int NearestWallRank = geometry->nodes->GetClosestWall_Rank(iPoint); + // unsigned long NearestWallElement = geometry->nodes->GetClosestWall_Elem(iPoint); + // unsigned short NearestWallMarker = geometry->nodes->GetClosestWall_Marker(iPoint); - return WallNormal[iMarker][iElem][iDim]; - }); - }); - }); + // NormalPerPoint[iPoint] = new su2double [MAXNDIM]; + // for(auto iDim = 0; iDim < nDim; iDim++) + // NormalPerPoint[iPoint][iDim] = Normals_global[NearestWallRank][NearestWallMarker][NearestWallElement][iDim]; - NdFlattener<3>Normals_Local(normal_i); - NdFlattener<4> Normals_global(Nd_MPI_Environment(), Normals_Local); - su2double** NormalPerPoint = new su2double* [nPoint]; + // nodes->SetAuxVar(iPoint, 0, flowNodes->GetProjVel(iPoint, NormalPerPoint[iPoint])); + // nodes->SetNormal(iPoint, NormalPerPoint[iPoint][0], NormalPerPoint[iPoint][1]); + // } + // END_SU2_OMP_FOR auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); SU2_OMP_FOR_STAT(omp_chunk_size) for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { - - // Extract nearest wall element and wall marker - int NearestWallRank = geometry->nodes->GetClosestWall_Rank(iPoint); - unsigned long NearestWallElement = geometry->nodes->GetClosestWall_Elem(iPoint); - unsigned short NearestWallMarker = geometry->nodes->GetClosestWall_Marker(iPoint); - // cout << "NearestWallRank = " << NearestWallRank << " NearestWallElement = " << NearestWallElement << " NearestWallMarker = " << NearestWallMarker << endl; - - NormalPerPoint[iPoint] = new su2double [MAXNDIM]; - for(auto iDim = 0; iDim < nDim; iDim++) - NormalPerPoint[iPoint][iDim] = Normals_global[NearestWallRank][NearestWallMarker][NearestWallElement][iDim]; - - // cout << "NormalHere(x, y, z) = " << NormalPerPoint[iPoint][0] << ", " << NormalPerPoint[iPoint][1] << ", " << NormalPerPoint[iPoint][2] << endl; - nodes->SetAuxVar(iPoint, 0, flowNodes->GetProjVel(iPoint, NormalPerPoint[iPoint])); - nodes->SetNormal(iPoint, NormalPerPoint[iPoint][0], NormalPerPoint[iPoint][1]); + auto Normal = geometry->nodes->GetNormal(iPoint); + nodes->SetAuxVar(iPoint, 0, flowNodes->GetProjVel(iPoint, Normal)); + nodes->SetNormal(iPoint, Normal[0], Normal[1]); } END_SU2_OMP_FOR - - // cout << "primo for" << endl; - if (config->GetKind_Gradient_Method() == GREEN_GAUSS) { SetAuxVar_Gradient_GG(geometry, config); } @@ -304,20 +296,17 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain SetAuxVar_Gradient_LS(geometry, config); } - //SU2_OMP_BARRIER - - // cout << "Dopo Gradienti" << endl; SU2_OMP_FOR_STAT(omp_chunk_size) for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { su2double AuxVarHere = 0.0; + auto Normal = geometry->nodes->GetNormal(iPoint); for (auto iDim = 0u; iDim < nDim; iDim++) - AuxVarHere += NormalPerPoint[iPoint][iDim] * nodes->GetAuxVarGradient(iPoint, 0, iDim); + AuxVarHere += Normal[iDim] * nodes->GetAuxVarGradient(iPoint, 0, iDim); nodes->SetAuxVar(iPoint, 0, AuxVarHere); } END_SU2_OMP_FOR - // cout << "Ho finito" << endl; } } From 7eee4ab87bd40ab5b5bc02a7bc04b0e6925c99f0 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 27 Apr 2023 10:06:15 +0200 Subject: [PATCH 10/61] Check For changes --- .../turbulent/transition/trans_sources.hpp | 4 +- .../numerics/turbulent/turb_sources.hpp | 7 +- SU2_CFD/src/SU2_CFD.cpp | 3 +- SU2_CFD/src/output/CFlowIncOutput.cpp | 1 + SU2_CFD/src/output/CFlowOutput.cpp | 7 +- SU2_CFD/src/solvers/CTransLMSolver.cpp | 89 +------------------ SU2_CFD/src/solvers/CTurbSASolver.cpp | 4 +- SU2_CFD/src/solvers/CTurbSSTSolver.cpp | 4 +- 8 files changed, 21 insertions(+), 98 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index 14daac3d81a6..0dae2e76c0ef 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -124,7 +124,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { const su2double vel_v = V_i[1 + idx.Velocity()]; const su2double vel_w = (nDim == 3) ? V_i[2 + idx.Velocity()] : 0.0; - const su2double Velocity_Mag = sqrt(vel_u * vel_u + vel_v * vel_v + vel_w * vel_w); + const su2double Velocity_Mag = max(sqrt(vel_u * vel_u + vel_v * vel_v + vel_w * vel_w), 1e-20); AD::SetPreaccIn(V_i[idx.Density()], V_i[idx.LaminarViscosity()], V_i[idx.EddyViscosity()]); @@ -235,7 +235,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { const su2double Corr_Ret_lim = 20.0; su2double f_lambda = 1.0; - su2double Retheta_Error = 200.0, Retheta_old = 0.0; + su2double Retheta_Error = 200.0, Retheta_old = 1.0; su2double lambda = 0.0; su2double Corr_Ret = 20.0; diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index 8283018dd6ac..eff9a773051e 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -122,7 +122,10 @@ class CSourceBase_TurbSA : public CNumerics { /*--- Dacles-Mariani et. al. rotation correction ("-R"). ---*/ if (options.rot) { - var.Omega += 2.0 * min(0.0, StrainMag_i - var.Omega); + // const su2double Crot = 2.0; // Orig + const su2double Crot = 1.0; // HLPW-5 + var.Omega += Crot * min(0.0, StrainMag_i - var.Omega); + if(ScalarVar_i[0] < 0 ) var.Omega = abs(var.Omega); } if (dist_i > 1e-10) { @@ -832,7 +835,7 @@ class CSourcePieceWise_TurbSST final : public CNumerics { if (config->GetKind_Trans_Model() == TURB_TRANS_MODEL::LM) { pk = pk * eff_intermittency; // Check if the Prod_lim_k has to be introduced based on input options - if ((config->GetLMParsedOptions()).SLM) { + if ((config->GetLMParsedOptions()).SLM && (config->GetLMParsedOptions()).Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) { const su2double Re_theta_c_lim = 1100.0; const su2double C_k = 1.0; const su2double C_SEP = 1.0; diff --git a/SU2_CFD/src/SU2_CFD.cpp b/SU2_CFD/src/SU2_CFD.cpp index a6a6a92f69c7..6e4fb584cead 100644 --- a/SU2_CFD/src/SU2_CFD.cpp +++ b/SU2_CFD/src/SU2_CFD.cpp @@ -33,7 +33,7 @@ #endif /* Include file, needed for the runtime NaN catching. You also have to include feenableexcept(...) below. */ -//#include +#include using namespace std; @@ -75,6 +75,7 @@ int main(int argc, char *argv[]) { /*--- Uncomment the following line if runtime NaN catching is desired. ---*/ // feenableexcept(FE_INVALID | FE_OVERFLOW | FE_DIVBYZERO ); + feenableexcept(FE_OVERFLOW | FE_DIVBYZERO ); /*--- Initialize libxsmm, if supported. ---*/ #ifdef HAVE_LIBXSMM diff --git a/SU2_CFD/src/output/CFlowIncOutput.cpp b/SU2_CFD/src/output/CFlowIncOutput.cpp index c98685c50583..794bca81cb6f 100644 --- a/SU2_CFD/src/output/CFlowIncOutput.cpp +++ b/SU2_CFD/src/output/CFlowIncOutput.cpp @@ -210,6 +210,7 @@ void CFlowIncOutput::LoadHistoryData(CConfig *config, CGeometry *geometry, CSolv SetHistoryOutputValue("MAX_PRESSURE", log10(flow_solver->GetRes_Max(0))); SetHistoryOutputValue("MAX_VELOCITY-X", log10(flow_solver->GetRes_Max(1))); + cout << flow_solver->GetRes_Max(2) << endl; SetHistoryOutputValue("MAX_VELOCITY-Y", log10(flow_solver->GetRes_Max(2))); if (nDim == 3) SetHistoryOutputValue("RMS_VELOCITY-Z", log10(flow_solver->GetRes_Max(3))); diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index 0ba43a94a989..5808e8d500ae 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -1079,17 +1079,18 @@ void CFlowOutput::SetVolumeOutputFields_ScalarSolution(const CConfig* config){ AddVolumeOutput("F_ONSET", "LM_F_onset", "DEBUG", "LM F_ONSET"); AddVolumeOutput("STRAINMAG", "StrainMag", "DEBUG", "LM STRAINMAG"); AddVolumeOutput("LAMBDA_THETA", "Lambda_theta", "DEBUG", "LM Lambda_theta"); - AddVolumeOutput("DU_DS", "du_ds", "DEBUG", "LM du_ds"); + AddVolumeOutput("DU_DS", "du_ds", "DEBUG", "LM du_ds"); if ((config->GetLMParsedOptions()).SLM) { AddVolumeOutput("TU", "Tu", "SOLUTION", "LM Tu"); AddVolumeOutput("NORMAL_X", "Normal_x", "DEBUG", "LM Normal_x"); AddVolumeOutput("NORMAL_Y", "Normal_y", "DEBUG", "LM Normal_y"); AddVolumeOutput("NORMAL_Z", "Normal_z", "DEBUG", "LM Normal_z"); - if (TurbModelFamily(config->GetKind_Turb_Model()) == TURB_FAMILY::SA) { + if (!((config->GetLMParsedOptions()).Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM)) { AddVolumeOutput("INTERMITTENCY_SEP", "LM_gamma_sep", "PRIMITIVE", "LM intermittency"); AddVolumeOutput("INTERMITTENCY_EFF", "LM_gamma_eff", "PRIMITIVE", "LM RE_THETA_T"); } } + if (!(config->GetLMParsedOptions()).SLM) { AddVolumeOutput("INTERMITTENCY_SEP", "LM_gamma_sep", "PRIMITIVE", "LM intermittency"); AddVolumeOutput("INTERMITTENCY_EFF", "LM_gamma_eff", "PRIMITIVE", "LM RE_THETA_T"); @@ -1266,7 +1267,7 @@ void CFlowOutput::LoadVolumeData_Scalar(const CConfig* config, const CSolver* co SetVolumeOutputValue("NORMAL_X", iPoint, (Node_Trans->GetNormal(iPoint)).first); SetVolumeOutputValue("NORMAL_Y", iPoint, (Node_Trans->GetNormal(iPoint)).second); SetVolumeOutputValue("NORMAL_Z", iPoint, 0.0); - if (TurbModelFamily(config->GetKind_Turb_Model()) == TURB_FAMILY::SA) { + if (!((config->GetLMParsedOptions()).Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM)) { SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); } diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index a7eda1086c20..b831af93e47f 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -74,7 +74,7 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh isSepNeeded = true; // If the Simplified model is used coupled with SST then we do not need the separation induced intermittency // due to the added production term to k equation - if (options.SLM && TurbFamily == TURB_FAMILY::KW) isSepNeeded = false; + if (options.SLM && options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) isSepNeeded = false; /*--- Single grid simulation ---*/ @@ -199,86 +199,6 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain if (options.SLM && options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) { - /*--- Reconstructon of auxiliary variables gradient ---*/ - - // Each rank collects all normals - - // vector>> WallNormal; - // WallNormal.resize(config->GetnMarker_All()); - // for (auto iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++){ - // if (config->GetViscous_Wall(iMarker)) { - // WallNormal[iMarker].resize(geometry->GetnElem_Bound(iMarker)); - - // // cout << "geometry->nVertex[iMarker] = " << geometry->nVertex[iMarker] << endl; - // for (auto iElem = 0u; iElem < geometry->GetnElem_Bound(iMarker); iElem++) { - // vector NormalHere(nDim, 0.0); - - // for (unsigned short iNode = 0; iNode < geometry->bound[iMarker][iElem]->GetnNodes(); iNode++) { - // // Extract global coordinate of the node - // unsigned long iPointHere = geometry->bound[iMarker][iElem]->GetNode(iNode); - // long iVertexHere = geometry->nodes->GetVertex(iPointHere, iMarker); - // for (auto iDim = 0u; iDim < nDim; iDim++) - // NormalHere[iDim] += geometry->vertex[iMarker][iElem]->GetNormal(iDim); - // } - - // for (auto iDim = 0u; iDim < nDim; iDim++) - // NormalHere[iDim] /= geometry->bound[iMarker][iElem]->GetnNodes(); - - // su2double NormalMag = 0.0; - // for (auto iDim = 0u; iDim < nDim; iDim++) - // NormalMag += NormalHere[iDim]*NormalHere[iDim]; - // NormalMag = sqrt(NormalMag); - - // for (auto iDim = 0u; iDim < nDim; iDim++) - // NormalHere[iDim] /= NormalMag; - - // WallNormal[iMarker][iElem] = NormalHere; - // } - // } else { - // WallNormal[iMarker].resize(1); - // WallNormal[iMarker][0].resize(3); - // WallNormal[iMarker][0][0] = 0.0; - // WallNormal[iMarker][0][1] = 0.0; - // WallNormal[iMarker][0][2] = 0.0; - // } - // } - - // auto normal_i = - // make_pair( config->GetnMarker_All(), [config,geometry,WallNormal](unsigned long iMarker){ - // auto nElem_Bou = geometry->GetnElem_Bound(iMarker); - // if (!config->GetViscous_Wall(iMarker)) nElem_Bou = 1; - - // return make_pair(nElem_Bou, [WallNormal,iMarker](unsigned long iElem){ - // const auto dimensions = 3; - - // return make_pair(dimensions, [WallNormal,iMarker,iElem](unsigned short iDim){ - - // return WallNormal[iMarker][iElem][iDim]; - // }); - // }); - // }); - - // NdFlattener<3>Normals_Local(normal_i); - // NdFlattener<4> Normals_global(Nd_MPI_Environment(), Normals_Local); - // su2double** NormalPerPoint = new su2double* [nPoint]; - - // auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); - // SU2_OMP_FOR_STAT(omp_chunk_size) - // for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { - - // // Extract nearest wall element and wall marker - // int NearestWallRank = geometry->nodes->GetClosestWall_Rank(iPoint); - // unsigned long NearestWallElement = geometry->nodes->GetClosestWall_Elem(iPoint); - // unsigned short NearestWallMarker = geometry->nodes->GetClosestWall_Marker(iPoint); - - // NormalPerPoint[iPoint] = new su2double [MAXNDIM]; - // for(auto iDim = 0; iDim < nDim; iDim++) - // NormalPerPoint[iPoint][iDim] = Normals_global[NearestWallRank][NearestWallMarker][NearestWallElement][iDim]; - - // nodes->SetAuxVar(iPoint, 0, flowNodes->GetProjVel(iPoint, NormalPerPoint[iPoint])); - // nodes->SetNormal(iPoint, NormalPerPoint[iPoint][0], NormalPerPoint[iPoint][1]); - // } - // END_SU2_OMP_FOR auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); SU2_OMP_FOR_STAT(omp_chunk_size) @@ -345,10 +265,7 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai StrainMag = max(StrainMag, 1e-12); // safety against division by zero const su2double Intermittency = nodes->GetSolution(iPoint,0); const su2double Re_v = rho*dist*dist*StrainMag/mu; - const su2double vel_u = flowNodes->GetVelocity(iPoint, 0); - const su2double vel_v = flowNodes->GetVelocity(iPoint, 1); - const su2double vel_w = (nDim ==3) ? flowNodes->GetVelocity(iPoint, 2) : 0.0; - const su2double VelocityMag = sqrt(vel_u*vel_u + vel_v*vel_v + vel_w*vel_w); + const su2double VelocityMag = max(sqrt(flowNodes->GetVelocity2(iPoint)), 1e-20); su2double omega = 0.0; su2double k = 0.0; if(TurbFamily == TURB_FAMILY::KW){ @@ -359,7 +276,7 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai su2double Re_t = 0.0; su2double Corr_Rec = 0.0; - if (options.SLM && TurbFamily == TURB_FAMILY::SA) { + if (options.SLM) { Re_t = nodes->GetRe_t(iPoint); Corr_Rec = nodes->GetCorr_Rec(iPoint); } else { diff --git a/SU2_CFD/src/solvers/CTurbSASolver.cpp b/SU2_CFD/src/solvers/CTurbSASolver.cpp index 30d7308cd2ed..8d0855dbe4f7 100644 --- a/SU2_CFD/src/solvers/CTurbSASolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSASolver.cpp @@ -269,7 +269,7 @@ void CTurbSASolver::Postprocessing(CGeometry *geometry, CSolver **solver_contain } shearStress = sqrt(shearStress); - FrictionVelocity = sqrt(shearStress/flowNodes->GetDensity(iPoint)); + FrictionVelocity = sqrt(shearStress/max(flowNodes->GetDensity(iPoint), 1e-20)); } else { su2double VorticityMag = max(GeometryToolbox::Norm(3, flowNodes->GetVorticity(iPoint)), 1e-12); FrictionVelocity = sqrt(flowNodes->GetLaminarViscosity(iPoint)*VorticityMag); @@ -277,7 +277,7 @@ void CTurbSASolver::Postprocessing(CGeometry *geometry, CSolver **solver_contain const su2double wall_dist = geometry->nodes->GetWall_Distance(jPoint); const su2double Derivative = nodes->GetSolution(jPoint, 0) / wall_dist; - const su2double turbulence_index = Derivative / (FrictionVelocity * 0.41); + const su2double turbulence_index = Derivative / max((FrictionVelocity * 0.41), 1e-20); nodes->SetTurbIndex(iPoint, turbulence_index); diff --git a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp index c2f1983cd73c..d0e26a43153d 100644 --- a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp @@ -259,10 +259,10 @@ void CTurbSSTSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai } shearStress = sqrt(shearStress); - const su2double FrictionVelocity = sqrt(shearStress/flowNodes->GetDensity(iPoint)); + const su2double FrictionVelocity = sqrt(shearStress/max(flowNodes->GetDensity(iPoint),1e-20)); const su2double wall_dist = geometry->nodes->GetWall_Distance(jPoint); const su2double Derivative = flowNodes->GetLaminarViscosity(jPoint) * pow(nodes->GetSolution(jPoint, 0), 0.673) / wall_dist; - const su2double turbulence_index = 6.1 * Derivative / pow(FrictionVelocity, 2.346); + const su2double turbulence_index = 6.1 * Derivative / max(pow(FrictionVelocity, 2.346),1e-20); nodes->SetTurbIndex(iPoint, turbulence_index); From c4615188e5718f3f44b0e5cf7a72032bd51f3fdf Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 27 Apr 2023 10:08:30 +0200 Subject: [PATCH 11/61] Removing changes for SA-R --- SU2_CFD/include/numerics/turbulent/turb_sources.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index eff9a773051e..999e1dad3ef3 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -122,10 +122,7 @@ class CSourceBase_TurbSA : public CNumerics { /*--- Dacles-Mariani et. al. rotation correction ("-R"). ---*/ if (options.rot) { - // const su2double Crot = 2.0; // Orig - const su2double Crot = 1.0; // HLPW-5 - var.Omega += Crot * min(0.0, StrainMag_i - var.Omega); - if(ScalarVar_i[0] < 0 ) var.Omega = abs(var.Omega); + var.Omega += 2.0 * min(0.0, StrainMag_i - var.Omega); } if (dist_i > 1e-10) { From e68a9e47c4d6d8a026156500478e33908e2cda6a Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 27 Apr 2023 12:12:09 +0200 Subject: [PATCH 12/61] Fixed vertex indexing for wall normal computation --- Common/src/geometry/CGeometry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/geometry/CGeometry.cpp b/Common/src/geometry/CGeometry.cpp index c5436b8930d0..db8772f464bc 100644 --- a/Common/src/geometry/CGeometry.cpp +++ b/Common/src/geometry/CGeometry.cpp @@ -4128,7 +4128,7 @@ void CGeometry::ComputeWallDistance(const CConfig* const* config_container, CGeo unsigned long iPointHere = geometry->bound[iMarker][iElem]->GetNode(iNode); long iVertexHere = geometry->nodes->GetVertex(iPointHere, iMarker); for (auto iDim = 0u; iDim < 3; iDim++) - NormalHere[iDim] += geometry->vertex[iMarker][iElem]->GetNormal(iDim); + NormalHere[iDim] += geometry->vertex[iMarker][iVertexHere]->GetNormal(iDim); } for (auto iDim = 0u; iDim < 3; iDim++) From bcdd671de3903c7ba1bfad0aed72a2ae620c78ff Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 27 Apr 2023 12:19:37 +0200 Subject: [PATCH 13/61] Removed a cout --- SU2_CFD/src/output/CFlowIncOutput.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/SU2_CFD/src/output/CFlowIncOutput.cpp b/SU2_CFD/src/output/CFlowIncOutput.cpp index 794bca81cb6f..c98685c50583 100644 --- a/SU2_CFD/src/output/CFlowIncOutput.cpp +++ b/SU2_CFD/src/output/CFlowIncOutput.cpp @@ -210,7 +210,6 @@ void CFlowIncOutput::LoadHistoryData(CConfig *config, CGeometry *geometry, CSolv SetHistoryOutputValue("MAX_PRESSURE", log10(flow_solver->GetRes_Max(0))); SetHistoryOutputValue("MAX_VELOCITY-X", log10(flow_solver->GetRes_Max(1))); - cout << flow_solver->GetRes_Max(2) << endl; SetHistoryOutputValue("MAX_VELOCITY-Y", log10(flow_solver->GetRes_Max(2))); if (nDim == 3) SetHistoryOutputValue("RMS_VELOCITY-Z", log10(flow_solver->GetRes_Max(3))); From 9bb243599b99b9c12b8698b7c53861921d400525 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 27 Apr 2023 12:41:08 +0200 Subject: [PATCH 14/61] Fixed division by zero with Corr_Rec --- SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp | 2 +- SU2_CFD/src/solvers/CTransLMSolver.cpp | 1 + SU2_CFD/src/variables/CTransLMVariable.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index 0dae2e76c0ef..97b00174fdaa 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -397,7 +397,7 @@ class CSourcePieceWise_TransSLM final : public CNumerics { su2double IntermittencyEff = 1.0; su2double Re_t; - su2double Corr_Rec; + su2double Corr_Rec = 1.0; su2double AuxVar; su2double F2; su2double Tu_Here = 0.0; diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index b831af93e47f..3bd90c72b87e 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -291,6 +291,7 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai } + // cout << Re_t << " " << Corr_Rec << endl; // if (geometry->nodes->GetDomain(iPoint)) cout << "Point is on boundary" << endl; diff --git a/SU2_CFD/src/variables/CTransLMVariable.cpp b/SU2_CFD/src/variables/CTransLMVariable.cpp index bcc72b3af70b..d5de642adc39 100644 --- a/SU2_CFD/src/variables/CTransLMVariable.cpp +++ b/SU2_CFD/src/variables/CTransLMVariable.cpp @@ -66,7 +66,7 @@ CTransLMVariable::CTransLMVariable(su2double Intermittency, su2double ReThetaT, Re_v.resize(nPoint) = 0.0; - Corr_Rec.resize(nPoint) = 0.0; + Corr_Rec.resize(nPoint) = 1.0; Prod.resize(nPoint) = 0.0; Destr.resize(nPoint) = 0.0; F_onset1.resize(nPoint) = 0.0; From a9a6ce48e8619402b1763d811425846a17d2f432 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 27 Apr 2023 14:07:03 +0200 Subject: [PATCH 15/61] Removed cout --- .../include/numerics/turbulent/transition/trans_sources.hpp | 6 +++--- SU2_CFD/src/solvers/CTransLMSolver.cpp | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index 97b00174fdaa..2a134d3f99e9 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -552,9 +552,9 @@ class CSourcePieceWise_TransSLM final : public CNumerics { const su2double k = 0.25 - lambda_theta; const su2double FirstTerm = 4.14 * k; const su2double SecondTerm = 83.5 * pow(k, 2.0); - const su2double ThirdTerm = 854 * pow(k, 3.0); - const su2double ForthTerm = 3337 * pow(k, 4.0); - const su2double FifthTerm = 4576 * pow(k, 5.0); + const su2double ThirdTerm = 854.0 * pow(k, 3.0); + const su2double ForthTerm = 3337.0 * pow(k, 4.0); + const su2double FifthTerm = 4576.0 * pow(k, 5.0); const su2double H = min(2.0 + FirstTerm - SecondTerm + ThirdTerm - ForthTerm + FifthTerm, 2.7); // Computation of critical cross flow Reynolds number diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 3bd90c72b87e..b831af93e47f 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -291,7 +291,6 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai } - // cout << Re_t << " " << Corr_Rec << endl; // if (geometry->nodes->GetDomain(iPoint)) cout << "Point is on boundary" << endl; From 86b068c00f85be0943d6d5700ff7972bb20d3122 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 27 Apr 2023 14:22:19 +0200 Subject: [PATCH 16/61] Fixed Max Velocity-Z output for Incompressible flow --- SU2_CFD/src/output/CFlowIncOutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/output/CFlowIncOutput.cpp b/SU2_CFD/src/output/CFlowIncOutput.cpp index c98685c50583..87783ca9bc76 100644 --- a/SU2_CFD/src/output/CFlowIncOutput.cpp +++ b/SU2_CFD/src/output/CFlowIncOutput.cpp @@ -211,7 +211,7 @@ void CFlowIncOutput::LoadHistoryData(CConfig *config, CGeometry *geometry, CSolv SetHistoryOutputValue("MAX_PRESSURE", log10(flow_solver->GetRes_Max(0))); SetHistoryOutputValue("MAX_VELOCITY-X", log10(flow_solver->GetRes_Max(1))); SetHistoryOutputValue("MAX_VELOCITY-Y", log10(flow_solver->GetRes_Max(2))); - if (nDim == 3) SetHistoryOutputValue("RMS_VELOCITY-Z", log10(flow_solver->GetRes_Max(3))); + if (nDim == 3) SetHistoryOutputValue("MAX_VELOCITY-Z", log10(flow_solver->GetRes_Max(3))); if (multiZone){ SetHistoryOutputValue("BGS_PRESSURE", log10(flow_solver->GetRes_BGS(0))); From 73c0a4b40ca64266dd9bb914e745524afbc2538b Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 27 Apr 2023 15:14:21 +0200 Subject: [PATCH 17/61] Fixed output of Normals in volume --- SU2_CFD/include/variables/CTransLMVariable.hpp | 7 +++++-- SU2_CFD/include/variables/CVariable.hpp | 6 ++++-- SU2_CFD/src/output/CFlowOutput.cpp | 6 +++--- SU2_CFD/src/solvers/CTransLMSolver.cpp | 2 +- SU2_CFD/src/variables/CTransLMVariable.cpp | 4 +++- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/SU2_CFD/include/variables/CTransLMVariable.hpp b/SU2_CFD/include/variables/CTransLMVariable.hpp index 8478b84d5502..84e15f2dccbd 100644 --- a/SU2_CFD/include/variables/CTransLMVariable.hpp +++ b/SU2_CFD/include/variables/CTransLMVariable.hpp @@ -55,6 +55,7 @@ class CTransLMVariable final : public CTurbVariable { VectorType normal_x; VectorType normal_y; + VectorType normal_z; public: /*! @@ -104,7 +105,7 @@ class CTransLMVariable final : public CTurbVariable { void SetF_onset2(unsigned long iPoint, su2double val_F_onset2) override; void SetF_onset3(unsigned long iPoint, su2double val_F_onset3) override; void SetF_onset(unsigned long iPoint, su2double val_F_onset) override; - void SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y) override; + void SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y, su2double val_normal_z) override; /*! * \brief Calculate effective intermittency. @@ -135,5 +136,7 @@ class CTransLMVariable final : public CTurbVariable { inline su2double GetF_onset2(unsigned long iPoint) const override { return F_onset2(iPoint); } inline su2double GetF_onset3(unsigned long iPoint) const override { return F_onset3(iPoint); } inline su2double GetF_onset(unsigned long iPoint) const override { return F_onset(iPoint); } - inline pair GetNormal(unsigned long iPoint) const override {return make_pair(normal_x(iPoint), normal_y(iPoint));}; + inline su2double GetNormal_x(unsigned long iPoint) const override {return normal_x(iPoint);}; + inline su2double GetNormal_y(unsigned long iPoint) const override {return normal_y(iPoint);}; + inline su2double GetNormal_z(unsigned long iPoint) const override {return normal_z(iPoint);}; }; diff --git a/SU2_CFD/include/variables/CVariable.hpp b/SU2_CFD/include/variables/CVariable.hpp index 9fb1cac05566..726e81112be8 100644 --- a/SU2_CFD/include/variables/CVariable.hpp +++ b/SU2_CFD/include/variables/CVariable.hpp @@ -1727,7 +1727,7 @@ class CVariable { inline virtual void SetF_onset2(unsigned long iPoint, su2double val_F_onset2) {}; inline virtual void SetF_onset3(unsigned long iPoint, su2double val_F_onset3) {}; inline virtual void SetF_onset(unsigned long iPoint, su2double val_F_onset1) {}; - inline virtual void SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y) {}; + inline virtual void SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y, su2double val_normal_z) {}; /*! * \brief Get Value of Transition Momentum Thickness Reynolds number from correlations. @@ -1743,7 +1743,9 @@ class CVariable { inline virtual su2double GetF_onset2(unsigned long iPoint) const { return 0.0; } inline virtual su2double GetF_onset3(unsigned long iPoint) const { return 0.0; } inline virtual su2double GetF_onset(unsigned long iPoint) const { return 0.0; } - inline virtual pair GetNormal(unsigned long iPoint) const { return make_pair(0.0, 0.0); } + inline virtual su2double GetNormal_x(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetNormal_y(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetNormal_z(unsigned long iPoint) const { return 0.0; } /*! * \brief Set Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index 5808e8d500ae..2851d9636f51 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -1264,9 +1264,9 @@ void CFlowOutput::LoadVolumeData_Scalar(const CConfig* config, const CSolver* co } else { SetVolumeOutputValue("RE_THETA_T", iPoint, Node_Trans->GetRe_t(iPoint)); SetVolumeOutputValue("TU", iPoint, Node_Trans->GetTu(iPoint)); - SetVolumeOutputValue("NORMAL_X", iPoint, (Node_Trans->GetNormal(iPoint)).first); - SetVolumeOutputValue("NORMAL_Y", iPoint, (Node_Trans->GetNormal(iPoint)).second); - SetVolumeOutputValue("NORMAL_Z", iPoint, 0.0); + SetVolumeOutputValue("NORMAL_X", iPoint, Node_Trans->GetNormal_x(iPoint)); + SetVolumeOutputValue("NORMAL_Y", iPoint, Node_Trans->GetNormal_y(iPoint)); + SetVolumeOutputValue("NORMAL_Z", iPoint, Node_Trans->GetNormal_z(iPoint)); if (!((config->GetLMParsedOptions()).Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM)) { SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index b831af93e47f..d0f8eeaf11df 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -205,7 +205,7 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { auto Normal = geometry->nodes->GetNormal(iPoint); nodes->SetAuxVar(iPoint, 0, flowNodes->GetProjVel(iPoint, Normal)); - nodes->SetNormal(iPoint, Normal[0], Normal[1]); + nodes->SetNormal(iPoint, Normal[0], Normal[1], Normal[2]); } END_SU2_OMP_FOR diff --git a/SU2_CFD/src/variables/CTransLMVariable.cpp b/SU2_CFD/src/variables/CTransLMVariable.cpp index d5de642adc39..405e2fea9a09 100644 --- a/SU2_CFD/src/variables/CTransLMVariable.cpp +++ b/SU2_CFD/src/variables/CTransLMVariable.cpp @@ -62,6 +62,7 @@ CTransLMVariable::CTransLMVariable(su2double Intermittency, su2double ReThetaT, normal_x.resize(nPoint) = 0.0; normal_y.resize(nPoint) = 0.0; + normal_z.resize(nPoint) = 0.0; } @@ -127,7 +128,8 @@ void CTransLMVariable::SetF_onset3(unsigned long iPoint, su2double val_F_onset3) void CTransLMVariable::SetF_onset(unsigned long iPoint, su2double val_F_onset) { F_onset(iPoint) = val_F_onset; } -void CTransLMVariable::SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y) { +void CTransLMVariable::SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y, su2double val_normal_z) { normal_x(iPoint) = val_normal_x; normal_y(iPoint) = val_normal_y; + normal_z(iPoint) = val_normal_z; } \ No newline at end of file From 8d5148e1ef5d18483fa28aa42ec82a21116fecae Mon Sep 17 00:00:00 2001 From: rois1995 Date: Mon, 1 Jul 2024 10:55:41 +0200 Subject: [PATCH 18/61] - Added Simplified Langtry Menter model --- Common/include/geometry/dual_grid/CPoint.hpp | 57 +++ Common/include/option_structure.hpp | 74 +++- Common/src/CConfig.cpp | 33 +- Common/src/geometry/CGeometry.cpp | 75 ++++ Common/src/geometry/dual_grid/CPoint.cpp | 2 + SU2_CFD/include/numerics/CNumerics.hpp | 35 ++ .../turbulent/transition/trans_convection.hpp | 7 + .../transition/trans_correlations.hpp | 105 ++++++ .../turbulent/transition/trans_diffusion.hpp | 68 ++++ .../turbulent/transition/trans_sources.hpp | 332 +++++++++++++++++- .../numerics/turbulent/turb_sources.hpp | 12 + SU2_CFD/include/solvers/CTransLMSolver.hpp | 1 + .../include/variables/CTransLMVariable.hpp | 61 ++++ .../include/variables/CTurbSSTVariable.hpp | 1 + SU2_CFD/include/variables/CVariable.hpp | 45 +++ SU2_CFD/src/drivers/CDriver.cpp | 22 +- SU2_CFD/src/output/CFlowIncOutput.cpp | 2 +- SU2_CFD/src/output/CFlowOutput.cpp | 92 ++++- SU2_CFD/src/solvers/CTransLMSolver.cpp | 236 +++++++++---- SU2_CFD/src/solvers/CTurbSASolver.cpp | 2 +- SU2_CFD/src/solvers/CTurbSSTSolver.cpp | 4 +- SU2_CFD/src/variables/CTransLMVariable.cpp | 85 ++++- SU2_CFD/src/variables/CTurbSSTVariable.cpp | 1 + 23 files changed, 1236 insertions(+), 116 deletions(-) diff --git a/Common/include/geometry/dual_grid/CPoint.hpp b/Common/include/geometry/dual_grid/CPoint.hpp index 9c73fdeaa9af..a2cc83c04cd6 100644 --- a/Common/include/geometry/dual_grid/CPoint.hpp +++ b/Common/include/geometry/dual_grid/CPoint.hpp @@ -112,6 +112,7 @@ class CPoint { su2activevector Curvature; /*!< \brief Value of the surface curvature (SU2_GEO). */ su2activevector MaxLength; /*!< \brief The maximum cell-center to cell-center length. */ su2activevector RoughnessHeight; /*!< \brief Roughness of the nearest wall. */ + su2activematrix Normals; /*!< \brief Normal of the nearest wall element. */ su2matrix AD_InputIndex; /*!< \brief Indices of Coord variables in the adjoint vector. */ su2matrix @@ -494,6 +495,27 @@ class CPoint { inline su2double& GetWall_Distance(unsigned long iPoint) { return Wall_Distance(iPoint); } inline const su2double& GetWall_Distance(unsigned long iPoint) const { return Wall_Distance(iPoint); } + /*! + * \brief Get the index of the closest wall element. + * \param[in] iPoint - Index of the point. + * \param[out] ClosestWall_Elem - ID of the closest element on a wall boundary. + */ + inline unsigned long GetClosestWall_Elem(unsigned long iPoint) {return ClosestWall_Elem(iPoint);} + + /*! + * \brief Get the marker of the closest wall marker. + * \param[in] iPoint - Index of the point. + * \param[out] ClosestWall_Marker - MarkerID of the closest wall boundary. + */ + inline unsigned long GetClosestWall_Marker(unsigned long iPoint) {return ClosestWall_Marker(iPoint);} + + /*! + * \brief Get the rank of the closest wall marker. + * \param[in] iPoint - Index of the point. + * \param[out] ClosestWall_Rank - RankID of the closest wall boundary. + */ + inline unsigned long GetClosestWall_Rank(unsigned long iPoint) {return ClosestWall_Rank(iPoint);} + /*! * \brief Set the value of the distance to the nearest wall. * \param[in] iPoint - Index of the point. @@ -508,6 +530,24 @@ class CPoint { */ inline su2double GetRoughnessHeight(unsigned long iPoint) const { return RoughnessHeight(iPoint); } + /*! + * \brief Set the value of the normal of the nearest wall element. + * \param[in] iPoint - Index of the point. + * \param[in] normal - Value of the normal. + */ + template + inline void SetNormal(unsigned long iPoint, Normals_type const&normal) { + for (unsigned long iDim = 0; iDim < nDim; iDim++) + Normals(iPoint,iDim) = normal[iDim]; + } + + /*! + * \brief Set the value of the normal of the nearest wall element. + * \param[in] iPoint - Index of the point. + * \return normal to the normal of the nearest wall element. + */ + inline su2double *GetNormal(unsigned long iPoint) { return Normals[iPoint]; } + /*! * \brief Set the value of the distance to a sharp edge. * \param[in] iPoint - Index of the point. @@ -908,4 +948,21 @@ class CPoint { } } } + + /*! + * \brief Set wall normal according to stored closest wall information. + * \param[in] normals - Mapping [rank][zone][marker][element] -> normal + */ + template + void SetWallNormals(Normals_type const&normals){ + for (unsigned long iPoint=0; iPoint= 0) + SetNormal(iPoint, normals[rankID][zoneID][markerID][elementID]); + } + } + }; diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp index 9bbe613c4bc2..605cb49ca178 100644 --- a/Common/include/option_structure.hpp +++ b/Common/include/option_structure.hpp @@ -1189,27 +1189,37 @@ static const MapType Trans_Model_Map = { * \brief LM Options */ enum class LM_OPTIONS { - NONE, /*!< \brief No option / default. */ - LM2015, /*!< \brief Cross-flow corrections. */ - MALAN, /*!< \brief Kind of transition correlation model (Malan). */ - SULUKSNA, /*!< \brief Kind of transition correlation model (Suluksna). */ - KRAUSE, /*!< \brief Kind of transition correlation model (Krause). */ - KRAUSE_HYPER, /*!< \brief Kind of transition correlation model (Krause hypersonic). */ - MEDIDA_BAEDER,/*!< \brief Kind of transition correlation model (Medida-Baeder). */ - MEDIDA, /*!< \brief Kind of transition correlation model (Medida). */ - MENTER_LANGTRY, /*!< \brief Kind of transition correlation model (Menter-Langtry). */ - DEFAULT /*!< \brief Kind of transition correlation model (Menter-Langtry if SST, MALAN if SA). */ + NONE, /*!< \brief No option / default. */ + CROSSFLOW, /*!< \brief Cross-flow corrections. */ + SLM, /*!< \brief Simplified version. */ + PRODLIM, /*!< \brief Add production term to Pk. */ + MALAN, /*!< \brief Kind of transition correlation model (Malan). */ + SULUKSNA, /*!< \brief Kind of transition correlation model (Suluksna). */ + KRAUSE, /*!< \brief Kind of transition correlation model (Krause). */ + KRAUSE_HYPER, /*!< \brief Kind of transition correlation model (Krause hypersonic). */ + MEDIDA_BAEDER, /*!< \brief Kind of transition correlation model (Medida-Baeder). */ + MEDIDA, /*!< \brief Kind of transition correlation model (Medida). */ + MENTER_LANGTRY, /*!< \brief Kind of transition correlation model (Menter-Langtry). */ + MENTER_SLM, /*!< \brief Kind of transition correlation model (Menter Simplified LM model). */ + CODER_SLM, /*!< \brief Kind of transition correlation model (Coder Simplified LM model). */ + MOD_EPPLER_SLM, /*!< \brief Kind of transition correlation model (Modified Eppler Simplified LM model). */ + DEFAULT /*!< \brief Kind of transition correlation model (Menter-Langtry if SST, MALAN if SA). */ }; static const MapType LM_Options_Map = { MakePair("NONE", LM_OPTIONS::NONE) - MakePair("LM2015", LM_OPTIONS::LM2015) + MakePair("CROSSFLOW", LM_OPTIONS::CROSSFLOW) + MakePair("SLM", LM_OPTIONS::SLM) + MakePair("PRODLIM", LM_OPTIONS::PRODLIM) MakePair("MALAN", LM_OPTIONS::MALAN) MakePair("SULUKSNA", LM_OPTIONS::SULUKSNA) MakePair("KRAUSE", LM_OPTIONS::KRAUSE) MakePair("KRAUSE_HYPER", LM_OPTIONS::KRAUSE_HYPER) MakePair("MEDIDA_BAEDER", LM_OPTIONS::MEDIDA_BAEDER) MakePair("MENTER_LANGTRY", LM_OPTIONS::MENTER_LANGTRY) + MakePair("MENTER_SLM", LM_OPTIONS::MENTER_SLM) + MakePair("CODER_SLM", LM_OPTIONS::CODER_SLM) + MakePair("MOD_EPPLER_SLM", LM_OPTIONS::MOD_EPPLER_SLM) MakePair("DEFAULT", LM_OPTIONS::DEFAULT) }; @@ -1227,13 +1237,26 @@ enum class TURB_TRANS_CORRELATION { DEFAULT /*!< \brief Kind of transition correlation model (Menter-Langtry if SST, MALAN if SA). */ }; +/*! + * \brief Types of transition correlations for Simplified LM model + */ +enum class TURB_TRANS_CORRELATION_SLM { + MENTER_SLM, /*!< \brief Kind of transition correlation model (Menter Simplified LM model). */ + CODER_SLM, /*!< \brief Kind of transition correlation model (Coder Simplified LM model). */ + MOD_EPPLER_SLM, /*!< \brief Kind of transition correlation model (Modified Eppler Simplified LM model). */ + DEFAULT /*!< \brief Kind of transition correlation model. */ +}; + /*! * \brief Structure containing parsed LM options. */ struct LM_ParsedOptions { LM_OPTIONS version = LM_OPTIONS::NONE; /*!< \brief LM base model. */ - bool LM2015 = false; /*!< \brief Use cross-flow corrections. */ + bool SLM = false; /*!< \brief Use simplified version. */ + bool ProdLim = false; /*!< \brief Add production term to Pk. */ + bool CrossFlow = false; /*!< \brief Use cross-flow corrections. */ TURB_TRANS_CORRELATION Correlation = TURB_TRANS_CORRELATION::DEFAULT; + TURB_TRANS_CORRELATION_SLM Correlation_SLM = TURB_TRANS_CORRELATION_SLM::DEFAULT; }; /*! @@ -1251,7 +1274,10 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh return std::find(LM_Options, lm_options_end, option) != lm_options_end; }; - LMParsedOptions.LM2015 = IsPresent(LM_OPTIONS::LM2015); + LMParsedOptions.SLM = IsPresent(LM_OPTIONS::SLM); + LMParsedOptions.ProdLim = IsPresent(LM_OPTIONS::PRODLIM); + + LMParsedOptions.CrossFlow = IsPresent(LM_OPTIONS::CROSSFLOW); int NFoundCorrelations = 0; if (IsPresent(LM_OPTIONS::MALAN)) { @@ -1287,6 +1313,24 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh SU2_MPI::Error("Two correlations selected for LM_OPTIONS. Please choose only one.", CURRENT_FUNCTION); } + int NFoundCorrelations_SLM = 0; + if (IsPresent(LM_OPTIONS::MENTER_SLM)) { + LMParsedOptions.Correlation_SLM = TURB_TRANS_CORRELATION_SLM::MENTER_SLM; + NFoundCorrelations_SLM++; + } + if (IsPresent(LM_OPTIONS::CODER_SLM)) { + LMParsedOptions.Correlation_SLM = TURB_TRANS_CORRELATION_SLM::CODER_SLM; + NFoundCorrelations_SLM++; + } + if (IsPresent(LM_OPTIONS::MOD_EPPLER_SLM)) { + LMParsedOptions.Correlation_SLM = TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM; + NFoundCorrelations_SLM++; + } + + if (NFoundCorrelations_SLM > 1) { + SU2_MPI::Error("Two correlations selected for Simplified model into LM_OPTIONS. Please choose only one.", CURRENT_FUNCTION); + } + if (LMParsedOptions.Correlation == TURB_TRANS_CORRELATION::DEFAULT){ if (Kind_Turb_Model == TURB_MODEL::SST) { LMParsedOptions.Correlation = TURB_TRANS_CORRELATION::MENTER_LANGTRY; @@ -1295,6 +1339,10 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh } } + if (LMParsedOptions.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::DEFAULT){ + LMParsedOptions.Correlation_SLM = TURB_TRANS_CORRELATION_SLM::MENTER_SLM; + } + return LMParsedOptions; } diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 5ff351cfee5c..9517aacacdb6 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -3485,7 +3485,7 @@ void CConfig::SetPostprocessing(SU2_COMPONENT val_software, unsigned short val_i lmParsedOptions = ParseLMOptions(LM_Options, nLM_Options, rank, Kind_Turb_Model); /*--- Check if problem is 2D and LM2015 has been selected ---*/ - if (lmParsedOptions.LM2015 && val_nDim == 2) { + if (lmParsedOptions.CrossFlow && val_nDim == 2) { SU2_MPI::Error("LM2015 is available only for 3D problems", CURRENT_FUNCTION); } } @@ -6180,11 +6180,27 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { switch (Kind_Trans_Model) { case TURB_TRANS_MODEL::NONE: break; case TURB_TRANS_MODEL::LM: { - cout << "Transition model: Langtry and Menter's 4 equation model"; - if (lmParsedOptions.LM2015) { - cout << " w/ cross-flow corrections (2015)" << endl; + int NTurbEqs = 0; + switch (Kind_Turb_Model) { + case TURB_MODEL::SA: NTurbEqs = 1; break; + case TURB_MODEL::SST: NTurbEqs = 2; break; + case TURB_MODEL::NONE: SU2_MPI::Error("No turbulence model has been selected but LM transition model is active.", CURRENT_FUNCTION); break; + } + if (!lmParsedOptions.SLM) { + int NEquations = 2; + cout << "Transition model: Langtry and Menter's "<< NEquations+NTurbEqs <<" equation model"; } else { - cout << " (2009)" << endl; + int NEquations = 1; + cout << "Transition model: Simplified Langtry and Menter's "<< NEquations+NTurbEqs <<" equation model"; + } + if (lmParsedOptions.CrossFlow) { + cout << " w/ cross-flow corrections" << endl; + } else { + if (!lmParsedOptions.SLM) { + cout << " (2009)" << endl; + } else { + cout << " (2015)" << endl; + } } break; } @@ -6208,6 +6224,13 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { } break; } + cout << "Correlation Functions for Simplified LM model: "; + switch (lmParsedOptions.Correlation_SLM) { + case TURB_TRANS_CORRELATION_SLM::CODER_SLM: cout << "Coder et al. (2012)" << endl; break; + case TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM: cout << "Modified Eppler (from Coder et al. 2012)" << endl; break; + case TURB_TRANS_CORRELATION_SLM::MENTER_SLM: + case TURB_TRANS_CORRELATION_SLM::DEFAULT: cout << "Menter et al. (2015)" << endl; break; + } } cout << "Hybrid RANS/LES: "; switch (Kind_HybridRANSLES) { diff --git a/Common/src/geometry/CGeometry.cpp b/Common/src/geometry/CGeometry.cpp index bbdbb0316d06..94238a4259b5 100644 --- a/Common/src/geometry/CGeometry.cpp +++ b/Common/src/geometry/CGeometry.cpp @@ -4021,5 +4021,80 @@ void CGeometry::ComputeWallDistance(const CConfig* const* config_container, CGeo } } } + + su2vector>> WallNormal_container; + WallNormal_container.resize(nZone) = su2vector>(); + for (int iZone = 0; iZone < nZone; iZone++){ + const CConfig* config = config_container[iZone]; + const CGeometry* geometry = geometry_container[iZone][iInst][MESH_0]; + WallNormal_container[iZone].resize(geometry->GetnMarker()); + for (auto iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++){ + if (config->GetViscous_Wall(iMarker)) { + WallNormal_container[iZone][iMarker].resize(geometry->GetnElem_Bound(iMarker), 3); + + // cout << "geometry->nVertex[iMarker] = " << geometry->nVertex[iMarker] << endl; + for (auto iElem = 0u; iElem < geometry->GetnElem_Bound(iMarker); iElem++) { + su2vector NormalHere; + NormalHere.resize(3) = su2double(0.0); + + for (unsigned short iNode = 0; iNode < geometry->bound[iMarker][iElem]->GetnNodes(); iNode++) { + // Extract global coordinate of the node + unsigned long iPointHere = geometry->bound[iMarker][iElem]->GetNode(iNode); + long iVertexHere = geometry->nodes->GetVertex(iPointHere, iMarker); + for (auto iDim = 0u; iDim < 3; iDim++) + NormalHere[iDim] += geometry->vertex[iMarker][iVertexHere]->GetNormal(iDim); + } + + for (auto iDim = 0u; iDim < 3; iDim++) + NormalHere[iDim] /= geometry->bound[iMarker][iElem]->GetnNodes(); + + su2double NormalMag = 0.0; + for (auto iDim = 0u; iDim < 3; iDim++) + NormalMag += NormalHere[iDim]*NormalHere[iDim]; + NormalMag = sqrt(NormalMag); + + for (auto iDim = 0u; iDim < 3; iDim++) + NormalHere[iDim] /= NormalMag; + + for (auto iDim = 0u; iDim < 3; iDim++) + WallNormal_container[iZone][iMarker](iElem, iDim) = NormalHere[iDim]; + + } + } else { + WallNormal_container[iZone][iMarker].resize(1, 3) = su2double(0.0); + } + } + } + + auto normal_i = + make_pair(nZone, [config_container,geometry_container,iInst,WallNormal_container](unsigned long iZone){ + const CConfig* config = config_container[iZone]; + const CGeometry* geometry = geometry_container[iZone][iInst][MESH_0]; + const auto nMarker = geometry->GetnMarker(); + const auto WallNormal = WallNormal_container[iZone]; + + return make_pair( nMarker, [config,geometry,WallNormal](unsigned long iMarker){ + auto nElem_Bou = geometry->GetnElem_Bound(iMarker); + if (!config->GetViscous_Wall(iMarker)) nElem_Bou = 1; + + return make_pair(nElem_Bou, [WallNormal,iMarker](unsigned long iElem){ + const auto dimensions = 3; + + return make_pair(dimensions, [WallNormal,iMarker,iElem](unsigned short iDim){ + + return WallNormal[iMarker](iElem, iDim); + }); + }); + }); + }); + + NdFlattener<4>Normals_Local(normal_i); + NdFlattener<5> Normals_global(Nd_MPI_Environment(), Normals_Local); + + + // use it to update roughnesses + for(int jZone=0; jZonenodes->SetWallNormals(Normals_global); + } } } diff --git a/Common/src/geometry/dual_grid/CPoint.cpp b/Common/src/geometry/dual_grid/CPoint.cpp index f11b7dd89457..34999b1fbd1d 100644 --- a/Common/src/geometry/dual_grid/CPoint.cpp +++ b/Common/src/geometry/dual_grid/CPoint.cpp @@ -132,6 +132,8 @@ void CPoint::FullAllocation(unsigned short imesh, const CConfig* config) { RoughnessHeight.resize(npoint) = su2double(0.0); SharpEdge_Distance.resize(npoint) = su2double(0.0); + + Normals.resize(npoint, 3) = su2double(0.0); } void CPoint::SetElems(const vector >& elemsMatrix) { Elem = CCompressedSparsePatternL(elemsMatrix); } diff --git a/SU2_CFD/include/numerics/CNumerics.hpp b/SU2_CFD/include/numerics/CNumerics.hpp index 450112df8f7f..9c80ec71ff31 100644 --- a/SU2_CFD/include/numerics/CNumerics.hpp +++ b/SU2_CFD/include/numerics/CNumerics.hpp @@ -729,6 +729,41 @@ class CNumerics { */ su2double GetIntermittencyEff() const { return intermittency_eff_i; } + /*! + * \brief Get the value of the Transition Momentum Thickness Reynolds number from correlations. + * \param[out] Corr_Rec_i - Value of the Transition Momentum Thickness Reynolds number at point i. + */ + inline virtual su2double GetCorr_Rec() {return 0.0;} + + /*! + * \brief Get the value of the Momentum Thickness Reynolds number. + * \param[out] re_t - Value of the Momentum Thickness Reynolds number at point i. + */ + inline virtual su2double GetRe_t() {return 0.0;} + inline virtual su2double GetTu() {return 0.0;} + inline virtual su2double GetLambda_theta() {return 0.0;} + inline virtual su2double Getduds() {return 0.0;} + inline virtual su2double GetRe_v() {return 0.0;} + inline virtual su2double GetProd() {return 0.0;} + inline virtual su2double GetDestr() {return 0.0;} + inline virtual su2double GetF_onset1() {return 0.0;} + inline virtual su2double GetF_onset2() {return 0.0;} + inline virtual su2double GetF_onset3() {return 0.0;} + inline virtual su2double GetF_onset() {return 0.0;} + + /*! + * \brief Set the value of the F2 blending function into SLM transition model. + * \param[in] val_F2 - F2 blending function. + */ + inline virtual void SetF2(su2double val_F2) {} + + /*! + * \brief Set the gradient of the auxiliary variables. + * \param[in] val_auxvar_grad_i - Gradient of the auxiliary variable at point i. + * \param[in] val_auxvar_grad_j - Gradient of the auxiliary variable at point j. + */ + inline virtual void SetAuxVar(su2double val_AuxVar) {} + /*! * \brief Set the gradient of the auxiliary variables. * \param[in] val_auxvar_grad_i - Gradient of the auxiliary variable at point i. diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_convection.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_convection.hpp index 669c3a3dfa49..29ff718cd307 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_convection.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_convection.hpp @@ -38,3 +38,10 @@ template using CUpwSca_TransLM = CUpwSca_TurbSST; +/*! + * \class CUpwSca_TransSLM + * \brief Re-use the SA convective fluxes for the scalar upwind discretization of Simplified LM transition model equations. + * \ingroup ConvDiscr + */ +template +using CUpwSca_TransSLM = CUpwSca_TurbSA; \ No newline at end of file diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp index b8102120701c..b16daf7c0713 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp @@ -189,4 +189,109 @@ class TransLMCorrelations { return F_length1; } + + /*! + * \brief Compute Re_theta_c from correlations for the Simplified LM model. + * \param[in] Tu - Turbulence intensity. + * \param[in] du_ds - Streamwise velocity gradient. + * \param[out] rethetac - Corrected value for Re_theta. + */ + su2double ReThetaC_Correlations_SLM(const su2double Tu_L, const su2double lambda_theta, const su2double wall_dist, const su2double VorticityMag, const su2double VelocityMag) const { + + su2double rethetac = 0.0; + + switch (options.Correlation_SLM) { + case TURB_TRANS_CORRELATION_SLM::MENTER_SLM: { + + /*-- Thwaites parameter ---*/ + su2double lambda_theta_local = lambda_theta; + + /*-- Function to sensitize the transition onset to the streamwise pressure gradient ---*/ + su2double FPG = 0.0; + const su2double C_PG1 = 14.68; + const su2double C_PG1_lim = 1.5; + const su2double C_PG2 = -7.34; + const su2double C_PG2_lim = 3.0; + const su2double C_PG3 = 0.0; + if (lambda_theta_local >= 0.0) { + FPG = min(1+ C_PG1 * lambda_theta_local, C_PG1_lim); + } else { + const su2double FirstTerm = C_PG2 * lambda_theta_local; + const su2double SecondTerm = C_PG3 * min(lambda_theta_local + 0.0681, 0.0); + FPG = min(1 + FirstTerm + SecondTerm, C_PG2_lim); + } + + FPG = max(FPG, 0.0); + + const su2double C_TU1 = 100.0; + const su2double C_TU2 = 1000.0; + const su2double C_TU3 = 1.0; + rethetac = C_TU1 + C_TU2 * exp(-C_TU3 * Tu_L * FPG); + + break; + } case TURB_TRANS_CORRELATION_SLM::CODER_SLM: { + + /*-- Local pressure gradient parameter ---*/ + const su2double H_c = max(min(wall_dist * VorticityMag / VelocityMag, 1.1542), 0.3823); + + /*-- Thwaites parameter ---*/ + su2double lambda_theta_local = 0.0; + const su2double H_c_delta = 0.587743 - H_c; + if ( H_c >= 0.587743 ) { + const su2double FirstTerm = 0.1919 * pow(H_c_delta, 3.0); + const su2double SecondTerm = 0.4182 * pow(H_c_delta, 2.0); + const su2double ThirdTerm = 0.2959 * H_c_delta; + lambda_theta_local = FirstTerm + SecondTerm + ThirdTerm; + } else { + const su2double FirstTerm = 4.7596 * pow(H_c_delta, 3.0); + const su2double SecondTerm = -0.3837 * pow(H_c_delta, 2.0); + const su2double ThirdTerm = 0.3575 * H_c_delta; + lambda_theta_local = FirstTerm + SecondTerm + ThirdTerm; + } + + /*-- Function to sensitize the transition onset to the streamwise pressure gradient ---*/ + su2double FPG = 0.0; + if (lambda_theta_local <= 0.0) { + const su2double FirstTerm = -12.986 * lambda_theta_local; + const su2double SecondTerm = -123.66 * pow(lambda_theta_local, 2.0); + const su2double ThirdTerm = -405.689 * pow(lambda_theta_local, 3.0); + FPG = 1 - (FirstTerm + SecondTerm + ThirdTerm) * exp(-pow(Tu_L/1.5,1.5)); + } else { + FPG = 1 + 0.275 * (1 - exp(-35.0 * lambda_theta_local)) * exp(-Tu_L/0.5); + } + + // This is not reported in the paper + //FPG = max(FPG, 0.0); + + if (Tu_L <= 1.3) { + const su2double FirstTerm = -589.428 * Tu_L; + const su2double SecondTerm = 0.2196 / max(pow(Tu_L, 2.0), 1e-12); + rethetac = 1173.51 + FirstTerm + SecondTerm; + } else { + rethetac = 331.50 * pow(Tu_L-0.5658, -0.671); + } + rethetac = rethetac * FPG; + + break; + } case TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM: { + + /*-- Local pressure gradient parameter ---*/ + const su2double H_c = max(min(wall_dist * VorticityMag / VelocityMag, 1.1542), 0.3823); + + /*-- H_32 Shape factor --*/ + const su2double H_32 = 1.515095 + 0.2041 * pow((1.1542 - H_c), 2.0956); + + rethetac = exp(127.94 * pow((H_32-1.515095), 2.0) + 6.774224); + + break; + } + case TURB_TRANS_CORRELATION_SLM::DEFAULT: + SU2_MPI::Error("Transition correlation for Simplified LM model is set to DEFAULT but no default value has ben set in the code.", + CURRENT_FUNCTION); + break; + } + + return rethetac; + } + }; diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp index 50153606860b..e5d581b537e4 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp @@ -103,3 +103,71 @@ class CAvgGrad_TransLM final : public CAvgGrad_Scalar { } }; + +/*! + * \class CAvgGrad_TransSLM + * \brief Class for computing viscous term using average of gradient with correction (Simplified LM transition model). + * \ingroup ViscDiscr + * \author S. Kang. + */ +template +class CAvgGrad_TransSLM final : public CAvgGrad_Scalar { +private: + using Base = CAvgGrad_Scalar; + using Base::Laminar_Viscosity_i; + using Base::Laminar_Viscosity_j; + using Base::Eddy_Viscosity_i; + using Base::Eddy_Viscosity_j; + using Base::Density_i; + using Base::Density_j; + using Base::ScalarVar_i; + using Base::ScalarVar_j; + using Base::Proj_Mean_GradScalarVar; + using Base::proj_vector_ij; + using Base::Flux; + using Base::Jacobian_i; + using Base::Jacobian_j; + + /*! + * \brief Adds any extra variables to AD + */ + void ExtraADPreaccIn() override {} + + /*! + * \brief LM transition model specific steps in the ComputeResidual method + * \param[in] config - Definition of the particular problem. + */ + void FinishResidualCalc(const CConfig* config) override { + const bool implicit = config->GetKind_TimeIntScheme() == EULER_IMPLICIT; + + /*--- Compute mean effective dynamic viscosity ---*/ + const su2double diff_i_gamma = Laminar_Viscosity_i + Eddy_Viscosity_i; + const su2double diff_j_gamma = Laminar_Viscosity_j + Eddy_Viscosity_j; + + const su2double diff_gamma = 0.5*(diff_i_gamma + diff_j_gamma); + + Flux[0] = diff_gamma*Proj_Mean_GradScalarVar[0]; + + /*--- For Jacobians -> Use of TSL (Thin Shear Layer) approx. to compute derivatives of the gradients ---*/ + if (implicit) { + const su2double proj_on_rho_i = proj_vector_ij/Density_i; + Jacobian_i[0][0] = -diff_gamma*proj_on_rho_i; + + const su2double proj_on_rho_j = proj_vector_ij/Density_j; + Jacobian_j[0][0] = diff_gamma*proj_on_rho_j; + } + } + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] correct_grad - Whether to correct gradient for skewness. + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_TransSLM(unsigned short val_nDim, unsigned short val_nVar, bool correct_grad, const CConfig* config) + : CAvgGrad_Scalar(val_nDim, val_nVar, correct_grad, config){ + } + +}; \ No newline at end of file diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index c1388c2df9c6..dd6bae78a812 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -56,6 +56,17 @@ class CSourcePieceWise_TransLM final : public CNumerics { TURB_FAMILY TurbFamily; su2double hRoughness; + su2double Re_v_Here; + su2double Corr_Rec_Here; + su2double Prod_Here = 0.0; + su2double Destr_Here = 0.0; + su2double F_onset1_Here = 0.0; + su2double F_onset2_Here = 0.0; + su2double F_onset3_Here = 0.0; + su2double F_onset_Here = 0.0; + su2double lambda_theta_Here = 0.0; + su2double duds_Here = 0.0; + su2double IntermittencySep = 1.0; su2double IntermittencyEff = 1.0; @@ -92,7 +103,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. */ ResidualType<> ComputeResidual(const CConfig* config) override { - /*--- ScalarVar[0] = k, ScalarVar[0] = w, TransVar[0] = gamma, and TransVar[0] = ReThetaT ---*/ + /*--- ScalarVar[0] = k, ScalarVar[0] = w, TransVar[0] = gamma, and TransVar[1] = ReThetaT ---*/ /*--- dU/dx = PrimVar_Grad[1][0] ---*/ AD::StartPreacc(); AD::SetPreaccIn(StrainMag_i); @@ -113,7 +124,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { const su2double vel_v = V_i[1 + idx.Velocity()]; const su2double vel_w = (nDim == 3) ? V_i[2 + idx.Velocity()] : 0.0; - const su2double Velocity_Mag = sqrt(vel_u * vel_u + vel_v * vel_v + vel_w * vel_w); + const su2double Velocity_Mag = max(sqrt(vel_u * vel_u + vel_v * vel_v + vel_w * vel_w), 1e-20); AD::SetPreaccIn(V_i[idx.Density()], V_i[idx.LaminarViscosity()], V_i[idx.EddyViscosity()]); @@ -135,6 +146,8 @@ class CSourcePieceWise_TransLM final : public CNumerics { /*--- Corr_RetC correlation*/ const su2double Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, TransVar_i[1]); + // AGGIUNTO PER DEBUG + Corr_Rec_Here = Corr_Rec; /*--- F_length correlation*/ const su2double Corr_F_length = TransCorrelations.FLength_Correlations(Tu, TransVar_i[1]); @@ -154,6 +167,9 @@ class CSourcePieceWise_TransLM final : public CNumerics { if (TurbFamily == TURB_FAMILY::SA) R_t = Eddy_Viscosity_i / Laminar_Viscosity_i; const su2double Re_v = Density_i * dist_i * dist_i * StrainMag_i / Laminar_Viscosity_i; + // AGGIUNTO PER DEBUG + Re_v_Here = Re_v; + const su2double F_onset1 = Re_v / (2.193 * Corr_Rec); su2double F_onset2 = 1.0; su2double F_onset3 = 1.0; @@ -166,6 +182,11 @@ class CSourcePieceWise_TransLM final : public CNumerics { F_onset3 = max(2.0 - pow(R_t / 2.5, 3.0), 0.0); } const su2double F_onset = max(F_onset2 - F_onset3, 0.0); + // AGGIUNTO PER DEBUG + F_onset1_Here = F_onset1; + F_onset2_Here = F_onset2; + F_onset3_Here = F_onset3; + F_onset_Here = F_onset; /*-- Gradient of velocity magnitude ---*/ @@ -186,7 +207,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { /*-- Calculate blending function f_theta --*/ su2double time_scale = 500.0 * Laminar_Viscosity_i / Density_i / Velocity_Mag / Velocity_Mag; - if (options.LM2015) + if (options.CrossFlow) time_scale = min(time_scale, Density_i * LocalGridLength_i * LocalGridLength_i / (Laminar_Viscosity_i + Eddy_Viscosity_i)); const su2double theta_bl = TransVar_i[1] * Laminar_Viscosity_i / Density_i / Velocity_Mag; @@ -206,7 +227,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { const su2double f_turb = exp(-pow(R_t / 4, 4)); su2double f_theta_2 = 0.0; - if (options.LM2015) + if (options.CrossFlow) f_theta_2 = min(f_wake * exp(-pow(dist_i / delta, 4.0)), 1.0); /*--- Corr_Ret correlation*/ @@ -245,9 +266,13 @@ class CSourcePieceWise_TransLM final : public CNumerics { Retheta_old = Corr_Ret; } + // DEBUG + lambda_theta_Here = lambda; + duds_Here = du_ds; + /*-- Corr_RetT_SCF Correlations--*/ su2double ReThetat_SCF = 0.0; - if (options.LM2015) { + if (options.CrossFlow) { su2double VelocityNormalized[3]; VelocityNormalized[0] = vel_u / Velocity_Mag; VelocityNormalized[1] = vel_v / Velocity_Mag; @@ -292,13 +317,17 @@ class CSourcePieceWise_TransLM final : public CNumerics { /*-- destruction term of Intermeittency(Gamma) --*/ const su2double Dg = c_a2 * Density_i * VorticityMag * TransVar_i[0] * f_turb * (c_e2 * TransVar_i[0] - 1.0); + // DEBUG + Prod_Here = Pg; + Destr_Here = Dg; + /*-- production term of ReThetaT --*/ const su2double PRethetat = c_theta * Density_i / time_scale * (Corr_Ret - TransVar_i[1]) * (1.0 - f_theta); /*-- destruction term of ReThetaT --*/ // It should not be with the minus sign but I put for consistency su2double DRethetat = 0.0; - if (options.LM2015) + if (options.CrossFlow) DRethetat = -c_theta * (Density_i / time_scale) * c_CF * min(ReThetat_SCF - TransVar_i[1], 0.0) * f_theta_2; /*--- Source ---*/ @@ -313,7 +342,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { Jacobian_i[0][1] = 0.0; Jacobian_i[1][0] = 0.0; Jacobian_i[1][1] = -c_theta / time_scale * (1.0 - f_theta) * Volume; - if (options.LM2015 && ReThetat_SCF - TransVar_i[1] < 0) + if (options.CrossFlow && ReThetat_SCF - TransVar_i[1] < 0) Jacobian_i[1][1] += (c_theta / time_scale) * c_CF * f_theta_2 * Volume; } @@ -322,4 +351,293 @@ class CSourcePieceWise_TransLM final : public CNumerics { return ResidualType<>(Residual, Jacobian_i, nullptr); } + + inline su2double GetRe_v() override {return Re_v_Here;} + inline su2double GetCorr_Rec() override {return Corr_Rec_Here;} + inline su2double GetProd() override {return Prod_Here;} + inline su2double GetDestr() override {return Destr_Here;} + inline su2double GetF_onset1() override {return F_onset1_Here;} + inline su2double GetF_onset2() override {return F_onset2_Here;} + inline su2double GetF_onset3() override {return F_onset3_Here;} + inline su2double GetF_onset() override {return F_onset_Here;} + inline su2double GetLambda_theta() override {return lambda_theta_Here;} + inline su2double Getduds() override {return duds_Here;} + }; + +/*! + * \class CSourcePieceWise_TranSLM + * \brief Class for integrating the source terms of the Simplified LM transition model equations. + * \ingroup SourceDiscr + * \author S. Kang. + */ +template +class CSourcePieceWise_TransSLM final : public CNumerics { + private: + const FlowIndices idx; /*!< \brief Object to manage the access to the flow primitives. */ + + const LM_ParsedOptions options; + + /*--- LM Closure constants ---*/ + const su2double c_e1 = 1.0; + const su2double c_a1 = 2.0; + const su2double c_e2 = 50.0; + const su2double c_a2 = 0.06; + const su2double sigmaf = 1.0; + const su2double s1 = 2.0; + const su2double c_theta = 0.03; + const su2double c_CF = 0.6; + const su2double sigmat = 2.0; + + TURB_FAMILY TurbFamily; + su2double hRoughness; + + su2double IntermittencySep = 1.0; + su2double IntermittencyEff = 1.0; + + su2double Re_t; + su2double Corr_Rec = 1.0; + su2double AuxVar; + su2double F2; + su2double Tu_Here = 0.0; + su2double duds_Here = 0.0; + su2double lambda_theta_Here = 0.0; + su2double Re_v_Here = 0.0; + su2double Prod_Here = 0.0; + su2double Destr_Here = 0.0; + su2double F_onset1_Here = 0.0; + su2double F_onset2_Here = 0.0; + su2double F_onset3_Here = 0.0; + su2double F_onset_Here = 0.0; + + su2double Residual; + su2double* Jacobian_i; + su2double Jacobian_Buffer; // Static storage for the Jacobian (which needs to be pointer for return type). + + TransLMCorrelations TransCorrelations; + + public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourcePieceWise_TransSLM(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) + : CNumerics(val_nDim, 1, config), idx(val_nDim, config->GetnSpecies()), options(config->GetLMParsedOptions()){ + /*--- "Allocate" the Jacobian using the static buffer. ---*/ + Jacobian_i = &Jacobian_Buffer; + + TurbFamily = TurbModelFamily(config->GetKind_Turb_Model()); + + hRoughness = config->GethRoughness(); + + TransCorrelations.SetOptions(options); + + } + + /*! + * \brief Residual for source term integration. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override { + /*--- ScalarVar[0] = k, ScalarVar[0] = w, TransVar[0] = gamma ---*/ + /*--- dU/dx = PrimVar_Grad[1][0] ---*/ + AD::StartPreacc(); + AD::SetPreaccIn(StrainMag_i); + AD::SetPreaccIn(ScalarVar_i, nVar); + AD::SetPreaccIn(ScalarVar_Grad_i, nVar, nDim); + AD::SetPreaccIn(TransVar_i, nVar); + AD::SetPreaccIn(TransVar_Grad_i, nVar, nDim); + AD::SetPreaccIn(Volume); + AD::SetPreaccIn(dist_i); + AD::SetPreaccIn(&V_i[idx.Velocity()], nDim); + AD::SetPreaccIn(PrimVar_Grad_i, nDim + idx.Velocity(), nDim); + AD::SetPreaccIn(Vorticity_i, 3); + + su2double VorticityMag = + sqrt(Vorticity_i[0] * Vorticity_i[0] + Vorticity_i[1] * Vorticity_i[1] + Vorticity_i[2] * Vorticity_i[2]); + + const su2double vel_u = V_i[idx.Velocity()]; + const su2double vel_v = V_i[1 + idx.Velocity()]; + const su2double vel_w = (nDim == 3) ? V_i[2 + idx.Velocity()] : 0.0; + + su2double Velocity[nDim]; + Velocity[0] = vel_u; + Velocity[1] = vel_v; + if(nDim == 3) Velocity[2] = vel_w; + + + const su2double Velocity_Mag = max(sqrt(vel_u * vel_u + vel_v * vel_v + vel_w * vel_w), 1e-20); + + AD::SetPreaccIn(V_i[idx.Density()], V_i[idx.LaminarViscosity()], V_i[idx.EddyViscosity()]); + + Density_i = V_i[idx.Density()]; + Laminar_Viscosity_i = V_i[idx.LaminarViscosity()]; + Eddy_Viscosity_i = V_i[idx.EddyViscosity()]; + + Residual = 0.0; + Jacobian_i[0] = 0.0; + + if (dist_i > 1e-10) { + su2double Tu_L = 1.0; + if (TurbFamily == TURB_FAMILY::KW) Tu_L = min(100.0 * sqrt(2.0 * ScalarVar_i[0] / 3.0) / (ScalarVar_i[1]*dist_i), 100.0); + // if (TurbFamily == TURB_FAMILY::KW) Tu_L = min(100.0 * sqrt(2.0 * ScalarVar_i[0] / 3.0) / (Velocity_Mag), 100.0); + if (TurbFamily == TURB_FAMILY::SA) Tu_L = config->GetTurbulenceIntensity_FreeStream() * 100; + + Tu_Here = Tu_L; + + /*--- F_length ---*/ + su2double F_length = 100.0; + + /*--- F_onset ---*/ + su2double R_t = 1.0; + if (TurbFamily == TURB_FAMILY::KW) R_t = Density_i * ScalarVar_i[0] / (Laminar_Viscosity_i * ScalarVar_i[1]); + if (TurbFamily == TURB_FAMILY::SA) R_t = Eddy_Viscosity_i / Laminar_Viscosity_i; + + /*-- Gradient of velocity magnitude ---*/ + + // su2double du_ds = 0.0; + // for (int i = 0; i < nDim; i++) + // for (int j = 0; j < nDim; j++) + // du_ds = du_ds + Velocity[i]*Velocity[j]*PrimVar_Grad_i[i][j]; + + // du_ds = du_ds/(Velocity_Mag*Velocity_Mag); + + // const su2double lambda_theta = -7.57e-3 * du_ds * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128; + const su2double lambda_theta = max(min(-7.57e-3 * AuxVar * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128, 1.0), -1.0); + // const su2double lambda_theta = du_ds * dist_i * dist_i * Density_i / Laminar_Viscosity_i; + // duds_Here = du_ds; + duds_Here = AuxVar; + lambda_theta_Here = lambda_theta; + + // const su2double lambda_theta = 7.57e-3 * AuxVar * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128; + + /*--- Corr_RetC correlation*/ + Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, lambda_theta, dist_i, VorticityMag, Velocity_Mag); + Corr_Rec = Re_t; // If the MENTER_SLM correlation is used then they are the same thing + + if (options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::CODER_SLM || options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM) { + // If these correlations are used, then the value of Corr_Rec has to be used instead of the TransVar[1] of the original LM model + F_length = TransCorrelations.FLength_Correlations(Tu_L, Re_t); + Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu_L, Re_t); + } + + + const su2double Re_v = Density_i * dist_i * dist_i * StrainMag_i / Laminar_Viscosity_i; + Re_v_Here = Re_v; + const su2double F_onset1 = Re_v / (2.2 * Corr_Rec); + su2double F_onset2 = 1.0; + su2double F_onset3 = 1.0; + if (TurbFamily == TURB_FAMILY::KW) { + F_onset2 = min(F_onset1, 2.0); + F_onset3 = max(1.0 - pow(R_t / 3.5, 3.0), 0.0); + } + if (TurbFamily == TURB_FAMILY::SA) { + F_onset2 = min(max(F_onset1, pow(F_onset1, 4.0)), 4.0); + F_onset3 = max(2.0 - pow(R_t / 2.5, 3.0), 0.0); + } + su2double F_onset = max(F_onset2 - F_onset3, 0.0); + + F_onset1_Here = F_onset1; + F_onset2_Here = F_onset2; + F_onset3_Here = F_onset3; + F_onset_Here = F_onset; + + if (options.CrossFlow) { + + // Computation of shape factor + const su2double k = 0.25 - lambda_theta; + const su2double FirstTerm = 4.14 * k; + const su2double SecondTerm = 83.5 * pow(k, 2.0); + const su2double ThirdTerm = 854.0 * pow(k, 3.0); + const su2double ForthTerm = 3337.0 * pow(k, 4.0); + const su2double FifthTerm = 4576.0 * pow(k, 5.0); + const su2double H = min(2.0 + FirstTerm - SecondTerm + ThirdTerm - ForthTerm + FifthTerm, 2.7); + + // Computation of critical cross flow Reynolds number + su2double Re_Crit_CF = 0.0; + if(H < 2.3) { + Re_Crit_CF = 150.0; + } else { + Re_Crit_CF = -(300.0/PI_NUMBER) * atan(0.106/(pow(H-2.3, 2.05))); + } + + // Helicity computation + su2double VelocityNormalized[3]; + VelocityNormalized[0] = vel_u / Velocity_Mag; + VelocityNormalized[1] = vel_v / Velocity_Mag; + if (nDim == 3) VelocityNormalized[2] = vel_w / Velocity_Mag; + + su2double StreamwiseVort = 0.0; + for (auto iDim = 0u; iDim < nDim; iDim++) { + StreamwiseVort += VelocityNormalized[iDim] * Vorticity_i[iDim]; + } + StreamwiseVort = abs(StreamwiseVort); + + const su2double H_CF = StreamwiseVort * dist_i / Velocity_Mag; + + // Computation of Delta_H_CF. Here I have included directly R_t as the ration between turb and lam viscosity + const su2double Delta_H_CF = H_CF * (1.0 + min(R_t, 0.4)); + + // Take into account for roughness + const su2double h_0 = 0.25e-6; + const su2double C_r = 2.0 - pow(0.5, config->GethRoughness()/h_0); + + // Construct Cross flow activation function + const su2double C_CF = 1.0; + const su2double f_CF = (C_CF * C_r * Delta_H_CF * Corr_Rec) / Re_Crit_CF; + const su2double F_onset_CF = min(max(0.0, f_CF - 1.0), 1.0); + + // Adjust onset function for intermittency + F_onset = max(F_onset, F_onset_CF); + + } + + const su2double f_turb = exp(-pow(R_t / 2, 4)); + + /*-- production term of Intermeittency(Gamma) --*/ + const su2double Pg = + F_length * Density_i * StrainMag_i * F_onset * TransVar_i[0] * (1.0 - TransVar_i[0]); + + /*-- destruction term of Intermeittency(Gamma) --*/ + const su2double Dg = c_a2 * Density_i * VorticityMag * TransVar_i[0] * f_turb * (c_e2 * TransVar_i[0] - 1.0); + + Prod_Here = Pg; + Destr_Here = Dg; + + /*--- Source ---*/ + Residual += (Pg - Dg) * Volume; + + /*--- Implicit part ---*/ + Jacobian_i[0] = (F_length * StrainMag_i * F_onset * (1 - 2*TransVar_i[0]) - + c_a2 * VorticityMag * f_turb * (2.0 * c_e2 * TransVar_i[0] - 1.0)) * + Volume; + + } + + AD::SetPreaccOut(Residual, nVar); + AD::EndPreacc(); + + return ResidualType<>(&Residual, &Jacobian_i, nullptr); + + } + + inline su2double GetRe_t() override {return Re_t;} + inline su2double GetCorr_Rec() override {return Corr_Rec;} + inline su2double GetTu() override {return Tu_Here;} + inline su2double GetLambda_theta() override {return lambda_theta_Here;} + inline su2double Getduds() override {return duds_Here;} + inline su2double GetRe_v() override {return Re_v_Here;} + inline su2double GetProd() override {return Prod_Here;} + inline su2double GetDestr() override {return Destr_Here;} + inline su2double GetF_onset1() override {return F_onset1_Here;} + inline su2double GetF_onset2() override {return F_onset2_Here;} + inline su2double GetF_onset3() override {return F_onset3_Here;} + inline su2double GetF_onset() override {return F_onset_Here;} + inline void SetAuxVar(su2double val_AuxVar) override { AuxVar = val_AuxVar;} + // non serve più + inline void SetF2(su2double val_F2) override { F2 = val_F2;} + +}; \ No newline at end of file diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index bdf9d0c6fc47..28eab5619578 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -839,6 +839,18 @@ class CSourcePieceWise_TurbSST final : public CNumerics { /*--- LM model coupling with production and dissipation term for k transport equation---*/ if (config->GetKind_Trans_Model() == TURB_TRANS_MODEL::LM) { pk = pk * eff_intermittency; + + // Check if the Prod_lim_k has to be introduced based on input options + if ((config->GetLMParsedOptions()).SLM && (config->GetLMParsedOptions()).Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) { + const su2double Re_theta_c_lim = 1100.0; + const su2double C_k = 1.0; + const su2double C_SEP = 1.0; + const su2double Re_v = Density_i * dist_i * dist_i * StrainMag_i / Laminar_Viscosity_i; + const su2double F_on_lim = min(max(Re_v/(2.2*Re_theta_c_lim)-1.0, 0.0), 3.0); + const su2double IntermittencyRelated = max(eff_intermittency-0.2, 0.0) * (1.0 - eff_intermittency); + pk = pk + 5*C_k * IntermittencyRelated * F_on_lim * max(3.0*C_SEP*Laminar_Viscosity_i - Eddy_Viscosity_i, 0.0) * StrainMag_i * VorticityMag; + } + dk = min(max(eff_intermittency, 0.1), 1.0) * dk; } diff --git a/SU2_CFD/include/solvers/CTransLMSolver.hpp b/SU2_CFD/include/solvers/CTransLMSolver.hpp index 98595abb266d..40515ed50543 100644 --- a/SU2_CFD/include/solvers/CTransLMSolver.hpp +++ b/SU2_CFD/include/solvers/CTransLMSolver.hpp @@ -42,6 +42,7 @@ class CTransLMSolver final : public CTurbSolver { LM_ParsedOptions options; TURB_FAMILY TurbFamily; + bool isSepNeeded; TransLMCorrelations TransCorrelations; diff --git a/SU2_CFD/include/variables/CTransLMVariable.hpp b/SU2_CFD/include/variables/CTransLMVariable.hpp index 96b556f54508..f1c3f280264f 100644 --- a/SU2_CFD/include/variables/CTransLMVariable.hpp +++ b/SU2_CFD/include/variables/CTransLMVariable.hpp @@ -40,6 +40,23 @@ class CTransLMVariable final : public CTurbVariable { protected: VectorType Intermittency_Eff; VectorType Intermittency_Sep; + + VectorType Corr_Rec; + VectorType Re_t; + VectorType Tu; + VectorType Lambda_theta; + VectorType duds; + VectorType Re_v; + VectorType Prod; + VectorType Destr; + VectorType F_onset1; + VectorType F_onset2; + VectorType F_onset3; + VectorType F_onset; + + VectorType normal_x; + VectorType normal_y; + VectorType normal_z; public: /*! @@ -70,6 +87,28 @@ class CTransLMVariable final : public CTurbVariable { */ void SetIntermittencyEff(unsigned long iPoint, su2double val_Intermittency_sep) override; + /*! + * \brief Set Value of Transition Momentum Thickness Reynolds number from correlations. + */ + void SetCorr_Rec(unsigned long iPoint, su2double val_Corr_Rec) override; + + /*! + * \brief Set Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). + */ + void SetRe_t(unsigned long iPoint, su2double val_Re_t) override; + void SetTu(unsigned long iPoint, su2double val_Tu) override; + void SetLambda_theta(unsigned long iPoint, su2double val_Lambda_theta) override; + void Setduds(unsigned long iPoint, su2double val_duds) override; + void SetRe_v(unsigned long iPoint, su2double val_Re_v) override; + void SetProd(unsigned long iPoint, su2double val_Prod) override; + void SetDestr(unsigned long iPoint, su2double val_Destr) override; + void SetF_onset1(unsigned long iPoint, su2double val_F_onset1) override; + void SetF_onset2(unsigned long iPoint, su2double val_F_onset2) override; + void SetF_onset3(unsigned long iPoint, su2double val_F_onset3) override; + void SetF_onset(unsigned long iPoint, su2double val_F_onset) override; + void SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y, su2double val_normal_z) override; + + /*! * \brief Calculate effective intermittency. */ @@ -80,4 +119,26 @@ class CTransLMVariable final : public CTurbVariable { */ inline su2double GetIntermittencySep(unsigned long iPoint) const override { return Intermittency_Sep(iPoint); } + /*! + * \brief Get Value of Transition Momentum Thickness Reynolds number from correlations. + */ + inline su2double GetCorr_Rec(unsigned long iPoint) const override { return Corr_Rec(iPoint); } + + /*! + * \brief Get Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). + */ + inline su2double GetRe_t(unsigned long iPoint) const override { return Re_t(iPoint); } + inline su2double GetTu(unsigned long iPoint) const override { return Tu(iPoint); } + inline su2double GetLambda_theta(unsigned long iPoint) const override { return Lambda_theta(iPoint); } + inline su2double Getduds(unsigned long iPoint) const override { return duds(iPoint); } + inline su2double GetRe_v(unsigned long iPoint) const override { return Re_v(iPoint); } + inline su2double GetProd(unsigned long iPoint) const override { return Prod(iPoint); } + inline su2double GetDestr(unsigned long iPoint) const override { return Destr(iPoint); } + inline su2double GetF_onset1(unsigned long iPoint) const override { return F_onset1(iPoint); } + inline su2double GetF_onset2(unsigned long iPoint) const override { return F_onset2(iPoint); } + inline su2double GetF_onset3(unsigned long iPoint) const override { return F_onset3(iPoint); } + inline su2double GetF_onset(unsigned long iPoint) const override { return F_onset(iPoint); } + inline su2double GetNormal_x(unsigned long iPoint) const override {return normal_x(iPoint);}; + inline su2double GetNormal_y(unsigned long iPoint) const override {return normal_y(iPoint);}; + inline su2double GetNormal_z(unsigned long iPoint) const override {return normal_z(iPoint);}; }; diff --git a/SU2_CFD/include/variables/CTurbSSTVariable.hpp b/SU2_CFD/include/variables/CTurbSSTVariable.hpp index 8735ddc6de6c..d745ca82d716 100644 --- a/SU2_CFD/include/variables/CTurbSSTVariable.hpp +++ b/SU2_CFD/include/variables/CTurbSSTVariable.hpp @@ -45,6 +45,7 @@ class CTurbSSTVariable final : public CTurbVariable { VectorType F2; /*!< \brief Menter blending function for blending of k-w and k-eps. */ VectorType CDkw; /*!< \brief Cross-diffusion. */ SST_ParsedOptions sstParsedOptions; + LM_ParsedOptions lmParsedOptions; public: /*! * \brief Constructor of the class. diff --git a/SU2_CFD/include/variables/CVariable.hpp b/SU2_CFD/include/variables/CVariable.hpp index 358824ae8d7a..d48f8839d571 100644 --- a/SU2_CFD/include/variables/CVariable.hpp +++ b/SU2_CFD/include/variables/CVariable.hpp @@ -1689,6 +1689,51 @@ class CVariable { */ inline virtual void SetIntermittencyEff(unsigned long iPoint, su2double val_Intermittency_eff) {} + + /*! + * \brief Set Value of Transition Momentum Thickness Reynolds number from correlations. + */ + inline virtual void SetCorr_Rec(unsigned long iPoint, su2double val_Corr_Rec) {}; + inline virtual void SetTu(unsigned long iPoint, su2double val_Tu) {}; + inline virtual void SetLambda_theta(unsigned long iPoint, su2double val_Lambda_theta) {}; + inline virtual void Setduds(unsigned long iPoint, su2double val_duds) {}; + inline virtual void SetRe_v(unsigned long iPoint, su2double val_Re_v) {}; + inline virtual void SetProd(unsigned long iPoint, su2double val_Prod) {}; + inline virtual void SetDestr(unsigned long iPoint, su2double val_Destr) {}; + inline virtual void SetF_onset1(unsigned long iPoint, su2double val_F_onset1) {}; + inline virtual void SetF_onset2(unsigned long iPoint, su2double val_F_onset2) {}; + inline virtual void SetF_onset3(unsigned long iPoint, su2double val_F_onset3) {}; + inline virtual void SetF_onset(unsigned long iPoint, su2double val_F_onset1) {}; + inline virtual void SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y, su2double val_normal_z) {}; + + /*! + * \brief Get Value of Transition Momentum Thickness Reynolds number from correlations. + */ + inline virtual su2double GetCorr_Rec(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetTu(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetLambda_theta(unsigned long iPoint) const { return 0.0; } + inline virtual su2double Getduds(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetRe_v(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetProd(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetDestr(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetF_onset1(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetF_onset2(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetF_onset3(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetF_onset(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetNormal_x(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetNormal_y(unsigned long iPoint) const { return 0.0; } + inline virtual su2double GetNormal_z(unsigned long iPoint) const { return 0.0; } + + /*! + * \brief Set Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). + */ + inline virtual void SetRe_t(unsigned long iPoint, su2double val_Re_t) {}; + + /*! + * \brief Get Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). + */ + inline virtual su2double GetRe_t(unsigned long iPoint) const { return 0.0; } + /*! * \brief Set the value of the eddy viscosity. * \param[in] val_muT diff --git a/SU2_CFD/src/drivers/CDriver.cpp b/SU2_CFD/src/drivers/CDriver.cpp index 14c478c0f473..0b7992825446 100644 --- a/SU2_CFD/src/drivers/CDriver.cpp +++ b/SU2_CFD/src/drivers/CDriver.cpp @@ -1333,6 +1333,8 @@ void CDriver::InstantiateTransitionNumerics(unsigned short nVar_Trans, int offse const int visc_bound_term = VISC_BOUND_TERM + offset; const bool LM = config->GetKind_Trans_Model() == TURB_TRANS_MODEL::LM; + LM_ParsedOptions options; + if(LM) options = config->GetLMParsedOptions(); /*--- Definition of the convective scheme for each equation and mesh level ---*/ @@ -1342,7 +1344,10 @@ void CDriver::InstantiateTransitionNumerics(unsigned short nVar_Trans, int offse break; case SPACE_UPWIND : for (auto iMGlevel = 0u; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - if (LM) numerics[iMGlevel][TRANS_SOL][conv_term] = new CUpwSca_TransLM(nDim, nVar_Trans, config); + if (LM){ + if (!options.SLM) numerics[iMGlevel][TRANS_SOL][conv_term] = new CUpwSca_TransLM(nDim, nVar_Trans, config); + if (options.SLM) numerics[iMGlevel][TRANS_SOL][conv_term] = new CUpwSca_TransSLM(nDim, nVar_Trans, config); + } } break; default: @@ -1353,7 +1358,10 @@ void CDriver::InstantiateTransitionNumerics(unsigned short nVar_Trans, int offse /*--- Definition of the viscous scheme for each equation and mesh level ---*/ for (auto iMGlevel = 0u; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - if (LM) numerics[iMGlevel][TRANS_SOL][visc_term] = new CAvgGrad_TransLM(nDim, nVar_Trans, true, config); + if (LM){ + if (!options.SLM) numerics[iMGlevel][TRANS_SOL][visc_term] = new CAvgGrad_TransLM(nDim, nVar_Trans, true, config); + if (options.SLM) numerics[iMGlevel][TRANS_SOL][visc_term] = new CAvgGrad_TransSLM(nDim, nVar_Trans, true, config); + } } /*--- Definition of the source term integration scheme for each equation and mesh level ---*/ @@ -1361,7 +1369,10 @@ void CDriver::InstantiateTransitionNumerics(unsigned short nVar_Trans, int offse for (auto iMGlevel = 0u; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { auto& trans_source_first_term = numerics[iMGlevel][TRANS_SOL][source_first_term]; - if (LM) trans_source_first_term = new CSourcePieceWise_TransLM(nDim, nVar_Trans, config); + if (LM){ + if (!options.SLM) trans_source_first_term = new CSourcePieceWise_TransLM(nDim, nVar_Trans, config); + if (options.SLM) trans_source_first_term = new CSourcePieceWise_TransSLM(nDim, nVar_Trans, config); + } numerics[iMGlevel][TRANS_SOL][source_second_term] = new CSourceNothing(nDim, nVar_Trans, config); } @@ -1369,9 +1380,12 @@ void CDriver::InstantiateTransitionNumerics(unsigned short nVar_Trans, int offse /*--- Definition of the boundary condition method ---*/ for (auto iMGlevel = 0u; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - if (LM) { + if (!options.SLM) { numerics[iMGlevel][TRANS_SOL][conv_bound_term] = new CUpwSca_TransLM(nDim, nVar_Trans, config); numerics[iMGlevel][TRANS_SOL][visc_bound_term] = new CAvgGrad_TransLM(nDim, nVar_Trans, false, config); + } else { + numerics[iMGlevel][TRANS_SOL][conv_bound_term] = new CUpwSca_TransSLM(nDim, nVar_Trans, config); + numerics[iMGlevel][TRANS_SOL][visc_bound_term] = new CAvgGrad_TransSLM(nDim, nVar_Trans, false, config); } } } diff --git a/SU2_CFD/src/output/CFlowIncOutput.cpp b/SU2_CFD/src/output/CFlowIncOutput.cpp index cd275b8f51ea..c70551c14d44 100644 --- a/SU2_CFD/src/output/CFlowIncOutput.cpp +++ b/SU2_CFD/src/output/CFlowIncOutput.cpp @@ -211,7 +211,7 @@ void CFlowIncOutput::LoadHistoryData(CConfig *config, CGeometry *geometry, CSolv SetHistoryOutputValue("MAX_PRESSURE", log10(flow_solver->GetRes_Max(0))); SetHistoryOutputValue("MAX_VELOCITY-X", log10(flow_solver->GetRes_Max(1))); SetHistoryOutputValue("MAX_VELOCITY-Y", log10(flow_solver->GetRes_Max(2))); - if (nDim == 3) SetHistoryOutputValue("RMS_VELOCITY-Z", log10(flow_solver->GetRes_Max(3))); + if (nDim == 3) SetHistoryOutputValue("MAX_VELOCITY-Z", log10(flow_solver->GetRes_Max(3))); if (multiZone){ SetHistoryOutputValue("BGS_PRESSURE", log10(flow_solver->GetRes_BGS(0))); diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index 5ffee0d23f54..bf45c281b0fa 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -981,7 +981,10 @@ void CFlowOutput::AddHistoryOutputFields_ScalarRMS_RES(const CConfig* config) { /// DESCRIPTION: Root-mean square residual of the intermittency (LM model). AddHistoryOutput("RMS_INTERMITTENCY", "rms[LM_1]", ScreenOutputFormat::FIXED, "RMS_RES", "Root-mean square residual of intermittency (LM model).", HistoryFieldType::RESIDUAL); /// DESCRIPTION: Root-mean square residual of the momentum thickness Reynolds number (LM model). - AddHistoryOutput("RMS_RE_THETA_T", "rms[LM_2]", ScreenOutputFormat::FIXED, "RMS_RES", "Root-mean square residual of momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + if (!(config->GetLMParsedOptions()).SLM) { + /// DESCRIPTION: Root-mean square residual of the momentum thickness Reynolds number (LM model). + AddHistoryOutput("RMS_RE_THETA_T", "rms[LM_2]", ScreenOutputFormat::FIXED, "RMS_RES", "Root-mean square residual of momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + } break; case TURB_TRANS_MODEL::NONE: break; @@ -1037,7 +1040,10 @@ void CFlowOutput::AddHistoryOutputFields_ScalarMAX_RES(const CConfig* config) { /// DESCRIPTION: Maximum residual of the intermittency (LM model). AddHistoryOutput("MAX_INTERMITTENCY", "max[LM_1]", ScreenOutputFormat::FIXED, "MAX_RES", "Maximum residual of the intermittency (LM model).", HistoryFieldType::RESIDUAL); /// DESCRIPTION: Maximum residual of the momentum thickness Reynolds number (LM model). - AddHistoryOutput("MAX_RE_THETA_T", "max[LM_2]", ScreenOutputFormat::FIXED, "MAX_RES", "Maximum residual of the momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + if (!(config->GetLMParsedOptions()).SLM) { + /// DESCRIPTION: Maximum residual of the momentum thickness Reynolds number (LM model). + AddHistoryOutput("MAX_RE_THETA_T", "max[LM_2]", ScreenOutputFormat::FIXED, "MAX_RES", "Maximum residual of the momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + } break; case TURB_TRANS_MODEL::NONE: @@ -1093,7 +1099,10 @@ void CFlowOutput::AddHistoryOutputFields_ScalarBGS_RES(const CConfig* config) { /// DESCRIPTION: Maximum residual of the intermittency (LM model). AddHistoryOutput("BGS_INTERMITTENCY", "bgs[LM_1]", ScreenOutputFormat::FIXED, "BGS_RES", "BGS residual of the intermittency (LM model).", HistoryFieldType::RESIDUAL); /// DESCRIPTION: Maximum residual of the momentum thickness Reynolds number (LM model). - AddHistoryOutput("BGS_RE_THETA_T", "bgs[LM_2]", ScreenOutputFormat::FIXED, "BGS_RES", "BGS residual of the momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + if (!(config->GetLMParsedOptions()).SLM) { + /// DESCRIPTION: Maximum residual of the momentum thickness Reynolds number (LM model). + AddHistoryOutput("BGS_RE_THETA_T", "bgs[LM_2]", ScreenOutputFormat::FIXED, "BGS_RES", "BGS residual of the momentum thickness Reynolds number (LM model).", HistoryFieldType::RESIDUAL); + } break; case TURB_TRANS_MODEL::NONE: break; @@ -1186,10 +1195,15 @@ void CFlowOutput::LoadHistoryDataScalar(const CConfig* config, const CSolver* co SetHistoryOutputValue("RMS_INTERMITTENCY", log10(solver[TRANS_SOL]->GetRes_RMS(0))); SetHistoryOutputValue("RMS_RE_THETA_T",log10(solver[TRANS_SOL]->GetRes_RMS(1))); SetHistoryOutputValue("MAX_INTERMITTENCY", log10(solver[TRANS_SOL]->GetRes_Max(0))); - SetHistoryOutputValue("MAX_RE_THETA_T", log10(solver[TRANS_SOL]->GetRes_Max(1))); + if (!(config->GetLMParsedOptions()).SLM) { + SetHistoryOutputValue("RMS_RE_THETA_T",log10(solver[TRANS_SOL]->GetRes_RMS(1))); + SetHistoryOutputValue("MAX_RE_THETA_T", log10(solver[TRANS_SOL]->GetRes_Max(1))); + } if (multiZone) { SetHistoryOutputValue("BGS_INTERMITTENCY", log10(solver[TRANS_SOL]->GetRes_BGS(0))); - SetHistoryOutputValue("BGS_RE_THETA_T", log10(solver[TRANS_SOL]->GetRes_BGS(1))); + if (!(config->GetLMParsedOptions()).SLM) { + SetHistoryOutputValue("BGS_RE_THETA_T", log10(solver[TRANS_SOL]->GetRes_BGS(1))); + } } SetHistoryOutputValue("LINSOL_ITER_TRANS", solver[TRANS_SOL]->GetIterLinSolver()); SetHistoryOutputValue("LINSOL_RESIDUAL_TRANS", log10(solver[TRANS_SOL]->GetResLinSolver())); @@ -1262,6 +1276,33 @@ void CFlowOutput::SetVolumeOutputFieldsScalarSolution(const CConfig* config){ case TURB_TRANS_MODEL::LM: AddVolumeOutput("INTERMITTENCY", "LM_gamma", "SOLUTION", "LM intermittency"); AddVolumeOutput("RE_THETA_T", "LM_Re_t", "SOLUTION", "LM RE_THETA_T"); + AddVolumeOutput("RE_V", "Re_v", "DEBUG", "LM Re_v"); + AddVolumeOutput("RE_THETA_CORR", "LM_Corr_Rec", "DEBUG", "LM RE_THETA_CORR"); + AddVolumeOutput("PROD", "LM_Prod", "DEBUG", "LM PROD"); + AddVolumeOutput("DESTR", "LM_Destr", "DEBUG", "LM DESTR"); + AddVolumeOutput("F_ONSET1", "LM_F_onset1", "DEBUG", "LM F_ONSET1"); + AddVolumeOutput("F_ONSET2", "LM_F_onset2", "DEBUG", "LM F_ONSET2"); + AddVolumeOutput("F_ONSET3", "LM_F_onset3", "DEBUG", "LM F_ONSET3"); + AddVolumeOutput("F_ONSET", "LM_F_onset", "DEBUG", "LM F_ONSET"); + AddVolumeOutput("STRAINMAG", "StrainMag", "DEBUG", "LM STRAINMAG"); + AddVolumeOutput("LAMBDA_THETA", "Lambda_theta", "DEBUG", "LM Lambda_theta"); + AddVolumeOutput("DU_DS", "du_ds", "DEBUG", "LM du_ds"); + if ((config->GetLMParsedOptions()).SLM) { + AddVolumeOutput("TU", "Tu", "SOLUTION", "LM Tu"); + AddVolumeOutput("NORMAL_X", "Normal_x", "DEBUG", "LM Normal_x"); + AddVolumeOutput("NORMAL_Y", "Normal_y", "DEBUG", "LM Normal_y"); + AddVolumeOutput("NORMAL_Z", "Normal_z", "DEBUG", "LM Normal_z"); + if (!((config->GetLMParsedOptions()).Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM)) { + AddVolumeOutput("INTERMITTENCY_SEP", "LM_gamma_sep", "PRIMITIVE", "LM intermittency"); + AddVolumeOutput("INTERMITTENCY_EFF", "LM_gamma_eff", "PRIMITIVE", "LM RE_THETA_T"); + } + } + + if (!(config->GetLMParsedOptions()).SLM) { + AddVolumeOutput("INTERMITTENCY_SEP", "LM_gamma_sep", "PRIMITIVE", "LM intermittency"); + AddVolumeOutput("INTERMITTENCY_EFF", "LM_gamma_eff", "PRIMITIVE", "LM RE_THETA_T"); + } + AddVolumeOutput("TURB_INDEX", "Turb_index", "PRIMITIVE", "Turbulence index"); break; case TURB_TRANS_MODEL::NONE: @@ -1334,7 +1375,9 @@ void CFlowOutput::SetVolumeOutputFieldsScalarResidual(const CConfig* config) { switch (config->GetKind_Trans_Model()) { case TURB_TRANS_MODEL::LM: AddVolumeOutput("RES_INTERMITTENCY", "Residual_LM_intermittency", "RESIDUAL", "Residual of LM intermittency"); - AddVolumeOutput("RES_RE_THETA_T", "Residual_LM_RE_THETA_T", "RESIDUAL", "Residual of LM RE_THETA_T"); + if (!(config->GetLMParsedOptions()).SLM) { + AddVolumeOutput("RES_RE_THETA_T", "Residual_LM_RE_THETA_T", "RESIDUAL", "Residual of LM RE_THETA_T"); + } break; case TURB_TRANS_MODEL::NONE: @@ -1553,12 +1596,39 @@ void CFlowOutput::LoadVolumeDataScalar(const CConfig* config, const CSolver* con switch (config->GetKind_Trans_Model()) { case TURB_TRANS_MODEL::LM: SetVolumeOutputValue("INTERMITTENCY", iPoint, Node_Trans->GetSolution(iPoint, 0)); - SetVolumeOutputValue("RE_THETA_T", iPoint, Node_Trans->GetSolution(iPoint, 1)); - SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); - SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); + SetVolumeOutputValue("RE_V", iPoint, Node_Trans->GetRe_v(iPoint)); + SetVolumeOutputValue("RE_THETA_CORR", iPoint, Node_Trans->GetCorr_Rec(iPoint)); + SetVolumeOutputValue("PROD", iPoint, Node_Trans->GetProd(iPoint)); + SetVolumeOutputValue("DESTR", iPoint, Node_Trans->GetDestr(iPoint)); + SetVolumeOutputValue("F_ONSET1", iPoint, Node_Trans->GetF_onset1(iPoint)); + SetVolumeOutputValue("F_ONSET2", iPoint, Node_Trans->GetF_onset2(iPoint)); + SetVolumeOutputValue("F_ONSET3", iPoint, Node_Trans->GetF_onset3(iPoint)); + SetVolumeOutputValue("F_ONSET", iPoint, Node_Trans->GetF_onset(iPoint)); + SetVolumeOutputValue("STRAINMAG", iPoint, Node_Flow->GetStrainMag(iPoint)); + SetVolumeOutputValue("LAMBDA_THETA", iPoint, Node_Trans->GetLambda_theta(iPoint)); + SetVolumeOutputValue("DU_DS", iPoint, Node_Trans->Getduds(iPoint)); + if (!(config->GetLMParsedOptions()).SLM) { + SetVolumeOutputValue("RE_THETA_T", iPoint, Node_Trans->GetSolution(iPoint, 1)); + } else { + SetVolumeOutputValue("RE_THETA_T", iPoint, Node_Trans->GetRe_t(iPoint)); + SetVolumeOutputValue("TU", iPoint, Node_Trans->GetTu(iPoint)); + SetVolumeOutputValue("NORMAL_X", iPoint, Node_Trans->GetNormal_x(iPoint)); + SetVolumeOutputValue("NORMAL_Y", iPoint, Node_Trans->GetNormal_y(iPoint)); + SetVolumeOutputValue("NORMAL_Z", iPoint, Node_Trans->GetNormal_z(iPoint)); + if (!((config->GetLMParsedOptions()).Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM)) { + SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); + SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); + } + } + if (!(config->GetLMParsedOptions()).SLM) { + SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); + SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); + } SetVolumeOutputValue("TURB_INDEX", iPoint, Node_Turb->GetTurbIndex(iPoint)); SetVolumeOutputValue("RES_INTERMITTENCY", iPoint, trans_solver->LinSysRes(iPoint, 0)); - SetVolumeOutputValue("RES_RE_THETA_T", iPoint, trans_solver->LinSysRes(iPoint, 1)); + if (!(config->GetLMParsedOptions()).SLM) { + SetVolumeOutputValue("RES_RE_THETA_T", iPoint, trans_solver->LinSysRes(iPoint, 1)); + } break; case TURB_TRANS_MODEL::NONE: break; @@ -2667,7 +2737,7 @@ void CFlowOutput::WriteForcesBreakdown(const CConfig* config, const CSolver* flo case TURB_TRANS_MODEL::NONE: break; case TURB_TRANS_MODEL::LM: file << "Langtry and Menter's transition"; - if (config->GetLMParsedOptions().LM2015) { + if (config->GetLMParsedOptions().CrossFlow) { file << " w/ cross-flow corrections (2015)\n"; } else { file << " (2009)\n"; diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 1fdf2a47de19..a6d99018115a 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -49,6 +49,14 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh /*--- Dimension of the problem --> 2 Transport equations (intermittency, Reth) ---*/ nVar = 2; nPrimVar = 2; + + /*--- Check if Simplified version is used ---*/ + options = config->GetLMParsedOptions(); + if (options.SLM) { + nVar = 1; + nPrimVar = 1; + } + nPoint = geometry->GetnPoint(); nPointDomain = geometry->GetnPointDomain(); @@ -65,6 +73,11 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh TransCorrelations.SetOptions(options); TurbFamily = TurbModelFamily(config->GetKind_Turb_Model()); + isSepNeeded = true; + // If the Simplified model is used coupled with SST then we do not need the separation induced intermittency + // due to the added production term to k equation + if (options.SLM && options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) isSepNeeded = false; + /*--- Single grid simulation ---*/ if (iMesh == MESH_0) { @@ -101,8 +114,10 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh lowerlimit[0] = 1.0e-4; upperlimit[0] = 5.0; - lowerlimit[1] = 1.0e-4; - upperlimit[1] = 1.0e15; + if (!options.SLM) { + lowerlimit[1] = 1.0e-4; + upperlimit[1] = 1.0e15; + } /*--- Far-field flow state quantities and initialization. ---*/ const su2double Intensity = config->GetTurbulenceIntensity_FreeStream()*100.0; @@ -124,7 +139,9 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh } Solution_Inf[0] = Intermittency_Inf; - Solution_Inf[1] = ReThetaT_Inf; + if (!options.SLM) { + Solution_Inf[1] = ReThetaT_Inf; + } /*--- Initialize the solution to the far-field state everywhere. ---*/ nodes = new CTransLMVariable(Intermittency_Inf, ReThetaT_Inf, 1.0, 1.0, nPoint, nDim, nVar, config); @@ -155,7 +172,7 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh Inlet_TurbVars[iMarker].resize(nVertex[iMarker],nVar); for (unsigned long iVertex = 0; iVertex < nVertex[iMarker]; ++iVertex) { Inlet_TurbVars[iMarker](iVertex,0) = Intermittency_Inf; - Inlet_TurbVars[iMarker](iVertex,1) = ReThetaT_Inf; + if (!options.SLM) Inlet_TurbVars[iMarker](iVertex,1) = ReThetaT_Inf; } } @@ -178,6 +195,38 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain /*--- Upwind second order reconstruction and gradients ---*/ CommonPreprocessing(geometry, config, Output); + + if (options.SLM && options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) { + + auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + auto Normal = geometry->nodes->GetNormal(iPoint); + nodes->SetAuxVar(iPoint, 0, flowNodes->GetProjVel(iPoint, Normal)); + nodes->SetNormal(iPoint, Normal[0], Normal[1], Normal[2]); + } + END_SU2_OMP_FOR + + if (config->GetKind_Gradient_Method() == GREEN_GAUSS) { + SetAuxVar_Gradient_GG(geometry, config); + } + if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) { + SetAuxVar_Gradient_LS(geometry, config); + } + + + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + su2double AuxVarHere = 0.0; + auto Normal = geometry->nodes->GetNormal(iPoint); + for (auto iDim = 0u; iDim < nDim; iDim++) + AuxVarHere += Normal[iDim] * nodes->GetAuxVarGradient(iPoint, 0, iDim); + nodes->SetAuxVar(iPoint, 0, AuxVarHere); + } + END_SU2_OMP_FOR + + } + } void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh) { @@ -191,73 +240,103 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai SetSolution_Gradient_LS(geometry, config); } + AD::StartNoSharedReading(); - auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); - auto* turbNodes = su2staticcast_p(solver_container[TURB_SOL]->GetNodes()); - - SU2_OMP_FOR_STAT(omp_chunk_size) - for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { - - // Here the nodes already have the new solution, thus I have to compute everything from scratch - - const su2double rho = flowNodes->GetDensity(iPoint); - const su2double mu = flowNodes->GetLaminarViscosity(iPoint); - const su2double muT = turbNodes->GetmuT(iPoint); - const su2double dist = geometry->nodes->GetWall_Distance(iPoint); - su2double VorticityMag = GeometryToolbox::Norm(3, flowNodes->GetVorticity(iPoint)); - su2double StrainMag =flowNodes->GetStrainMag(iPoint); - VorticityMag = max(VorticityMag, 1e-12); - StrainMag = max(StrainMag, 1e-12); // safety against division by zero - const su2double Intermittency = nodes->GetSolution(iPoint,0); - const su2double Re_t = nodes->GetSolution(iPoint,1); - const su2double Re_v = rho*dist*dist*StrainMag/mu; - const su2double vel_u = flowNodes->GetVelocity(iPoint, 0); - const su2double vel_v = flowNodes->GetVelocity(iPoint, 1); - const su2double vel_w = (nDim ==3) ? flowNodes->GetVelocity(iPoint, 2) : 0.0; - const su2double VelocityMag = sqrt(vel_u*vel_u + vel_v*vel_v + vel_w*vel_w); - su2double omega = 0.0; - su2double k = 0.0; - if(TurbFamily == TURB_FAMILY::KW){ - omega = turbNodes->GetSolution(iPoint,1); - k = turbNodes->GetSolution(iPoint,0); - } - su2double Tu = 1.0; - if(TurbFamily == TURB_FAMILY::KW) - Tu = max(100.0*sqrt( 2.0 * k / 3.0 ) / VelocityMag,0.027); - if(TurbFamily == TURB_FAMILY::SA) - Tu = config->GetTurbulenceIntensity_FreeStream()*100; - - const su2double Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, Re_t); - - su2double R_t = 1.0; - if(TurbFamily == TURB_FAMILY::KW) - R_t = rho*k/ mu/ omega; - if(TurbFamily == TURB_FAMILY::SA) - R_t = muT/ mu; - - const su2double f_reattach = exp(-pow(R_t/20,4)); - su2double f_wake = 0.0; - if(TurbFamily == TURB_FAMILY::KW){ - const su2double re_omega = rho*omega*dist*dist/mu; - f_wake = exp(-pow(re_omega/(1.0e+05),2)); + + if(isSepNeeded){ + + AD::StartNoSharedReading(); + auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); + auto* turbNodes = su2staticcast_p(solver_container[TURB_SOL]->GetNodes()); + + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + + // Here the nodes already have the new solution, thus I have to compute everything from scratch + + const su2double rho = flowNodes->GetDensity(iPoint); + const su2double mu = flowNodes->GetLaminarViscosity(iPoint); + const su2double muT = turbNodes->GetmuT(iPoint); + const su2double dist = geometry->nodes->GetWall_Distance(iPoint); + su2double VorticityMag = GeometryToolbox::Norm(3, flowNodes->GetVorticity(iPoint)); + su2double StrainMag =flowNodes->GetStrainMag(iPoint); + VorticityMag = max(VorticityMag, 1e-12); + StrainMag = max(StrainMag, 1e-12); // safety against division by zero + const su2double Intermittency = nodes->GetSolution(iPoint,0); + const su2double Re_v = rho*dist*dist*StrainMag/mu; + const su2double VelocityMag = max(sqrt(flowNodes->GetVelocity2(iPoint)), 1e-20); + su2double omega = 0.0; + su2double k = 0.0; + if(TurbFamily == TURB_FAMILY::KW){ + omega = turbNodes->GetSolution(iPoint,1); + k = turbNodes->GetSolution(iPoint,0); + } + + su2double Re_t = 0.0; + su2double Corr_Rec = 0.0; + + if (options.SLM) { + Re_t = nodes->GetRe_t(iPoint); + Corr_Rec = nodes->GetCorr_Rec(iPoint); + } else { + Re_t = nodes->GetSolution(iPoint,1); + su2double Tu = 1.0; + if(TurbFamily == TURB_FAMILY::KW) + Tu = max(100.0*sqrt( 2.0 * k / 3.0 ) / VelocityMag,0.027); + if(TurbFamily == TURB_FAMILY::SA) + Tu = config->GetTurbulenceIntensity_FreeStream()*100; + + Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, Re_t); + } + + + // cout << Re_t << " " << Corr_Rec << endl; + // if (geometry->nodes->GetDomain(iPoint)) cout << "Point is on boundary" << endl; + + su2double R_t = 1.0; + if(TurbFamily == TURB_FAMILY::KW) + R_t = rho*k/ mu/ omega; + if(TurbFamily == TURB_FAMILY::SA) + R_t = muT/ mu; + + const su2double f_reattach = exp(-pow(R_t/20,4)); + + su2double f_wake = 0.0; + if(TurbFamily == TURB_FAMILY::KW){ + const su2double re_omega = rho*omega*dist*dist/mu; + f_wake = exp(-pow(re_omega/(1.0e+05),2)); + } + if(TurbFamily == TURB_FAMILY::SA) + f_wake = 1.0; + + //cout << "StrainMag = " << StrainMag << " rho = " << rho << " dist = " << dist << " Re_v = " << Re_v << " Corr_Rec = " << Corr_Rec << endl; + + const su2double theta_bl = Re_t*mu / rho /VelocityMag; + const su2double delta_bl = 7.5*theta_bl; + const su2double delta = 50.0*VorticityMag*dist/VelocityMag*delta_bl + 1e-20; + const su2double var1 = (Intermittency-1.0/50.0)/(1.0-1.0/50.0); + const su2double var2 = 1.0 - pow(var1,2.0); + const su2double f_theta = min(max(f_wake*exp(-pow(dist/delta, 4)), var2), 1.0); + su2double Intermittency_Sep = 2.0*max(0.0, Re_v/(3.235*Corr_Rec)-1.0)*f_reattach; + //if (Intermittency_Sep>1.0) cout << "StrainMag = " << StrainMag << " rho = " << rho << " dist = " << dist << " Re_v = " << Re_v << " Corr_Rec = " << Corr_Rec << " Intermittency: " << Intermittency_Sep << " f_reattach = " << f_reattach << endl; + Intermittency_Sep = min(Intermittency_Sep,2.0)*f_theta; + Intermittency_Sep = min(max(0.0, Intermittency_Sep), 2.0); + nodes -> SetIntermittencySep(iPoint, Intermittency_Sep); + nodes -> SetIntermittencyEff(iPoint, Intermittency_Sep); + } - if(TurbFamily == TURB_FAMILY::SA) - f_wake = 1.0; - - const su2double theta_bl = Re_t*mu / rho /VelocityMag; - const su2double delta_bl = 7.5*theta_bl; - const su2double delta = 50.0*VorticityMag*dist/VelocityMag*delta_bl + 1e-20; - const su2double var1 = (Intermittency-1.0/50.0)/(1.0-1.0/50.0); - const su2double var2 = 1.0 - pow(var1,2.0); - const su2double f_theta = min(max(f_wake*exp(-pow(dist/delta, 4)), var2), 1.0); - su2double Intermittency_Sep = 2.0*max(0.0, Re_v/(3.235*Corr_Rec)-1.0)*f_reattach; - Intermittency_Sep = min(Intermittency_Sep,2.0)*f_theta; - Intermittency_Sep = min(max(0.0, Intermittency_Sep), 2.0); - nodes -> SetIntermittencySep(iPoint, Intermittency_Sep); - nodes -> SetIntermittencyEff(iPoint, Intermittency_Sep); + END_SU2_OMP_FOR } - END_SU2_OMP_FOR + else { + + // Effective intermittency and separation intermittency are not taken into account here! There is the added production term in the k-equation + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + nodes -> SetIntermittencyEff(iPoint, nodes->GetSolution(iPoint,0)); + } + END_SU2_OMP_FOR + } AD::EndNoSharedReading(); } @@ -333,15 +412,36 @@ void CTransLMSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta /*--- Set coordinate (for debugging) ---*/ numerics->SetCoord(geometry->nodes->GetCoord(iPoint), nullptr); - if (options.LM2015) { + if (options.CrossFlow && !options.SLM) { /*--- Set local grid length (for LM2015)*/ numerics->SetLocalGridLength(geometry->nodes->GetMaxLength(iPoint)); } + if(options.SLM) { + if (options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) numerics->SetAuxVar(nodes->GetAuxVar(iPoint, 0)); + numerics->SetF2(turbNodes->GetF2blending(iPoint)); + } + /*--- Compute the source term ---*/ auto residual = numerics->ComputeResidual(config); + if(options.SLM) { + nodes->SetRe_t(iPoint, numerics->GetRe_t()); + nodes->SetTu(iPoint, numerics->GetTu()); + } + + nodes->SetRe_v(iPoint, numerics->GetRe_v()); + nodes->SetCorr_Rec(iPoint, numerics->GetCorr_Rec()); + nodes->SetProd(iPoint, numerics->GetProd()); + nodes->SetDestr(iPoint, numerics->GetDestr()); + nodes->SetF_onset1(iPoint, numerics->GetF_onset1()); + nodes->SetF_onset2(iPoint, numerics->GetF_onset2()); + nodes->SetF_onset3(iPoint, numerics->GetF_onset3()); + nodes->SetF_onset(iPoint, numerics->GetF_onset()); + nodes->SetLambda_theta(iPoint, numerics->GetLambda_theta()); + nodes->Setduds(iPoint, numerics->Getduds()); + /*--- Subtract residual and the Jacobian ---*/ LinSysRes.SubtractBlock(iPoint, residual); diff --git a/SU2_CFD/src/solvers/CTurbSASolver.cpp b/SU2_CFD/src/solvers/CTurbSASolver.cpp index f53596e99017..6de6dd03ac34 100644 --- a/SU2_CFD/src/solvers/CTurbSASolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSASolver.cpp @@ -269,7 +269,7 @@ void CTurbSASolver::Postprocessing(CGeometry *geometry, CSolver **solver_contain } shearStress = sqrt(shearStress); - FrictionVelocity = sqrt(shearStress/flowNodes->GetDensity(iPoint)); + FrictionVelocity = sqrt(shearStress/max(flowNodes->GetDensity(iPoint), 1e-20)); } else { su2double VorticityMag = max(GeometryToolbox::Norm(3, flowNodes->GetVorticity(iPoint)), 1e-12); FrictionVelocity = sqrt(flowNodes->GetLaminarViscosity(iPoint)*VorticityMag); diff --git a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp index 555f8e771559..d99b294f1381 100644 --- a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp @@ -259,10 +259,10 @@ void CTurbSSTSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai } shearStress = sqrt(shearStress); - const su2double FrictionVelocity = sqrt(shearStress/flowNodes->GetDensity(iPoint)); + const su2double FrictionVelocity = sqrt(shearStress/max(flowNodes->GetDensity(iPoint),1e-20)); const su2double wall_dist = geometry->nodes->GetWall_Distance(jPoint); const su2double Derivative = flowNodes->GetLaminarViscosity(jPoint) * pow(nodes->GetSolution(jPoint, 0), 0.673) / wall_dist; - const su2double turbulence_index = 6.1 * Derivative / pow(FrictionVelocity, 2.346); + const su2double turbulence_index = 6.1 * Derivative / max(pow(FrictionVelocity, 2.346),1e-20); nodes->SetTurbIndex(iPoint, turbulence_index); diff --git a/SU2_CFD/src/variables/CTransLMVariable.cpp b/SU2_CFD/src/variables/CTransLMVariable.cpp index 551968b1c35b..dca6f89113bf 100644 --- a/SU2_CFD/src/variables/CTransLMVariable.cpp +++ b/SU2_CFD/src/variables/CTransLMVariable.cpp @@ -31,10 +31,19 @@ CTransLMVariable::CTransLMVariable(su2double Intermittency, su2double ReThetaT, su2double gammaSep, su2double gammaEff, unsigned long npoint, unsigned long ndim, unsigned long nvar, CConfig *config) : CTurbVariable(npoint, ndim, nvar, config) { - for(unsigned long iPoint=0; iPointGetLMParsedOptions(); + + if (!options.SLM) { + for(unsigned long iPoint=0; iPointGetSSTParsedOptions(); + lmParsedOptions = config->GetLMParsedOptions(); for(unsigned long iPoint=0; iPoint Date: Mon, 1 Jul 2024 10:57:57 +0200 Subject: [PATCH 19/61] - corrected bu in output --- SU2_CFD/src/output/CFlowOutput.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index bf45c281b0fa..baafc7175948 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -1193,7 +1193,6 @@ void CFlowOutput::LoadHistoryDataScalar(const CConfig* config, const CSolver* co switch (config->GetKind_Trans_Model()) { case TURB_TRANS_MODEL::LM: SetHistoryOutputValue("RMS_INTERMITTENCY", log10(solver[TRANS_SOL]->GetRes_RMS(0))); - SetHistoryOutputValue("RMS_RE_THETA_T",log10(solver[TRANS_SOL]->GetRes_RMS(1))); SetHistoryOutputValue("MAX_INTERMITTENCY", log10(solver[TRANS_SOL]->GetRes_Max(0))); if (!(config->GetLMParsedOptions()).SLM) { SetHistoryOutputValue("RMS_RE_THETA_T",log10(solver[TRANS_SOL]->GetRes_RMS(1))); From a6fe9bca59ce02409b3b80c2d80f57fb1a7bbcb5 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 13 Sep 2024 14:54:12 +0200 Subject: [PATCH 20/61] - finish update --- Common/include/geometry/dual_grid/CPoint.hpp | 39 ----------- .../turbulent/transition/trans_diffusion.hpp | 68 ------------------- SU2_CFD/include/variables/CVariable.hpp | 45 ------------ externals/codi | 2 +- externals/medi | 2 +- externals/mel | 2 +- externals/opdi | 2 +- subprojects/CoolProp | 2 +- 8 files changed, 5 insertions(+), 157 deletions(-) diff --git a/Common/include/geometry/dual_grid/CPoint.hpp b/Common/include/geometry/dual_grid/CPoint.hpp index 79d5c2076c1f..ae725fea2589 100644 --- a/Common/include/geometry/dual_grid/CPoint.hpp +++ b/Common/include/geometry/dual_grid/CPoint.hpp @@ -514,27 +514,6 @@ class CPoint { inline su2double& GetWall_Distance(unsigned long iPoint) { return Wall_Distance(iPoint); } inline const su2double& GetWall_Distance(unsigned long iPoint) const { return Wall_Distance(iPoint); } - /*! - * \brief Get the index of the closest wall element. - * \param[in] iPoint - Index of the point. - * \param[out] ClosestWall_Elem - ID of the closest element on a wall boundary. - */ - inline unsigned long GetClosestWall_Elem(unsigned long iPoint) {return ClosestWall_Elem(iPoint);} - - /*! - * \brief Get the marker of the closest wall marker. - * \param[in] iPoint - Index of the point. - * \param[out] ClosestWall_Marker - MarkerID of the closest wall boundary. - */ - inline unsigned long GetClosestWall_Marker(unsigned long iPoint) {return ClosestWall_Marker(iPoint);} - - /*! - * \brief Get the rank of the closest wall marker. - * \param[in] iPoint - Index of the point. - * \param[out] ClosestWall_Rank - RankID of the closest wall boundary. - */ - inline unsigned long GetClosestWall_Rank(unsigned long iPoint) {return ClosestWall_Rank(iPoint);} - /*! * \brief Set the value of the distance to the nearest wall. * \param[in] iPoint - Index of the point. @@ -567,24 +546,6 @@ class CPoint { */ inline su2double *GetNormal(unsigned long iPoint) { return Normals[iPoint]; } - /*! - * \brief Set the value of the normal of the nearest wall element. - * \param[in] iPoint - Index of the point. - * \param[in] normal - Value of the normal. - */ - template - inline void SetNormal(unsigned long iPoint, Normals_type const&normal) { - for (unsigned long iDim = 0; iDim < nDim; iDim++) - Normals(iPoint,iDim) = normal[iDim]; - } - - /*! - * \brief Set the value of the normal of the nearest wall element. - * \param[in] iPoint - Index of the point. - * \return normal to the normal of the nearest wall element. - */ - inline su2double *GetNormal(unsigned long iPoint) { return Normals[iPoint]; } - /*! * \brief Set the value of the distance to a sharp edge. * \param[in] iPoint - Index of the point. diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp index 0961c8b8b823..4beb7d374eb2 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_diffusion.hpp @@ -105,74 +105,6 @@ class CAvgGrad_TransLM final : public CAvgGrad_Scalar { }; -/*! - * \class CAvgGrad_TransSLM - * \brief Class for computing viscous term using average of gradient with correction (Simplified LM transition model). - * \ingroup ViscDiscr - * \author S. Kang. - */ -template -class CAvgGrad_TransSLM final : public CAvgGrad_Scalar { -private: - using Base = CAvgGrad_Scalar; - using Base::Laminar_Viscosity_i; - using Base::Laminar_Viscosity_j; - using Base::Eddy_Viscosity_i; - using Base::Eddy_Viscosity_j; - using Base::Density_i; - using Base::Density_j; - using Base::ScalarVar_i; - using Base::ScalarVar_j; - using Base::Proj_Mean_GradScalarVar; - using Base::proj_vector_ij; - using Base::Flux; - using Base::Jacobian_i; - using Base::Jacobian_j; - - /*! - * \brief Adds any extra variables to AD - */ - void ExtraADPreaccIn() override {} - - /*! - * \brief LM transition model specific steps in the ComputeResidual method - * \param[in] config - Definition of the particular problem. - */ - void FinishResidualCalc(const CConfig* config) override { - const bool implicit = config->GetKind_TimeIntScheme() == EULER_IMPLICIT; - - /*--- Compute mean effective dynamic viscosity ---*/ - const su2double diff_i_gamma = Laminar_Viscosity_i + Eddy_Viscosity_i; - const su2double diff_j_gamma = Laminar_Viscosity_j + Eddy_Viscosity_j; - - const su2double diff_gamma = 0.5*(diff_i_gamma + diff_j_gamma); - - Flux[0] = diff_gamma*Proj_Mean_GradScalarVar[0]; - - /*--- For Jacobians -> Use of TSL (Thin Shear Layer) approx. to compute derivatives of the gradients ---*/ - if (implicit) { - const su2double proj_on_rho_i = proj_vector_ij/Density_i; - Jacobian_i[0][0] = -diff_gamma*proj_on_rho_i; - - const su2double proj_on_rho_j = proj_vector_ij/Density_j; - Jacobian_j[0][0] = diff_gamma*proj_on_rho_j; - } - } - -public: - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] correct_grad - Whether to correct gradient for skewness. - * \param[in] config - Definition of the particular problem. - */ - CAvgGrad_TransSLM(unsigned short val_nDim, unsigned short val_nVar, bool correct_grad, const CConfig* config) - : CAvgGrad_Scalar(val_nDim, val_nVar, correct_grad, config){ - } - -}; - /*! * \class CAvgGrad_TransSLM * \brief Class for computing viscous term using average of gradient with correction (Simplified LM transition model). diff --git a/SU2_CFD/include/variables/CVariable.hpp b/SU2_CFD/include/variables/CVariable.hpp index aa4810328c93..9c51ffafb39b 100644 --- a/SU2_CFD/include/variables/CVariable.hpp +++ b/SU2_CFD/include/variables/CVariable.hpp @@ -1699,51 +1699,6 @@ class CVariable { */ inline virtual void SetIntermittencyEff(unsigned long iPoint, su2double val_Intermittency_eff) {} - - /*! - * \brief Set Value of Transition Momentum Thickness Reynolds number from correlations. - */ - inline virtual void SetCorr_Rec(unsigned long iPoint, su2double val_Corr_Rec) {}; - inline virtual void SetTu(unsigned long iPoint, su2double val_Tu) {}; - inline virtual void SetLambda_theta(unsigned long iPoint, su2double val_Lambda_theta) {}; - inline virtual void Setduds(unsigned long iPoint, su2double val_duds) {}; - inline virtual void SetRe_v(unsigned long iPoint, su2double val_Re_v) {}; - inline virtual void SetProd(unsigned long iPoint, su2double val_Prod) {}; - inline virtual void SetDestr(unsigned long iPoint, su2double val_Destr) {}; - inline virtual void SetF_onset1(unsigned long iPoint, su2double val_F_onset1) {}; - inline virtual void SetF_onset2(unsigned long iPoint, su2double val_F_onset2) {}; - inline virtual void SetF_onset3(unsigned long iPoint, su2double val_F_onset3) {}; - inline virtual void SetF_onset(unsigned long iPoint, su2double val_F_onset1) {}; - inline virtual void SetNormal(unsigned long iPoint, su2double val_normal_x, su2double val_normal_y, su2double val_normal_z) {}; - - /*! - * \brief Get Value of Transition Momentum Thickness Reynolds number from correlations. - */ - inline virtual su2double GetCorr_Rec(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetTu(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetLambda_theta(unsigned long iPoint) const { return 0.0; } - inline virtual su2double Getduds(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetRe_v(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetProd(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetDestr(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetF_onset1(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetF_onset2(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetF_onset3(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetF_onset(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetNormal_x(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetNormal_y(unsigned long iPoint) const { return 0.0; } - inline virtual su2double GetNormal_z(unsigned long iPoint) const { return 0.0; } - - /*! - * \brief Set Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). - */ - inline virtual void SetRe_t(unsigned long iPoint, su2double val_Re_t) {}; - - /*! - * \brief Get Value of Momentum Thickness Reynolds number from correlations (substitute to the second equation of original LM model). - */ - inline virtual su2double GetRe_t(unsigned long iPoint) const { return 0.0; } - /*! * \brief Set Value of Transition Momentum Thickness Reynolds number from correlations. */ diff --git a/externals/codi b/externals/codi index c6b039e5c9ed..96ac78ec5bcc 160000 --- a/externals/codi +++ b/externals/codi @@ -1 +1 @@ -Subproject commit c6b039e5c9edb7675f90ffc725f9dd8e66571264 +Subproject commit 96ac78ec5bcc5ac25b785e79b16ed76fca22d736 diff --git a/externals/medi b/externals/medi index ab3a7688f6d5..6aef76912e70 160000 --- a/externals/medi +++ b/externals/medi @@ -1 +1 @@ -Subproject commit ab3a7688f6d518f8d940eb61a341d89f51922ba4 +Subproject commit 6aef76912e7099c4f08c9705848797ca9e8070da diff --git a/externals/mel b/externals/mel index 46205ab019e5..2484cd3258ef 160000 --- a/externals/mel +++ b/externals/mel @@ -1 +1 @@ -Subproject commit 46205ab019e5224559091375a6d71aabae6bc5b9 +Subproject commit 2484cd3258ef800a10e361016cb341834ee7930b diff --git a/externals/opdi b/externals/opdi index 8c8979881725..1aabf5bd1ed7 160000 --- a/externals/opdi +++ b/externals/opdi @@ -1 +1 @@ -Subproject commit 8c89798817253abb017d857a0ae7f0520187645c +Subproject commit 1aabf5bd1ed77611742eb655002f2ac7a3dddef9 diff --git a/subprojects/CoolProp b/subprojects/CoolProp index bafdea1f39ee..0ce42fcf3bb2 160000 --- a/subprojects/CoolProp +++ b/subprojects/CoolProp @@ -1 +1 @@ -Subproject commit bafdea1f39ee873a6bb9833e3a21fe41f90b85e8 +Subproject commit 0ce42fcf3bb2c373512bc825a4f0c1973a78f307 From 266cbd7fe1b186f4dec8085028de2a8f9c7ea63a Mon Sep 17 00:00:00 2001 From: rois1995 Date: Mon, 3 Mar 2025 08:43:40 +0100 Subject: [PATCH 21/61] Correct muT computation in SST --- SU2_CFD/src/solvers/CTurbSSTSolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp index 3f82a1248a83..749b91fe5de1 100644 --- a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp @@ -230,7 +230,7 @@ void CTurbSSTSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai const su2double dist = geometry->nodes->GetWall_Distance(iPoint); const su2double VorticityMag = max(GeometryToolbox::Norm(3, flowNodes->GetVorticity(iPoint)), 1e-12); - const su2double StrainMag = max(nodes->GetStrainMag(iPoint), 1e-12); + const su2double StrainMag = max(flowNodes->GetStrainMag(iPoint), 1e-12); nodes->SetBlendingFunc(iPoint, mu, dist, rho, config->GetKind_Trans_Model()); const su2double F2 = nodes->GetF2blending(iPoint); From 881b57418aa70c2c50f6f324d61338337fe00ac4 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Mon, 3 Mar 2025 10:01:57 +0100 Subject: [PATCH 22/61] - Remove debug options --- SU2_CFD/src/SU2_CFD.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/SU2_CFD.cpp b/SU2_CFD/src/SU2_CFD.cpp index 6bd8a6a383f0..f32efe12fbd6 100644 --- a/SU2_CFD/src/SU2_CFD.cpp +++ b/SU2_CFD/src/SU2_CFD.cpp @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) { /*--- Uncomment the following line if runtime NaN catching is desired. ---*/ // feenableexcept(FE_INVALID | FE_OVERFLOW | FE_DIVBYZERO ); - feenableexcept(FE_OVERFLOW | FE_DIVBYZERO ); + // feenableexcept(FE_OVERFLOW | FE_DIVBYZERO ); /*--- Create a pointer to the main SU2 Driver ---*/ From 5aa683fa99232f53228ff894415682b0f8385282 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Mon, 3 Mar 2025 14:32:58 +0100 Subject: [PATCH 23/61] - Reformat some lines --- Common/include/option_structure.hpp | 4 ++++ .../numerics/turbulent/transition/trans_sources.hpp | 4 ++-- SU2_CFD/src/solvers/CTransLMSolver.cpp | 7 +------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp index 7e7c1d511430..f9c354eab381 100644 --- a/Common/include/option_structure.hpp +++ b/Common/include/option_structure.hpp @@ -1353,6 +1353,10 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh SU2_MPI::Error("Two correlations selected for LM_OPTIONS. Please choose only one.", CURRENT_FUNCTION); } + if (NFoundCorrelations_SLM > 1) { + SU2_MPI::Error("Two SLM correlations selected for LM_OPTIONS. Please choose only one.", CURRENT_FUNCTION); + } + if (LMParsedOptions.Correlation == TURB_TRANS_CORRELATION::DEFAULT){ if (Kind_Turb_Model == TURB_MODEL::SST) { LMParsedOptions.Correlation = TURB_TRANS_CORRELATION::MENTER_LANGTRY; diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index b75d29cd090c..c92cc038d050 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -117,8 +117,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { AD::SetPreaccIn(PrimVar_Grad_i, nDim + idx.Velocity(), nDim); AD::SetPreaccIn(Vorticity_i, 3); - su2double VorticityMag = - sqrt(Vorticity_i[0] * Vorticity_i[0] + Vorticity_i[1] * Vorticity_i[1] + Vorticity_i[2] * Vorticity_i[2]); + const su2double VorticityMag = max(GeometryToolbox::Norm(3, Vorticity_i), 1e-20); const su2double vel_u = V_i[idx.Velocity()]; const su2double vel_v = V_i[1 + idx.Velocity()]; @@ -278,6 +277,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { VelocityNormalized[1] = vel_v / Velocity_Mag; if (nDim == 3) VelocityNormalized[2] = vel_w / Velocity_Mag; + // const su2double StreamwiseVort = abs(GeometryToolbox::DotProduct(VelocityNormalized, Vorticity_i)); su2double StreamwiseVort = 0.0; for (auto iDim = 0u; iDim < nDim; iDim++) { StreamwiseVort += VelocityNormalized[iDim] * Vorticity_i[iDim]; diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 08be4b25dfb4..ba88784ab8c7 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -128,12 +128,7 @@ CTransLMSolver::CTransLMSolver(CGeometry *geometry, CConfig *config, unsigned sh /*--- Momentum thickness Reynolds number, initialized from freestream turbulent intensity*/ if (Intensity <= 1.3) { - if(Intensity >=0.027) { - ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(Intensity*Intensity)); - } - else { - ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(0.27*0.27)); - } + ReThetaT_Inf = (1173.51-589.428*Intensity+0.2196/(pow(max(Intensity, 0.027), 2.0))); } else if(Intensity>1.3) { ReThetaT_Inf = 331.5*pow(Intensity-0.5658,-0.671); From a5a73aafdc4864554d1985485c4f3543d7adf425 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 6 Mar 2025 15:52:04 +0100 Subject: [PATCH 24/61] Fix compilation bug --- SU2_CFD/include/variables/CFlowVariable.hpp | 4 ++-- SU2_CFD/include/variables/CVariable.hpp | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/SU2_CFD/include/variables/CFlowVariable.hpp b/SU2_CFD/include/variables/CFlowVariable.hpp index d4d770f0ba8d..e705a18892f9 100644 --- a/SU2_CFD/include/variables/CFlowVariable.hpp +++ b/SU2_CFD/include/variables/CFlowVariable.hpp @@ -260,11 +260,11 @@ class CFlowVariable : public CVariable { * \param[in] iPoint - Point index. * \return Value of magnitude. */ - inline su2double GetStrainMag(unsigned long iPoint) const { return StrainMag(iPoint); } + inline su2double GetStrainMag(unsigned long iPoint) const final { return StrainMag(iPoint); } /*! * \brief Get the entire vector of the rate of strain magnitude. * \return Vector of magnitudes. */ - inline su2activevector& GetStrainMag() { return StrainMag; } + inline su2activevector& GetStrainMag() final { return StrainMag; } }; diff --git a/SU2_CFD/include/variables/CVariable.hpp b/SU2_CFD/include/variables/CVariable.hpp index 6bf8f2e54a45..70273c27ce4c 100644 --- a/SU2_CFD/include/variables/CVariable.hpp +++ b/SU2_CFD/include/variables/CVariable.hpp @@ -1147,6 +1147,19 @@ class CVariable { inline virtual su2double *GetVorticity(unsigned long iPoint) { return nullptr; } inline virtual const su2double *GetVorticity(unsigned long iPoint) const { return nullptr; } + /*! + * \brief Get the magnitude of rate of strain. + * \param[in] iPoint - Point index. + * \return Value of magnitude. + */ + inline virtual su2double GetStrainMag(unsigned long iPoint) const { } + + /*! + * \brief Get the entire vector of the rate of strain magnitude. + * \return Vector of magnitudes. + */ + inline virtual su2activevector& GetStrainMag() { } + /*! * \brief A virtual member. * \param[in] iPoint - Point index. From abc9d49fb67f53824daf8183748d5e258fb11423 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 6 Mar 2025 16:07:42 +0100 Subject: [PATCH 25/61] Remove StrainMag from outputs --- SU2_CFD/include/variables/CFlowVariable.hpp | 4 ++-- SU2_CFD/include/variables/CVariable.hpp | 15 +-------------- SU2_CFD/src/output/CFlowOutput.cpp | 2 -- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/SU2_CFD/include/variables/CFlowVariable.hpp b/SU2_CFD/include/variables/CFlowVariable.hpp index e705a18892f9..d4d770f0ba8d 100644 --- a/SU2_CFD/include/variables/CFlowVariable.hpp +++ b/SU2_CFD/include/variables/CFlowVariable.hpp @@ -260,11 +260,11 @@ class CFlowVariable : public CVariable { * \param[in] iPoint - Point index. * \return Value of magnitude. */ - inline su2double GetStrainMag(unsigned long iPoint) const final { return StrainMag(iPoint); } + inline su2double GetStrainMag(unsigned long iPoint) const { return StrainMag(iPoint); } /*! * \brief Get the entire vector of the rate of strain magnitude. * \return Vector of magnitudes. */ - inline su2activevector& GetStrainMag() final { return StrainMag; } + inline su2activevector& GetStrainMag() { return StrainMag; } }; diff --git a/SU2_CFD/include/variables/CVariable.hpp b/SU2_CFD/include/variables/CVariable.hpp index 70273c27ce4c..c8269202cd8b 100644 --- a/SU2_CFD/include/variables/CVariable.hpp +++ b/SU2_CFD/include/variables/CVariable.hpp @@ -1146,20 +1146,7 @@ class CVariable { */ inline virtual su2double *GetVorticity(unsigned long iPoint) { return nullptr; } inline virtual const su2double *GetVorticity(unsigned long iPoint) const { return nullptr; } - - /*! - * \brief Get the magnitude of rate of strain. - * \param[in] iPoint - Point index. - * \return Value of magnitude. - */ - inline virtual su2double GetStrainMag(unsigned long iPoint) const { } - - /*! - * \brief Get the entire vector of the rate of strain magnitude. - * \return Vector of magnitudes. - */ - inline virtual su2activevector& GetStrainMag() { } - + /*! * \brief A virtual member. * \param[in] iPoint - Point index. diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index f97cf5e64fe2..372673932eef 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -1283,7 +1283,6 @@ void CFlowOutput::SetVolumeOutputFieldsScalarSolution(const CConfig* config){ AddVolumeOutput("F_ONSET2", "LM_F_onset2", "DEBUG", "LM F_ONSET2"); AddVolumeOutput("F_ONSET3", "LM_F_onset3", "DEBUG", "LM F_ONSET3"); AddVolumeOutput("F_ONSET", "LM_F_onset", "DEBUG", "LM F_ONSET"); - AddVolumeOutput("STRAINMAG", "StrainMag", "DEBUG", "LM STRAINMAG"); AddVolumeOutput("LAMBDA_THETA", "Lambda_theta", "DEBUG", "LM Lambda_theta"); AddVolumeOutput("DU_DS", "du_ds", "DEBUG", "LM du_ds"); if ((config->GetLMParsedOptions()).SLM) { @@ -1603,7 +1602,6 @@ void CFlowOutput::LoadVolumeDataScalar(const CConfig* config, const CSolver* con SetVolumeOutputValue("F_ONSET2", iPoint, Node_Trans->GetF_onset2(iPoint)); SetVolumeOutputValue("F_ONSET3", iPoint, Node_Trans->GetF_onset3(iPoint)); SetVolumeOutputValue("F_ONSET", iPoint, Node_Trans->GetF_onset(iPoint)); - SetVolumeOutputValue("STRAINMAG", iPoint, Node_Flow->GetStrainMag(iPoint)); SetVolumeOutputValue("LAMBDA_THETA", iPoint, Node_Trans->GetLambda_theta(iPoint)); SetVolumeOutputValue("DU_DS", iPoint, Node_Trans->Getduds(iPoint)); if (!(config->GetLMParsedOptions()).SLM) { From 1b1bc8a985e310b22ce7524a2d19a8f44a4953e9 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 6 Mar 2025 18:38:44 +0100 Subject: [PATCH 26/61] - Fix compilation bugs on Github Part 1 --- .../turbulent/transition/trans_sources.hpp | 26 +++---------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index c92cc038d050..d6ade40095a8 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -456,19 +456,12 @@ class CSourcePieceWise_TransSLM final : public CNumerics { AD::SetPreaccIn(PrimVar_Grad_i, nDim + idx.Velocity(), nDim); AD::SetPreaccIn(Vorticity_i, 3); - su2double VorticityMag = - sqrt(Vorticity_i[0] * Vorticity_i[0] + Vorticity_i[1] * Vorticity_i[1] + Vorticity_i[2] * Vorticity_i[2]); + const su2double VorticityMag = GeometryToolbox::Norm(3, Vorticity_i); const su2double vel_u = V_i[idx.Velocity()]; const su2double vel_v = V_i[1 + idx.Velocity()]; const su2double vel_w = (nDim == 3) ? V_i[2 + idx.Velocity()] : 0.0; - su2double Velocity[nDim]; - Velocity[0] = vel_u; - Velocity[1] = vel_v; - if(nDim == 3) Velocity[2] = vel_w; - - const su2double Velocity_Mag = max(sqrt(vel_u * vel_u + vel_v * vel_v + vel_w * vel_w), 1e-20); AD::SetPreaccIn(V_i[idx.Density()], V_i[idx.LaminarViscosity()], V_i[idx.EddyViscosity()]); @@ -482,8 +475,8 @@ class CSourcePieceWise_TransSLM final : public CNumerics { if (dist_i > 1e-10) { su2double Tu_L = 1.0; + // Local value of the Turbulence intensity that makes it galileian invariant. Look at Eq. 7 in https://doi.org/10.1007/s10494-015-9622-4 if (TurbFamily == TURB_FAMILY::KW) Tu_L = min(100.0 * sqrt(2.0 * ScalarVar_i[0] / 3.0) / (ScalarVar_i[1]*dist_i), 100.0); - // if (TurbFamily == TURB_FAMILY::KW) Tu_L = min(100.0 * sqrt(2.0 * ScalarVar_i[0] / 3.0) / (Velocity_Mag), 100.0); if (TurbFamily == TURB_FAMILY::SA) Tu_L = config->GetTurbulenceIntensity_FreeStream() * 100; Tu_Here = Tu_L; @@ -496,24 +489,11 @@ class CSourcePieceWise_TransSLM final : public CNumerics { if (TurbFamily == TURB_FAMILY::KW) R_t = Density_i * ScalarVar_i[0] / (Laminar_Viscosity_i * ScalarVar_i[1]); if (TurbFamily == TURB_FAMILY::SA) R_t = Eddy_Viscosity_i / Laminar_Viscosity_i; - /*-- Gradient of velocity magnitude ---*/ - - // su2double du_ds = 0.0; - // for (int i = 0; i < nDim; i++) - // for (int j = 0; j < nDim; j++) - // du_ds = du_ds + Velocity[i]*Velocity[j]*PrimVar_Grad_i[i][j]; - - // du_ds = du_ds/(Velocity_Mag*Velocity_Mag); - - // const su2double lambda_theta = -7.57e-3 * du_ds * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128; const su2double lambda_theta = max(min(-7.57e-3 * AuxVar * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128, 1.0), -1.0); - // const su2double lambda_theta = du_ds * dist_i * dist_i * Density_i / Laminar_Viscosity_i; - // duds_Here = du_ds; + duds_Here = AuxVar; lambda_theta_Here = lambda_theta; - // const su2double lambda_theta = 7.57e-3 * AuxVar * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128; - /*--- Corr_RetC correlation*/ Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, lambda_theta, dist_i, VorticityMag, Velocity_Mag); Corr_Rec = Re_t; // If the MENTER_SLM correlation is used then they are the same thing From 30b4c14066243ef045b03a18c4c01745fd7fb1c7 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 6 Mar 2025 19:21:37 +0100 Subject: [PATCH 27/61] Update codiPack version to 2.0 --- meson_scripts/init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson_scripts/init.py b/meson_scripts/init.py index 67a2e41a2ecc..61ec81799cbf 100755 --- a/meson_scripts/init.py +++ b/meson_scripts/init.py @@ -56,7 +56,7 @@ def init_submodules( # This information of the modules is used if projects was not cloned using git # The sha tag must be maintained manually to point to the correct commit - sha_version_codi = "762ba7698e3ceaa1b17aa299421ddd418f00b823" + sha_version_codi = "c549e49b8d0910ab237adf5cae40aca507063f60" github_repo_codi = "https://github.com/scicompkl/CoDiPack" sha_version_medi = "7d550831e0e233a85b9d9af9c181d7ecb2929946" github_repo_medi = "https://github.com/SciCompKL/MeDiPack" From 7d1c6125176ea4a474f94652f083a1cb6251ec59 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 6 Mar 2025 19:27:46 +0100 Subject: [PATCH 28/61] Revert "Update codiPack version to 2.0" This reverts commit 30b4c14066243ef045b03a18c4c01745fd7fb1c7. --- meson_scripts/init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson_scripts/init.py b/meson_scripts/init.py index 61ec81799cbf..67a2e41a2ecc 100755 --- a/meson_scripts/init.py +++ b/meson_scripts/init.py @@ -56,7 +56,7 @@ def init_submodules( # This information of the modules is used if projects was not cloned using git # The sha tag must be maintained manually to point to the correct commit - sha_version_codi = "c549e49b8d0910ab237adf5cae40aca507063f60" + sha_version_codi = "762ba7698e3ceaa1b17aa299421ddd418f00b823" github_repo_codi = "https://github.com/scicompkl/CoDiPack" sha_version_medi = "7d550831e0e233a85b9d9af9c181d7ecb2929946" github_repo_medi = "https://github.com/SciCompKL/MeDiPack" From a4f9268626ef803b3c0ba319c43acaf7fbfd488e Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 6 Mar 2025 19:28:59 +0100 Subject: [PATCH 29/61] Trying fixing the CodiPack bug --- meson_scripts/init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson_scripts/init.py b/meson_scripts/init.py index 67a2e41a2ecc..3b41865ab14f 100755 --- a/meson_scripts/init.py +++ b/meson_scripts/init.py @@ -56,7 +56,7 @@ def init_submodules( # This information of the modules is used if projects was not cloned using git # The sha tag must be maintained manually to point to the correct commit - sha_version_codi = "762ba7698e3ceaa1b17aa299421ddd418f00b823" + sha_version_codi = "8b1dd955bb59f5a1d05a11acfd6fb82899a78c07" github_repo_codi = "https://github.com/scicompkl/CoDiPack" sha_version_medi = "7d550831e0e233a85b9d9af9c181d7ecb2929946" github_repo_medi = "https://github.com/SciCompKL/MeDiPack" From 82c7b1f45fcf360cbd699c39c15840676c40b1ce Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 7 Mar 2025 12:28:02 +0100 Subject: [PATCH 30/61] CoDiPack sha --- .gitmodules | 2 +- meson_scripts/init.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 4c6d8a819f89..db36377def2a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "externals/codi"] path = externals/codi - url = https://github.com/scicompkl/CoDiPack + url = https://github.com/SciCompKL/CoDiPack ignore = dirty [submodule "externals/medi"] path = externals/medi diff --git a/meson_scripts/init.py b/meson_scripts/init.py index 3b41865ab14f..67a2e41a2ecc 100755 --- a/meson_scripts/init.py +++ b/meson_scripts/init.py @@ -56,7 +56,7 @@ def init_submodules( # This information of the modules is used if projects was not cloned using git # The sha tag must be maintained manually to point to the correct commit - sha_version_codi = "8b1dd955bb59f5a1d05a11acfd6fb82899a78c07" + sha_version_codi = "762ba7698e3ceaa1b17aa299421ddd418f00b823" github_repo_codi = "https://github.com/scicompkl/CoDiPack" sha_version_medi = "7d550831e0e233a85b9d9af9c181d7ecb2929946" github_repo_medi = "https://github.com/SciCompKL/MeDiPack" From c8f3fe78fe014db6766f12fd209689e5313c1798 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 7 Mar 2025 15:14:38 +0100 Subject: [PATCH 31/61] - align externals and submodules to develop --- .../transition/trans_correlations.hpp | 3 -- .../turbulent/transition/trans_sources.hpp | 1 - SU2_CFD/src/variables/CTransLMVariable.cpp | 30 +++++++++---------- externals/codi | 2 +- externals/medi | 2 +- externals/mel | 2 +- externals/opdi | 2 +- subprojects/CoolProp | 2 +- 8 files changed, 20 insertions(+), 24 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp index e36b11f6e5bb..6be8265d4890 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp @@ -261,9 +261,6 @@ class TransLMCorrelations { FPG = 1 + 0.275 * (1 - exp(-35.0 * lambda_theta_local)) * exp(-Tu_L/0.5); } - // This is not reported in the paper - //FPG = max(FPG, 0.0); - if (Tu_L <= 1.3) { const su2double FirstTerm = -589.428 * Tu_L; const su2double SecondTerm = 0.2196 / max(pow(Tu_L, 2.0), 1e-12); diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index d6ade40095a8..7fd3b46f1188 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -277,7 +277,6 @@ class CSourcePieceWise_TransLM final : public CNumerics { VelocityNormalized[1] = vel_v / Velocity_Mag; if (nDim == 3) VelocityNormalized[2] = vel_w / Velocity_Mag; - // const su2double StreamwiseVort = abs(GeometryToolbox::DotProduct(VelocityNormalized, Vorticity_i)); su2double StreamwiseVort = 0.0; for (auto iDim = 0u; iDim < nDim; iDim++) { StreamwiseVort += VelocityNormalized[iDim] * Vorticity_i[iDim]; diff --git a/SU2_CFD/src/variables/CTransLMVariable.cpp b/SU2_CFD/src/variables/CTransLMVariable.cpp index 40d3446f2137..677aea472819 100644 --- a/SU2_CFD/src/variables/CTransLMVariable.cpp +++ b/SU2_CFD/src/variables/CTransLMVariable.cpp @@ -56,26 +56,26 @@ CTransLMVariable::CTransLMVariable(su2double Intermittency, su2double ReThetaT, Re_t.resize(nPoint) = ReThetaT; nAuxVar = 1; - Grad_AuxVar.resize(nPoint, nAuxVar, nDim, 0.0); + Grad_AuxVar.resize(nPoint, nAuxVar, nDim, su2double(0.0)); AuxVar.resize(nPoint, nAuxVar) = su2double(0.0); - Tu.resize(nPoint) = 0.0; + Tu.resize(nPoint) = su2double(0.0); - normal_x.resize(nPoint) = 0.0; - normal_y.resize(nPoint) = 0.0; - normal_z.resize(nPoint) = 0.0; + normal_x.resize(nPoint) = su2double(0.0); + normal_y.resize(nPoint) = su2double(0.0); + normal_z.resize(nPoint) = su2double(0.0); } - Re_v.resize(nPoint) = 0.0; - Corr_Rec.resize(nPoint) = 1.0; - Prod.resize(nPoint) = 0.0; - Destr.resize(nPoint) = 0.0; - F_onset1.resize(nPoint) = 0.0; - F_onset2.resize(nPoint) = 0.0; - F_onset3.resize(nPoint) = 0.0; - F_onset.resize(nPoint) = 0.0; - Lambda_theta.resize(nPoint) = 0.0; - duds.resize(nPoint) = 0.0; + Re_v.resize(nPoint) = su2double(0.0); + Corr_Rec.resize(nPoint) = su2double(1.0); + Prod.resize(nPoint) = su2double(0.0); + Destr.resize(nPoint) = su2double(0.0); + F_onset1.resize(nPoint) = su2double(0.0); + F_onset2.resize(nPoint) = su2double(0.0); + F_onset3.resize(nPoint) = su2double(0.0); + F_onset.resize(nPoint) = su2double(0.0); + Lambda_theta.resize(nPoint) = su2double(0.0); + duds.resize(nPoint) = su2double(0.0); } diff --git a/externals/codi b/externals/codi index 96ac78ec5bcc..02b10b6b8c1d 160000 --- a/externals/codi +++ b/externals/codi @@ -1 +1 @@ -Subproject commit 96ac78ec5bcc5ac25b785e79b16ed76fca22d736 +Subproject commit 02b10b6b8c1dc7868b97fc36a512ff1ef65cfff4 diff --git a/externals/medi b/externals/medi index 6aef76912e70..7d550831e0e2 160000 --- a/externals/medi +++ b/externals/medi @@ -1 +1 @@ -Subproject commit 6aef76912e7099c4f08c9705848797ca9e8070da +Subproject commit 7d550831e0e233a85b9d9af9c181d7ecb2929946 diff --git a/externals/mel b/externals/mel index 2484cd3258ef..46205ab019e5 160000 --- a/externals/mel +++ b/externals/mel @@ -1 +1 @@ -Subproject commit 2484cd3258ef800a10e361016cb341834ee7930b +Subproject commit 46205ab019e5224559091375a6d71aabae6bc5b9 diff --git a/externals/opdi b/externals/opdi index 1aabf5bd1ed7..a6b9655c240a 160000 --- a/externals/opdi +++ b/externals/opdi @@ -1 +1 @@ -Subproject commit 1aabf5bd1ed77611742eb655002f2ac7a3dddef9 +Subproject commit a6b9655c240af2a35454a61727e5bbbbaa3a425f diff --git a/subprojects/CoolProp b/subprojects/CoolProp index 0ce42fcf3bb2..bafdea1f39ee 160000 --- a/subprojects/CoolProp +++ b/subprojects/CoolProp @@ -1 +1 @@ -Subproject commit 0ce42fcf3bb2c373512bc825a4f0c1973a78f307 +Subproject commit bafdea1f39ee873a6bb9833e3a21fe41f90b85e8 From 490416588d2a0aa6a04e7d2d0dbf41bc7afecd6b Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 7 Mar 2025 15:26:01 +0100 Subject: [PATCH 32/61] - align codi with develop --- externals/codi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/codi b/externals/codi index 02b10b6b8c1d..762ba7698e3c 160000 --- a/externals/codi +++ b/externals/codi @@ -1 +1 @@ -Subproject commit 02b10b6b8c1dc7868b97fc36a512ff1ef65cfff4 +Subproject commit 762ba7698e3ceaa1b17aa299421ddd418f00b823 From 831d95d655498618ef7cf5278d9a1b4a8c888094 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 7 Mar 2025 16:06:36 +0100 Subject: [PATCH 33/61] - fix compilation reverse AD bug --- SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index 7fd3b46f1188..c8c91ee46780 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -596,7 +596,7 @@ class CSourcePieceWise_TransSLM final : public CNumerics { } - AD::SetPreaccOut(Residual, nVar); + AD::SetPreaccOut(Residual); AD::EndPreacc(); return ResidualType<>(&Residual, &Jacobian_i, nullptr); From 41346679c77f17c022ba62045e7275f277adfc3a Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 7 Mar 2025 18:18:16 +0100 Subject: [PATCH 34/61] - Fix DG problems when normal computation --- Common/src/geometry/CGeometry.cpp | 114 +++++++++++++------------ SU2_CFD/src/solvers/CTransLMSolver.cpp | 7 -- 2 files changed, 59 insertions(+), 62 deletions(-) diff --git a/Common/src/geometry/CGeometry.cpp b/Common/src/geometry/CGeometry.cpp index a17073478dc4..2268d6dc5530 100644 --- a/Common/src/geometry/CGeometry.cpp +++ b/Common/src/geometry/CGeometry.cpp @@ -4026,80 +4026,84 @@ void CGeometry::ComputeWallDistance(const CConfig* const* config_container, CGeo } } + MAIN_SOLVER kindSolver = config_container[ZONE_0]->GetKind_Solver(); + if (!wallDistanceNeeded[ZONE_0] || kindSolver == MAIN_SOLVER::FEM_LES || kindSolver == MAIN_SOLVER::FEM_RANS) { + continue; + } else { - su2vector>> WallNormal_container; - WallNormal_container.resize(nZone) = su2vector>(); - for (int iZone = 0; iZone < nZone; iZone++){ - const CConfig* config = config_container[iZone]; - const CGeometry* geometry = geometry_container[iZone][iInst][MESH_0]; - WallNormal_container[iZone].resize(geometry->GetnMarker()); - for (auto iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++){ - if (config->GetViscous_Wall(iMarker)) { - WallNormal_container[iZone][iMarker].resize(geometry->GetnElem_Bound(iMarker), 3); - - // cout << "geometry->nVertex[iMarker] = " << geometry->nVertex[iMarker] << endl; - for (auto iElem = 0u; iElem < geometry->GetnElem_Bound(iMarker); iElem++) { - su2vector NormalHere; - NormalHere.resize(3) = su2double(0.0); - - for (unsigned short iNode = 0; iNode < geometry->bound[iMarker][iElem]->GetnNodes(); iNode++) { - // Extract global coordinate of the node - unsigned long iPointHere = geometry->bound[iMarker][iElem]->GetNode(iNode); - long iVertexHere = geometry->nodes->GetVertex(iPointHere, iMarker); - for (auto iDim = 0u; iDim < 3; iDim++) - NormalHere[iDim] += geometry->vertex[iMarker][iVertexHere]->GetNormal(iDim); - } + su2vector>> WallNormal_container; + WallNormal_container.resize(nZone) = su2vector>(); + for (int iZone = 0; iZone < nZone; iZone++){ + const CConfig* config = config_container[iZone]; + const CGeometry* geometry = geometry_container[iZone][iInst][MESH_0]; + WallNormal_container[iZone].resize(geometry->GetnMarker()); + for (auto iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++){ + if (config->GetViscous_Wall(iMarker)) { + WallNormal_container[iZone][iMarker].resize(geometry->GetnElem_Bound(iMarker), 3); + + for (auto iElem = 0u; iElem < geometry->GetnElem_Bound(iMarker); iElem++) { + su2vector NormalHere; + NormalHere.resize(3) = su2double(0.0); + + for (unsigned short iNode = 0; iNode < geometry->bound[iMarker][iElem]->GetnNodes(); iNode++) { + // Extract global coordinate of the node + unsigned long iPointHere = geometry->bound[iMarker][iElem]->GetNode(iNode); + long iVertexHere = geometry->nodes->GetVertex(iPointHere, iMarker); + for (auto iDim = 0u; iDim < 3; iDim++) + NormalHere[iDim] += geometry->vertex[iMarker][iVertexHere]->GetNormal(iDim); + } - for (auto iDim = 0u; iDim < 3; iDim++) - NormalHere[iDim] /= geometry->bound[iMarker][iElem]->GetnNodes(); + for (auto iDim = 0u; iDim < 3; iDim++) + NormalHere[iDim] /= geometry->bound[iMarker][iElem]->GetnNodes(); - su2double NormalMag = 0.0; - for (auto iDim = 0u; iDim < 3; iDim++) - NormalMag += NormalHere[iDim]*NormalHere[iDim]; - NormalMag = sqrt(NormalMag); + su2double NormalMag = 0.0; + for (auto iDim = 0u; iDim < 3; iDim++) + NormalMag += NormalHere[iDim]*NormalHere[iDim]; + NormalMag = sqrt(NormalMag); - for (auto iDim = 0u; iDim < 3; iDim++) - NormalHere[iDim] /= NormalMag; + for (auto iDim = 0u; iDim < 3; iDim++) + NormalHere[iDim] /= NormalMag; - for (auto iDim = 0u; iDim < 3; iDim++) - WallNormal_container[iZone][iMarker](iElem, iDim) = NormalHere[iDim]; + for (auto iDim = 0u; iDim < 3; iDim++) + WallNormal_container[iZone][iMarker](iElem, iDim) = NormalHere[iDim]; + } + } else { + WallNormal_container[iZone][iMarker].resize(1, 3) = su2double(0.0); } - } else { - WallNormal_container[iZone][iMarker].resize(1, 3) = su2double(0.0); } } - } - auto normal_i = - make_pair(nZone, [config_container,geometry_container,iInst,WallNormal_container](unsigned long iZone){ - const CConfig* config = config_container[iZone]; - const CGeometry* geometry = geometry_container[iZone][iInst][MESH_0]; - const auto nMarker = geometry->GetnMarker(); - const auto WallNormal = WallNormal_container[iZone]; + auto normal_i = + make_pair(nZone, [config_container,geometry_container,iInst,WallNormal_container](unsigned long iZone){ + const CConfig* config = config_container[iZone]; + const CGeometry* geometry = geometry_container[iZone][iInst][MESH_0]; + const auto nMarker = geometry->GetnMarker(); + const auto WallNormal = WallNormal_container[iZone]; - return make_pair( nMarker, [config,geometry,WallNormal](unsigned long iMarker){ - auto nElem_Bou = geometry->GetnElem_Bound(iMarker); - if (!config->GetViscous_Wall(iMarker)) nElem_Bou = 1; + return make_pair( nMarker, [config,geometry,WallNormal](unsigned long iMarker){ + auto nElem_Bou = geometry->GetnElem_Bound(iMarker); + if (!config->GetViscous_Wall(iMarker)) nElem_Bou = 1; - return make_pair(nElem_Bou, [WallNormal,iMarker](unsigned long iElem){ - const auto dimensions = 3; + return make_pair(nElem_Bou, [WallNormal,iMarker](unsigned long iElem){ + const auto dimensions = 3; - return make_pair(dimensions, [WallNormal,iMarker,iElem](unsigned short iDim){ - - return WallNormal[iMarker](iElem, iDim); + return make_pair(dimensions, [WallNormal,iMarker,iElem](unsigned short iDim){ + + return WallNormal[iMarker](iElem, iDim); + }); }); }); }); - }); - NdFlattener<4>Normals_Local(normal_i); - NdFlattener<5> Normals_global(Nd_MPI_Environment(), Normals_Local); + NdFlattener<4>Normals_Local(normal_i); + NdFlattener<5> Normals_global(Nd_MPI_Environment(), Normals_Local); - // use it to update roughnesses - for(int jZone=0; jZonenodes->SetWallNormals(Normals_global); + // use it to update roughnesses + for(int jZone=0; jZonenodes->SetWallNormals(Normals_global); + } } } } diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index ba88784ab8c7..061cb25c719b 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -286,10 +286,6 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, Re_t); } - - // cout << Re_t << " " << Corr_Rec << endl; - // if (geometry->nodes->GetDomain(iPoint)) cout << "Point is on boundary" << endl; - su2double R_t = 1.0; if(TurbFamily == TURB_FAMILY::KW) R_t = rho*k/ mu/ omega; @@ -306,8 +302,6 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai if(TurbFamily == TURB_FAMILY::SA) f_wake = 1.0; - //cout << "StrainMag = " << StrainMag << " rho = " << rho << " dist = " << dist << " Re_v = " << Re_v << " Corr_Rec = " << Corr_Rec << endl; - const su2double theta_bl = Re_t*mu / rho /VelocityMag; const su2double delta_bl = 7.5*theta_bl; const su2double delta = 50.0*VorticityMag*dist/VelocityMag*delta_bl + 1e-20; @@ -315,7 +309,6 @@ void CTransLMSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai const su2double var2 = 1.0 - pow(var1,2.0); const su2double f_theta = min(max(f_wake*exp(-pow(dist/delta, 4)), var2), 1.0); su2double Intermittency_Sep = 2.0*max(0.0, Re_v/(3.235*Corr_Rec)-1.0)*f_reattach; - //if (Intermittency_Sep>1.0) cout << "StrainMag = " << StrainMag << " rho = " << rho << " dist = " << dist << " Re_v = " << Re_v << " Corr_Rec = " << Corr_Rec << " Intermittency: " << Intermittency_Sep << " f_reattach = " << f_reattach << endl; Intermittency_Sep = min(Intermittency_Sep,2.0)*f_theta; Intermittency_Sep = min(max(0.0, Intermittency_Sep), 2.0); nodes -> SetIntermittencySep(iPoint, Intermittency_Sep); From f717ed579a944c367cd2e68d35d799afdbbb5971 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 12 Mar 2025 18:54:10 +0100 Subject: [PATCH 35/61] - Modify screen output in SU2 header --- Common/src/CConfig.cpp | 58 +++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 7735800d148c..f8d44d6a4a9f 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -6328,42 +6328,48 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { cout << "Transition model: Simplified Langtry and Menter's "<< NEquations+NTurbEqs <<" equation model"; } if (lmParsedOptions.CrossFlow) { - cout << " w/ cross-flow corrections" << endl; + cout << " w/ cross-flow corrections"; + if (!lmParsedOptions.SLM) { + cout << " (2015)"; + } + cout << endl; } else { if (!lmParsedOptions.SLM) { cout << " (2009)" << endl; - } else { - cout << " (2015)" << endl; } } break; } } - if (Kind_Trans_Model == TURB_TRANS_MODEL::LM) { - cout << "Correlation Functions: "; - switch (lmParsedOptions.Correlation) { - case TURB_TRANS_CORRELATION::MALAN: cout << "Malan et al. (2009)" << endl; break; - case TURB_TRANS_CORRELATION::SULUKSNA: cout << "Suluksna et al. (2009)" << endl; break; - case TURB_TRANS_CORRELATION::KRAUSE: cout << "Krause et al. (2008)" << endl; break; - case TURB_TRANS_CORRELATION::KRAUSE_HYPER: cout << "Krause et al. (2008, paper)" << endl; break; - case TURB_TRANS_CORRELATION::MEDIDA_BAEDER: cout << "Medida and Baeder (2011)" << endl; break; - case TURB_TRANS_CORRELATION::MEDIDA: cout << "Medida PhD (2014)" << endl; break; - case TURB_TRANS_CORRELATION::MENTER_LANGTRY: cout << "Menter and Langtry (2009)" << endl; break; - case TURB_TRANS_CORRELATION::DEFAULT: - switch (Kind_Turb_Model) { - case TURB_MODEL::SA: cout << "Malan et al. (2009)" << endl; break; - case TURB_MODEL::SST: cout << "Menter and Langtry (2009)" << endl; break; - case TURB_MODEL::NONE: SU2_MPI::Error("No turbulence model has been selected but LM transition model is active.", CURRENT_FUNCTION); break; - } - break; + if (Kind_Trans_Model == TURB_TRANS_MODEL::LM) { + if (!lmParsedOptions.SLM){ + cout << "Correlation Functions: "; + switch (lmParsedOptions.Correlation) { + case TURB_TRANS_CORRELATION::MALAN: cout << "Malan et al. (2009)" << endl; break; + case TURB_TRANS_CORRELATION::SULUKSNA: cout << "Suluksna et al. (2009)" << endl; break; + case TURB_TRANS_CORRELATION::KRAUSE: cout << "Krause et al. (2008)" << endl; break; + case TURB_TRANS_CORRELATION::KRAUSE_HYPER: cout << "Krause et al. (2008, paper)" << endl; break; + case TURB_TRANS_CORRELATION::MEDIDA_BAEDER: cout << "Medida and Baeder (2011)" << endl; break; + case TURB_TRANS_CORRELATION::MEDIDA: cout << "Medida PhD (2014)" << endl; break; + case TURB_TRANS_CORRELATION::MENTER_LANGTRY: cout << "Menter and Langtry (2009)" << endl; break; + case TURB_TRANS_CORRELATION::DEFAULT: + switch (Kind_Turb_Model) { + case TURB_MODEL::SA: cout << "Malan et al. (2009)" << endl; break; + case TURB_MODEL::SST: cout << "Menter and Langtry (2009)" << endl; break; + case TURB_MODEL::NONE: SU2_MPI::Error("No turbulence model has been selected but LM transition model is active.", CURRENT_FUNCTION); break; + } + break; + } } - cout << "Correlation Functions for Simplified LM model: "; - switch (lmParsedOptions.Correlation_SLM) { - case TURB_TRANS_CORRELATION_SLM::CODER_SLM: cout << "Coder et al. (2012)" << endl; break; - case TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM: cout << "Modified Eppler (from Coder et al. 2012)" << endl; break; - case TURB_TRANS_CORRELATION_SLM::MENTER_SLM: - case TURB_TRANS_CORRELATION_SLM::DEFAULT: cout << "Menter et al. (2015)" << endl; break; + else { + cout << "Correlation Functions for Simplified LM model: "; + switch (lmParsedOptions.Correlation_SLM) { + case TURB_TRANS_CORRELATION_SLM::CODER_SLM: cout << "Coder et al. (2012)" << endl; break; + case TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM: cout << "Modified Eppler (from Coder et al. 2012)" << endl; break; + case TURB_TRANS_CORRELATION_SLM::MENTER_SLM: + case TURB_TRANS_CORRELATION_SLM::DEFAULT: cout << "Menter et al. (2015)" << endl; break; + } } } cout << "Hybrid RANS/LES: "; From 0f3f412ac6bde64ef9ba6e0f5448f1dcb5c2a7fc Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 13 Mar 2025 10:20:51 +0100 Subject: [PATCH 36/61] - Fix bugs in crossflow correction --- .../include/numerics/turbulent/transition/trans_sources.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index c8c91ee46780..f12474be96f5 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -551,14 +551,14 @@ class CSourcePieceWise_TransSLM final : public CNumerics { su2double StreamwiseVort = 0.0; for (auto iDim = 0u; iDim < nDim; iDim++) { - StreamwiseVort += VelocityNormalized[iDim] * Vorticity_i[iDim]; + StreamwiseVort += VelocityNormalized[iDim] * Vorticity_i[iDim] / VorticityMag; } StreamwiseVort = abs(StreamwiseVort); const su2double H_CF = StreamwiseVort * dist_i / Velocity_Mag; // Computation of Delta_H_CF. Here I have included directly R_t as the ration between turb and lam viscosity - const su2double Delta_H_CF = H_CF * (1.0 + min(R_t, 0.4)); + const su2double Delta_H_CF = H_CF * (1.0 + min(Eddy_Viscosity_i / Laminar_Viscosity_i, 0.4)); // Take into account for roughness const su2double h_0 = 0.25e-6; From 1ef2081301846348028b44893679d869dc13a375 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 13 Mar 2025 12:01:31 +0100 Subject: [PATCH 37/61] - Revert to use of dimensional vorticity --- .../include/numerics/turbulent/transition/trans_sources.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index f12474be96f5..b4679a8bdc10 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -551,9 +551,9 @@ class CSourcePieceWise_TransSLM final : public CNumerics { su2double StreamwiseVort = 0.0; for (auto iDim = 0u; iDim < nDim; iDim++) { - StreamwiseVort += VelocityNormalized[iDim] * Vorticity_i[iDim] / VorticityMag; + StreamwiseVort += VelocityNormalized[iDim] * Vorticity_i[iDim]; } - StreamwiseVort = abs(StreamwiseVort); + StreamwiseVort = abs(StreamwiseVort); const su2double H_CF = StreamwiseVort * dist_i / Velocity_Mag; From bb3b066803e06dce39329cb531143ad310e0e308 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Fri, 14 Mar 2025 10:36:14 +0100 Subject: [PATCH 38/61] - Fix bug from paper in crossflow --- SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index b4679a8bdc10..e77666b83085 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -540,7 +540,7 @@ class CSourcePieceWise_TransSLM final : public CNumerics { if(H < 2.3) { Re_Crit_CF = 150.0; } else { - Re_Crit_CF = -(300.0/PI_NUMBER) * atan(0.106/(pow(H-2.3, 2.05))); + Re_Crit_CF = (300.0/PI_NUMBER) * atan(0.106/(pow(H-2.3, 2.05))); } // Helicity computation From d2791b05401b428504f17592588b6d0993623226 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 19 Mar 2025 18:12:10 +0100 Subject: [PATCH 39/61] - fixed formatting errors --- Common/include/geometry/dual_grid/CPoint.hpp | 38 ++++++-------- Common/src/geometry/CGeometry.cpp | 55 +++++++++----------- Common/src/geometry/dual_grid/CPoint.cpp | 1 - 3 files changed, 41 insertions(+), 53 deletions(-) diff --git a/Common/include/geometry/dual_grid/CPoint.hpp b/Common/include/geometry/dual_grid/CPoint.hpp index 9b0f6d31a59e..9806231384a3 100644 --- a/Common/include/geometry/dual_grid/CPoint.hpp +++ b/Common/include/geometry/dual_grid/CPoint.hpp @@ -108,11 +108,11 @@ class CPoint { su2vector ClosestWall_Elem; /*!< \brief Element index of closest wall element, for givenrank, zone and marker index. */ - su2activevector SharpEdge_Distance; /*!< \brief Distance to a sharp edge. */ - su2activevector Curvature; /*!< \brief Value of the surface curvature (SU2_GEO). */ - su2activevector MaxLength; /*!< \brief The maximum cell-center to cell-center length. */ - su2activevector RoughnessHeight; /*!< \brief Roughness of the nearest wall. */ - su2activematrix Normals; /*!< \brief Normal of the nearest wall element. */ + su2activevector SharpEdge_Distance; /*!< \brief Distance to a sharp edge. */ + su2activevector Curvature; /*!< \brief Value of the surface curvature (SU2_GEO). */ + su2activevector MaxLength; /*!< \brief The maximum cell-center to cell-center length. */ + su2activevector RoughnessHeight; /*!< \brief Roughness of the nearest wall. */ + su2activematrix Normals; /*!< \brief Normal of the nearest wall element. */ su2matrix AD_InputIndex; /*!< \brief Indices of Coord variables in the adjoint vector. */ su2matrix @@ -489,22 +489,22 @@ class CPoint { * \brief Get the index of the closest wall element. * \param[in] iPoint - Index of the point. * \param[out] ClosestWall_Elem - ID of the closest element on a wall boundary. - */ - inline unsigned long GetClosestWall_Elem(unsigned long iPoint) {return ClosestWall_Elem(iPoint);} + */ + inline unsigned long GetClosestWall_Elem(unsigned long iPoint) { return ClosestWall_Elem(iPoint); } /*! * \brief Get the marker of the closest wall marker. * \param[in] iPoint - Index of the point. * \param[out] ClosestWall_Marker - MarkerID of the closest wall boundary. */ - inline unsigned long GetClosestWall_Marker(unsigned long iPoint) {return ClosestWall_Marker(iPoint);} + inline unsigned long GetClosestWall_Marker(unsigned long iPoint) { return ClosestWall_Marker(iPoint); } /*! * \brief Get the rank of the closest wall marker. * \param[in] iPoint - Index of the point. * \param[out] ClosestWall_Rank - RankID of the closest wall boundary. */ - inline unsigned long GetClosestWall_Rank(unsigned long iPoint) {return ClosestWall_Rank(iPoint);} + inline unsigned long GetClosestWall_Rank(unsigned long iPoint) { return ClosestWall_Rank(iPoint); } /*! * \brief Get the value of the distance to the nearest wall. @@ -533,10 +533,9 @@ class CPoint { * \param[in] iPoint - Index of the point. * \param[in] normal - Value of the normal. */ - template - inline void SetNormal(unsigned long iPoint, Normals_type const&normal) { - for (unsigned long iDim = 0; iDim < nDim; iDim++) - Normals(iPoint,iDim) = normal[iDim]; + template + inline void SetNormal(unsigned long iPoint, Normals_type const& normal) { + for (unsigned long iDim = 0; iDim < nDim; iDim++) Normals(iPoint, iDim) = normal[iDim]; } /*! @@ -544,7 +543,7 @@ class CPoint { * \param[in] iPoint - Index of the point. * \return normal to the normal of the nearest wall element. */ - inline su2double *GetNormal(unsigned long iPoint) { return Normals[iPoint]; } + inline su2double* GetNormal(unsigned long iPoint) { return Normals[iPoint]; } /*! * \brief Set the value of the distance to a sharp edge. @@ -926,21 +925,18 @@ class CPoint { } } - /*! * \brief Set wall normal according to stored closest wall information. * \param[in] normals - Mapping [rank][zone][marker][element] -> normal */ - template - void SetWallNormals(Normals_type const&normals){ - for (unsigned long iPoint=0; iPoint + void SetWallNormals(Normals_type const& normals) { + for (unsigned long iPoint = 0; iPoint < GlobalIndex.size(); ++iPoint) { auto rankID = ClosestWall_Rank[iPoint]; auto zoneID = ClosestWall_Zone[iPoint]; auto markerID = ClosestWall_Marker[iPoint]; auto elementID = ClosestWall_Elem[iPoint]; - if(rankID >= 0) - SetNormal(iPoint, normals[rankID][zoneID][markerID][elementID]); + if (rankID >= 0) SetNormal(iPoint, normals[rankID][zoneID][markerID][elementID]); } } - }; diff --git a/Common/src/geometry/CGeometry.cpp b/Common/src/geometry/CGeometry.cpp index 2268d6dc5530..5a4638233b2e 100644 --- a/Common/src/geometry/CGeometry.cpp +++ b/Common/src/geometry/CGeometry.cpp @@ -4030,14 +4030,13 @@ void CGeometry::ComputeWallDistance(const CConfig* const* config_container, CGeo if (!wallDistanceNeeded[ZONE_0] || kindSolver == MAIN_SOLVER::FEM_LES || kindSolver == MAIN_SOLVER::FEM_RANS) { continue; } else { - su2vector>> WallNormal_container; WallNormal_container.resize(nZone) = su2vector>(); - for (int iZone = 0; iZone < nZone; iZone++){ + for (int iZone = 0; iZone < nZone; iZone++) { const CConfig* config = config_container[iZone]; const CGeometry* geometry = geometry_container[iZone][iInst][MESH_0]; WallNormal_container[iZone].resize(geometry->GetnMarker()); - for (auto iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++){ + for (auto iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) { if (config->GetViscous_Wall(iMarker)) { WallNormal_container[iZone][iMarker].resize(geometry->GetnElem_Bound(iMarker), 3); @@ -4053,20 +4052,16 @@ void CGeometry::ComputeWallDistance(const CConfig* const* config_container, CGeo NormalHere[iDim] += geometry->vertex[iMarker][iVertexHere]->GetNormal(iDim); } - for (auto iDim = 0u; iDim < 3; iDim++) - NormalHere[iDim] /= geometry->bound[iMarker][iElem]->GetnNodes(); + for (auto iDim = 0u; iDim < 3; iDim++) NormalHere[iDim] /= geometry->bound[iMarker][iElem]->GetnNodes(); su2double NormalMag = 0.0; - for (auto iDim = 0u; iDim < 3; iDim++) - NormalMag += NormalHere[iDim]*NormalHere[iDim]; + for (auto iDim = 0u; iDim < 3; iDim++) NormalMag += NormalHere[iDim] * NormalHere[iDim]; NormalMag = sqrt(NormalMag); - for (auto iDim = 0u; iDim < 3; iDim++) - NormalHere[iDim] /= NormalMag; + for (auto iDim = 0u; iDim < 3; iDim++) NormalHere[iDim] /= NormalMag; for (auto iDim = 0u; iDim < 3; iDim++) WallNormal_container[iZone][iMarker](iElem, iDim) = NormalHere[iDim]; - } } else { WallNormal_container[iZone][iMarker].resize(1, 3) = su2double(0.0); @@ -4075,33 +4070,31 @@ void CGeometry::ComputeWallDistance(const CConfig* const* config_container, CGeo } auto normal_i = - make_pair(nZone, [config_container,geometry_container,iInst,WallNormal_container](unsigned long iZone){ - const CConfig* config = config_container[iZone]; - const CGeometry* geometry = geometry_container[iZone][iInst][MESH_0]; - const auto nMarker = geometry->GetnMarker(); - const auto WallNormal = WallNormal_container[iZone]; - - return make_pair( nMarker, [config,geometry,WallNormal](unsigned long iMarker){ - auto nElem_Bou = geometry->GetnElem_Bound(iMarker); - if (!config->GetViscous_Wall(iMarker)) nElem_Bou = 1; - - return make_pair(nElem_Bou, [WallNormal,iMarker](unsigned long iElem){ - const auto dimensions = 3; - - return make_pair(dimensions, [WallNormal,iMarker,iElem](unsigned short iDim){ - - return WallNormal[iMarker](iElem, iDim); + make_pair(nZone, [config_container, geometry_container, iInst, WallNormal_container](unsigned long iZone) { + const CConfig* config = config_container[iZone]; + const CGeometry* geometry = geometry_container[iZone][iInst][MESH_0]; + const auto nMarker = geometry->GetnMarker(); + const auto WallNormal = WallNormal_container[iZone]; + + return make_pair(nMarker, [config, geometry, WallNormal](unsigned long iMarker) { + auto nElem_Bou = geometry->GetnElem_Bound(iMarker); + if (!config->GetViscous_Wall(iMarker)) nElem_Bou = 1; + + return make_pair(nElem_Bou, [WallNormal, iMarker](unsigned long iElem) { + const auto dimensions = 3; + + return make_pair(dimensions, [WallNormal, iMarker, iElem](unsigned short iDim) { + return WallNormal[iMarker](iElem, iDim); + }); + }); }); }); - }); - }); - NdFlattener<4>Normals_Local(normal_i); + NdFlattener<4> Normals_Local(normal_i); NdFlattener<5> Normals_global(Nd_MPI_Environment(), Normals_Local); - // use it to update roughnesses - for(int jZone=0; jZonenodes->SetWallNormals(Normals_global); } } diff --git a/Common/src/geometry/dual_grid/CPoint.cpp b/Common/src/geometry/dual_grid/CPoint.cpp index 3470f048dc14..d04b37191ed6 100644 --- a/Common/src/geometry/dual_grid/CPoint.cpp +++ b/Common/src/geometry/dual_grid/CPoint.cpp @@ -128,7 +128,6 @@ void CPoint::FullAllocation(unsigned short imesh, const CConfig* config) { SharpEdge_Distance.resize(npoint) = su2double(0.0); Normals.resize(npoint, 3) = su2double(0.0); - } void CPoint::SetElems(const vector >& elemsMatrix) { Elem = CCompressedSparsePatternL(elemsMatrix); } From 5fb0cb99b331927e44e2349f127fd25a5e83a4af Mon Sep 17 00:00:00 2001 From: rois1995 Date: Tue, 8 Apr 2025 15:47:39 +0200 Subject: [PATCH 40/61] Merge remote-tracking branch 'origin/develop' into feature_Trans_SLM --- externals/codi | 2 +- externals/medi | 2 +- externals/opdi | 2 +- subprojects/MLPCpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/externals/codi b/externals/codi index a0725b2bfd17..762ba7698e3c 160000 --- a/externals/codi +++ b/externals/codi @@ -1 +1 @@ -Subproject commit a0725b2bfd172e741a07f96b041a5ddf88d441d7 +Subproject commit 762ba7698e3ceaa1b17aa299421ddd418f00b823 diff --git a/externals/medi b/externals/medi index 0cfaf96e7a31..7d550831e0e2 160000 --- a/externals/medi +++ b/externals/medi @@ -1 +1 @@ -Subproject commit 0cfaf96e7a31a5a8941b97f84198da03a8f8bd7a +Subproject commit 7d550831e0e233a85b9d9af9c181d7ecb2929946 diff --git a/externals/opdi b/externals/opdi index a5e2ac47035b..a6b9655c240a 160000 --- a/externals/opdi +++ b/externals/opdi @@ -1 +1 @@ -Subproject commit a5e2ac47035b6b3663f60d5f80b7a9fe62084867 +Subproject commit a6b9655c240af2a35454a61727e5bbbbaa3a425f diff --git a/subprojects/MLPCpp b/subprojects/MLPCpp index e19ca0cafb28..6865a58b22f2 160000 --- a/subprojects/MLPCpp +++ b/subprojects/MLPCpp @@ -1 +1 @@ -Subproject commit e19ca0cafb28c4b7ba5b8cffef42883259b00dc0 +Subproject commit 6865a58b22f21a92977839d9c93eae9522402f55 From 0f06f3bc67d411a0a58615ded09468793be43ab4 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Apr 2025 11:54:16 +0200 Subject: [PATCH 41/61] - Improved notation for freestream conditions on ReThetaT --- SU2_CFD/src/solvers/CEulerSolver.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/SU2_CFD/src/solvers/CEulerSolver.cpp b/SU2_CFD/src/solvers/CEulerSolver.cpp index b0e1381fef0f..76488f7e4dc4 100644 --- a/SU2_CFD/src/solvers/CEulerSolver.cpp +++ b/SU2_CFD/src/solvers/CEulerSolver.cpp @@ -1059,17 +1059,12 @@ void CEulerSolver::SetNondimensionalization(CConfig *config, unsigned short iMes Omega_FreeStreamND = Density_FreeStreamND*Tke_FreeStreamND/(Viscosity_FreeStreamND*config->GetTurb2LamViscRatio_FreeStream()); config->SetOmega_FreeStreamND(Omega_FreeStreamND); - if (config->GetTurbulenceIntensity_FreeStream() *100 <= 1.3) { - if (config->GetTurbulenceIntensity_FreeStream() *100 >=0.027) { - Re_ThetaT_FreeStream = (1173.51-589.428*config->GetTurbulenceIntensity_FreeStream() *100+0.2196/ - (config->GetTurbulenceIntensity_FreeStream() *100*config->GetTurbulenceIntensity_FreeStream() *100)); - } - else { - Re_ThetaT_FreeStream = (1173.51-589.428*config->GetTurbulenceIntensity_FreeStream() *100+0.2196/(0.27*0.27)); - } + const su2double Intensity = config->GetTurbulenceIntensity_FreeStream()*100.0; + if (Intensity <= 1.3) { + Re_ThetaT_FreeStream = (1173.51-589.428*Intensity+0.2196/(pow(max(Intensity, 0.027), 2.0))); } - else { - Re_ThetaT_FreeStream = 331.5*pow(config->GetTurbulenceIntensity_FreeStream() *100-0.5658,-0.671); + else if(Intensity>1.3) { + Re_ThetaT_FreeStream = 331.5*pow(Intensity-0.5658,-0.671); } config->SetReThetaT_FreeStream(Re_ThetaT_FreeStream); From 651af7c92670b8fe899a59d98a2af64cb5224434 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 2 Oct 2025 18:06:35 +0200 Subject: [PATCH 42/61] - Added comments --- .../include/numerics/turbulent/transition/trans_sources.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index b3ac5915657f..a3db95132ef2 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -525,6 +525,9 @@ class CSourcePieceWise_TransSLM final : public CNumerics { F_onset_Here = F_onset; if (options.CrossFlow) { + + // Taken from Vallinayagam Pillai, S., & Lardeau, S. (2017). "Accounting crossflow effects in one-equation + // local correlation-based transition model."" In 8th AIAA Theoretical Fluid Mechanics Conference (p. 3159). // Computation of shape factor const su2double k = 0.25 - lambda_theta; @@ -540,6 +543,7 @@ class CSourcePieceWise_TransSLM final : public CNumerics { if(H < 2.3) { Re_Crit_CF = 150.0; } else { + // Correct from paper since for H = 2.3 it was not continuous if a minus sign is added here Re_Crit_CF = (300.0/PI_NUMBER) * atan(0.106/(pow(H-2.3, 2.05))); } From 2c0255ebd49bf0de2949bfddbe961f1712e54832 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:03:46 +0200 Subject: [PATCH 43/61] Use the codi and medi submodules of develop Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- externals/codi | 2 +- externals/medi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/externals/codi b/externals/codi index 762ba7698e3c..a0725b2bfd17 160000 --- a/externals/codi +++ b/externals/codi @@ -1 +1 @@ -Subproject commit 762ba7698e3ceaa1b17aa299421ddd418f00b823 +Subproject commit a0725b2bfd172e741a07f96b041a5ddf88d441d7 diff --git a/externals/medi b/externals/medi index 7d550831e0e2..0cfaf96e7a31 160000 --- a/externals/medi +++ b/externals/medi @@ -1 +1 @@ -Subproject commit 7d550831e0e233a85b9d9af9c181d7ecb2929946 +Subproject commit 0cfaf96e7a31a5a8941b97f84198da03a8f8bd7a From 4d4b0afec5efbcffbbad982a3d3d065622bc20ee Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:04:18 +0200 Subject: [PATCH 44/61] Remove debug and whitespace changes unrelated to the simplified LM model Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- .gitmodules | 2 +- SU2_CFD/src/SU2_CFD.cpp | 3 +-- SU2_CFD/src/variables/CIncNSVariable.cpp | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 5c1cdbc00729..47e94c29240d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "externals/codi"] path = externals/codi - url = https://github.com/SciCompKL/CoDiPack + url = https://github.com/scicompkl/CoDiPack ignore = dirty [submodule "externals/medi"] path = externals/medi diff --git a/SU2_CFD/src/SU2_CFD.cpp b/SU2_CFD/src/SU2_CFD.cpp index 3567c3577f96..ca6dd3afaa25 100644 --- a/SU2_CFD/src/SU2_CFD.cpp +++ b/SU2_CFD/src/SU2_CFD.cpp @@ -30,7 +30,7 @@ #include "Eigen/src/Core/products/Parallelizer.h" /* Include file, needed for the runtime NaN catching. You also have to include feenableexcept(...) below. */ -#include +//#include using namespace std; @@ -74,7 +74,6 @@ int main(int argc, char *argv[]) { /*--- Uncomment the following line if runtime NaN catching is desired. ---*/ // feenableexcept(FE_INVALID | FE_OVERFLOW | FE_DIVBYZERO ); - // feenableexcept(FE_OVERFLOW | FE_DIVBYZERO ); /*--- Create a pointer to the main SU2 Driver ---*/ diff --git a/SU2_CFD/src/variables/CIncNSVariable.cpp b/SU2_CFD/src/variables/CIncNSVariable.cpp index 08bce4e588f5..93d481956949 100644 --- a/SU2_CFD/src/variables/CIncNSVariable.cpp +++ b/SU2_CFD/src/variables/CIncNSVariable.cpp @@ -99,6 +99,7 @@ bool CIncNSVariable::SetPrimVar(unsigned long iPoint, su2double eddy_visc, su2do SetVelocity(iPoint); /*--- Set laminar viscosity ---*/ + SetLaminarViscosity(iPoint, FluidModel->GetLaminarViscosity()); /*--- Set eddy viscosity locally and in the fluid model. ---*/ From 1693fd32a52bc7a24dc24dd171d3c366bd37c505 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:11:53 +0200 Subject: [PATCH 45/61] Fix uninitialized AuxVar and missing AD inputs in the simplified LM source AuxVar (wall-normal derivative of the wall-normal velocity) is only set for the Menter correlation; with the Coder and modified Eppler correlations lambda_theta, which the cross-flow term and the output use, was computed from an uninitialized value. Initialize it to zero. The preaccumulation registered only nVar = 1 turbulence variables, so omega was missing for SST, and AuxVar was not registered at all. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- .../numerics/turbulent/transition/trans_sources.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index 5503bb38e95e..718d575527e0 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -396,7 +396,7 @@ class CSourcePieceWise_TransSLM final : public CNumerics { su2double Re_t; su2double Corr_Rec = 1.0; - su2double AuxVar; + su2double AuxVar = 0.0; /*!< \brief Wall-normal derivative of the wall-normal velocity (Menter correlation). */ su2double F2; su2double Tu_Here = 0.0; su2double duds_Here = 0.0; @@ -445,8 +445,11 @@ class CSourcePieceWise_TransSLM final : public CNumerics { /*--- dU/dx = PrimVar_Grad[1][0] ---*/ AD::StartPreacc(); AD::SetPreaccIn(StrainMag_i); - AD::SetPreaccIn(ScalarVar_i, nVar); - AD::SetPreaccIn(ScalarVar_Grad_i, nVar, nDim); + /*--- ScalarVar_i holds the turbulence variables (k and omega for SST), nVar is the single transition variable. ---*/ + const unsigned short nVarTurb = (TurbFamily == TURB_FAMILY::KW) ? 2 : 1; + AD::SetPreaccIn(ScalarVar_i, nVarTurb); + AD::SetPreaccIn(ScalarVar_Grad_i, nVarTurb, nDim); + AD::SetPreaccIn(AuxVar); AD::SetPreaccIn(TransVar_i, nVar); AD::SetPreaccIn(TransVar_Grad_i, nVar, nDim); AD::SetPreaccIn(Volume); From e502fed3077e0caa239541ed76eafa10bf1733f9 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:11:53 +0200 Subject: [PATCH 46/61] Read only nDim components of the vertex normals for the wall normals In 2D the vertex normals have two components, reading three went past the end of the array. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- Common/src/geometry/CGeometry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/geometry/CGeometry.cpp b/Common/src/geometry/CGeometry.cpp index 9333c389da7b..342783c65e69 100644 --- a/Common/src/geometry/CGeometry.cpp +++ b/Common/src/geometry/CGeometry.cpp @@ -4662,7 +4662,7 @@ void CGeometry::ComputeWallDistance(const CConfig* const* config_container, CGeo // Extract global coordinate of the node unsigned long iPointHere = geometry->bound[iMarker][iElem]->GetNode(iNode); long iVertexHere = geometry->nodes->GetVertex(iPointHere, iMarker); - for (auto iDim = 0u; iDim < 3; iDim++) + for (auto iDim = 0u; iDim < geometry->GetnDim(); iDim++) NormalHere[iDim] += geometry->vertex[iMarker][iVertexHere]->GetNormal(iDim); } From 6228cc6a12d9b346e66bcfa6b9b5ce4c128d8c05 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:25:55 +0200 Subject: [PATCH 47/61] Warn when the Menter one-equation model is used without Kato-Launder production Menter et al. (2015, Eq. 24) compute the k production of SST with the Kato-Launder form mu_t*S*Omega and without the production limiter. Print a warning when MENTER_SLM is used with SST, suggesting KATO-LAUNDER when it is not selected, and noting that the SST production limiter stays active. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- Common/src/CConfig.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index f19dcbf3da4d..e9745886aebc 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -6753,6 +6753,15 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { case TURB_TRANS_CORRELATION_SLM::MENTER_SLM: case TURB_TRANS_CORRELATION_SLM::DEFAULT: cout << "Menter et al. (2015)" << endl; break; } + const bool menterSLM = lmParsedOptions.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM || + lmParsedOptions.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::DEFAULT; + if (menterSLM && Kind_Turb_Model == TURB_MODEL::SST) { + cout << "WARNING: Menter et al. (2015, Eq. 24) compute the k production of the SST model with the\n" + " Kato-Launder form P_k = mu_t*S*Omega and without the SST production limiter.\n"; + if (sstParsedOptions.production != SST_OPTIONS::KL) + cout << " The selected SST options do not use Kato-Launder, add KATO-LAUNDER to SST_OPTIONS.\n"; + cout << " The SST production limiter is active." << endl; + } } } cout << "Hybrid RANS/LES: "; From aaee5bfadb65de4caa2c4a9c9f610d7472e3bbf7 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:30:11 +0200 Subject: [PATCH 48/61] Make the LM and simplified LM restarts consistent LoadRestart read the separation and effective intermittencies at index + 2 and + 3, but they are PRIMITIVE outputs: in compact restarts these are the values of the next point, in full restarts other fields. They are not solution variables and are recomputed by Postprocessing at the end of LoadRestart, so they are no longer read. With the simplified model (one solution variable) RE_THETA_T and TU were in the SOLUTION group and therefore in the restart files; they are now PRIMITIVE outputs. The duplicated definitions of INTERMITTENCY_SEP and INTERMITTENCY_EFF in the solution fields are removed, they are defined with the primitive fields and written for all LM variants. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- SU2_CFD/src/output/CFlowOutput.cpp | 30 +++++++++----------------- SU2_CFD/src/solvers/CTransLMSolver.cpp | 4 ++-- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index 08796aca911a..16c8d0ebd995 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -1391,7 +1391,13 @@ void CFlowOutput::SetVolumeOutputFieldsScalarSolution(const CConfig* config){ switch (config->GetKind_Trans_Model()) { case TURB_TRANS_MODEL::LM: AddVolumeOutput("INTERMITTENCY", "LM_gamma", "SOLUTION", "LM intermittency"); - AddVolumeOutput("RE_THETA_T", "LM_Re_t", "SOLUTION", "LM RE_THETA_T"); + /*--- Re_theta_t is a solution variable only of the two-equation model, the simplified model computes it + * algebraically, so it must not enter the restart files. ---*/ + if (!(config->GetLMParsedOptions()).SLM) { + AddVolumeOutput("RE_THETA_T", "LM_Re_t", "SOLUTION", "LM RE_THETA_T"); + } else { + AddVolumeOutput("RE_THETA_T", "LM_Re_t", "PRIMITIVE", "LM RE_THETA_T"); + } AddVolumeOutput("RE_V", "Re_v", "DEBUG", "LM Re_v"); AddVolumeOutput("RE_THETA_CORR", "LM_Corr_Rec", "DEBUG", "LM RE_THETA_CORR"); AddVolumeOutput("PROD", "LM_Prod", "DEBUG", "LM PROD"); @@ -1403,21 +1409,11 @@ void CFlowOutput::SetVolumeOutputFieldsScalarSolution(const CConfig* config){ AddVolumeOutput("LAMBDA_THETA", "Lambda_theta", "DEBUG", "LM Lambda_theta"); AddVolumeOutput("DU_DS", "du_ds", "DEBUG", "LM du_ds"); if ((config->GetLMParsedOptions()).SLM) { - AddVolumeOutput("TU", "Tu", "SOLUTION", "LM Tu"); + AddVolumeOutput("TU", "Tu", "PRIMITIVE", "LM Tu"); AddVolumeOutput("NORMAL_X", "Normal_x", "DEBUG", "LM Normal_x"); AddVolumeOutput("NORMAL_Y", "Normal_y", "DEBUG", "LM Normal_y"); AddVolumeOutput("NORMAL_Z", "Normal_z", "DEBUG", "LM Normal_z"); - if (!((config->GetLMParsedOptions()).Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM)) { - AddVolumeOutput("INTERMITTENCY_SEP", "LM_gamma_sep", "PRIMITIVE", "LM intermittency"); - AddVolumeOutput("INTERMITTENCY_EFF", "LM_gamma_eff", "PRIMITIVE", "LM RE_THETA_T"); - } - } - - if (!(config->GetLMParsedOptions()).SLM) { - AddVolumeOutput("INTERMITTENCY_SEP", "LM_gamma_sep", "PRIMITIVE", "LM intermittency"); - AddVolumeOutput("INTERMITTENCY_EFF", "LM_gamma_eff", "PRIMITIVE", "LM RE_THETA_T"); } - AddVolumeOutput("TURB_INDEX", "Turb_index", "PRIMITIVE", "Turbulence index"); break; case TURB_TRANS_MODEL::NONE: @@ -1756,15 +1752,9 @@ void CFlowOutput::LoadVolumeDataScalar(const CConfig* config, const CSolver* con SetVolumeOutputValue("NORMAL_X", iPoint, Node_Trans->GetNormal_x(iPoint)); SetVolumeOutputValue("NORMAL_Y", iPoint, Node_Trans->GetNormal_y(iPoint)); SetVolumeOutputValue("NORMAL_Z", iPoint, Node_Trans->GetNormal_z(iPoint)); - if (!((config->GetLMParsedOptions()).Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM)) { - SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); - SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); - } - } - if (!(config->GetLMParsedOptions()).SLM) { - SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); - SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); } + SetVolumeOutputValue("INTERMITTENCY_SEP", iPoint, Node_Trans->GetIntermittencySep(iPoint)); + SetVolumeOutputValue("INTERMITTENCY_EFF", iPoint, Node_Trans->GetIntermittencyEff(iPoint)); SetVolumeOutputValue("TURB_INDEX", iPoint, Node_Turb->GetTurbIndex(iPoint)); SetVolumeOutputValue("RES_INTERMITTENCY", iPoint, trans_solver->LinSysRes(iPoint, 0)); if (!(config->GetLMParsedOptions()).SLM) { diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index ea7e1cc9cb65..241fd870d634 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -639,8 +639,8 @@ void CTransLMSolver::LoadRestart(CGeometry** geometry, CSolver*** solver, CConfi const auto index = counter * Restart_Vars[1] + skipVars; for (auto iVar = 0u; iVar < nVar; iVar++) nodes->SetSolution(iPoint_Local, iVar, Restart_Data[index + iVar]); - nodes->SetIntermittencySep(iPoint_Local, Restart_Data[index + 2]); - nodes->SetIntermittencyEff(iPoint_Local, Restart_Data[index + 3]); + /*--- The separation and effective intermittencies are not in the restart (compact restarts only have the + * solution variables), they are recomputed by Postprocessing below. ---*/ /*--- Increment the overall counter for how many points have been loaded. ---*/ counter++; From 72388fc3b1bfc9f210db7d0a6a2a15348bc919b4 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:35:58 +0200 Subject: [PATCH 49/61] Limit the turbulence intensity in both terms of the freestream Re_theta_t correlation The limit Tu >= 0.027 % was applied only to the 1/Tu^2 term, the linear term still used the unlimited value. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- SU2_CFD/src/solvers/CEulerSolver.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SU2_CFD/src/solvers/CEulerSolver.cpp b/SU2_CFD/src/solvers/CEulerSolver.cpp index f3abb0509526..7e310571d94d 100644 --- a/SU2_CFD/src/solvers/CEulerSolver.cpp +++ b/SU2_CFD/src/solvers/CEulerSolver.cpp @@ -1097,11 +1097,11 @@ void CEulerSolver::SetNondimensionalization(CConfig *config, unsigned short iMes Omega_FreeStreamND = Density_FreeStreamND*Tke_FreeStreamND/max(Viscosity_FreeStreamND*config->GetTurb2LamViscRatio_FreeStream(), EPS); config->SetOmega_FreeStreamND(Omega_FreeStreamND); - const su2double Intensity = config->GetTurbulenceIntensity_FreeStream()*100.0; + /*--- Langtry-Menter correlation, the turbulence intensity (in percent) is limited to 0.027 to avoid the singularity. ---*/ + const su2double Intensity = max(config->GetTurbulenceIntensity_FreeStream()*100.0, 0.027); if (Intensity <= 1.3) { - Re_ThetaT_FreeStream = (1173.51-589.428*Intensity+0.2196/(pow(max(Intensity, 0.027), 2.0))); - } - else if(Intensity>1.3) { + Re_ThetaT_FreeStream = 1173.51 - 589.428*Intensity + 0.2196/(Intensity*Intensity); + } else { Re_ThetaT_FreeStream = 331.5*pow(Intensity-0.5658,-0.671); } config->SetReThetaT_FreeStream(Re_ThetaT_FreeStream); From c955ea0c3d8c8f19b5bf3cf671c805965729572f Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:50:32 +0200 Subject: [PATCH 50/61] Reject simplified LM combinations that are not in the literature The one-equation model is available with MENTER_SLM and SST (Menter et al. 2015, cross-flow of Vallinayagam Pillai and Lardeau, AIAA 2017-3159) or SA (Lee and Baeder, AIAA 2021-1532). The CODER_SLM and MOD_EPPLER_SLM correlations of Coder and Maughmer (AIAA 2012-672) belong to the Langtry-Menter intermittency equation, not to the one-equation model implemented here, so they now stop with an error. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- Common/src/CConfig.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index e9745886aebc..4181f9681596 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -3843,6 +3843,26 @@ void CConfig::SetPostprocessing(SU2_COMPONENT val_software, unsigned short val_i if (lmParsedOptions.CrossFlow && val_nDim == 2) { SU2_MPI::Error("Cross-flow corrections are available only for 3D problems", CURRENT_FUNCTION); } + + /*--- The simplified (one-equation) model is available only for the combinations found in the literature: + * SST + MENTER_SLM (+ CROSSFLOW): Menter et al., Flow Turbul. Combust. 95, 2015, with the cross-flow extension of + * Vallinayagam Pillai and Lardeau, AIAA 2017-3159. + * SA + MENTER_SLM (+ CROSSFLOW): Lee and Baeder, AIAA 2021-1532. + * The CODER_SLM and MOD_EPPLER_SLM correlations (Coder and Maughmer, AIAA 2012-672) are defined for the + * Langtry-Menter intermittency equation, not for the one-equation model implemented here. ---*/ + if (lmParsedOptions.SLM) { + if (lmParsedOptions.Correlation_SLM != TURB_TRANS_CORRELATION_SLM::MENTER_SLM) { + SU2_MPI::Error("The CODER_SLM and MOD_EPPLER_SLM correlations of LM_OPTIONS are not available with the " + "one-equation (SLM) transition model:\nCoder and Maughmer (AIAA 2012-672) use them with the " + "Langtry-Menter intermittency equation.\nSupported combinations: SLM with MENTER_SLM and " + "KIND_TURB_MODEL= SST (Menter et al. 2015) or SA (Lee and Baeder, AIAA 2021-1532), " + "with or without CROSSFLOW.", CURRENT_FUNCTION); + } + if (Kind_Turb_Model != TURB_MODEL::SST && Kind_Turb_Model != TURB_MODEL::SA) { + SU2_MPI::Error("The one-equation (SLM) transition model is available only with KIND_TURB_MODEL= SST or SA.", + CURRENT_FUNCTION); + } + } } /*--- Set the boolean Wall_Functions equal to true if there is a From 75d666c635ad27177947673b7baa976c1e701c1e Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:50:32 +0200 Subject: [PATCH 51/61] Couple the simplified LM model with SA as in Lee and Baeder (AIAA 2021-1532) - Onset functions, F_turb and R_T = mu_t/mu as in Eqs. 4-7 (the same F_onset2 and F_onset3 as with SST). - Re_theta_c with C_TU1 and C_TU2 blended with the freestream Tu between the constants of Colonia et al. and the original ones (Eqs. 10-13). - SA equation: production times gamma_s, destruction times max(gamma_s, 0.1), with the scaled intermittency of Eq. 18 (Eq. 17). The two-equation LM coupling is unchanged. - Positivity of the implicit operator of the intermittency source (Eq. 24). - Cross-flow: the Langtry et al. stationary cross-flow criterion (Eqs. 36-43) and the Menter-Smirnov C1 criterion (Eqs. 25-35), with the cross-flow strength from the gradient of the vorticity direction. The CODER_SLM and MOD_EPPLER_SLM branch of the source, rejected at configuration, is removed. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- SU2_CFD/include/numerics/CNumerics.hpp | 5 + .../transition/trans_correlations.hpp | 17 ++- .../turbulent/transition/trans_sources.hpp | 140 ++++++++++++------ .../numerics/turbulent/turb_sources.hpp | 13 +- SU2_CFD/src/solvers/CTransLMSolver.cpp | 23 ++- SU2_CFD/src/variables/CTransLMVariable.cpp | 4 +- 6 files changed, 147 insertions(+), 55 deletions(-) diff --git a/SU2_CFD/include/numerics/CNumerics.hpp b/SU2_CFD/include/numerics/CNumerics.hpp index a73d39999d54..1741e483f9b2 100644 --- a/SU2_CFD/include/numerics/CNumerics.hpp +++ b/SU2_CFD/include/numerics/CNumerics.hpp @@ -843,6 +843,11 @@ class CNumerics { */ inline virtual void SetAuxVar(su2double val_AuxVar) {} + /*! + * \brief Set the cross-flow strength Psi = |n . grad(e_omega)| d_w of the one-equation transition model. + */ + inline virtual void SetCrossFlowStrength(su2double val_Psi) {} + /*! * \brief Set the gradient of the auxiliary variables. * \param[in] val_auxvar_grad_i - Gradient of the auxiliary variable at point i. diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp index 06b57927b429..bca5c24869f3 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_correlations.hpp @@ -197,7 +197,9 @@ class TransLMCorrelations { * \param[in] du_ds - Streamwise velocity gradient. * \param[out] rethetac - Corrected value for Re_theta. */ - su2double ReThetaC_Correlations_SLM(const su2double Tu_L, const su2double lambda_theta, const su2double wall_dist, const su2double VorticityMag, const su2double VelocityMag) const { + su2double ReThetaC_Correlations_SLM(const su2double Tu_L, const su2double lambda_theta, const su2double wall_dist, + const su2double VorticityMag, const su2double VelocityMag, + const bool spalartAllmaras = false) const { su2double rethetac = 0.0; @@ -224,9 +226,18 @@ class TransLMCorrelations { FPG = max(FPG, 0.0); - const su2double C_TU1 = 100.0; - const su2double C_TU2 = 1000.0; + /*--- Menter et al. (2015), Eq. 14. ---*/ + su2double C_TU1 = 100.0; + su2double C_TU2 = 1000.0; const su2double C_TU3 = 1.0; + + if (spalartAllmaras) { + /*--- Lee and Baeder, AIAA 2021-1532, Eqs. 11-13: the constants of Colonia et al. (Eq. 12) below Tu = 0.51%, + * the original ones (Eq. 11) above Tu = 2%, linearly blended in between. Tu_L is the freestream Tu. ---*/ + const su2double Tu_blend = min(max(Tu_L, 0.51), 2.0); + C_TU1 = (100.0 - 163.0) / (2.0 - 0.51) * (Tu_blend - 2.0) + 100.0; + C_TU2 = (1000.0 - 1002.25) / (2.0 - 0.51) * (Tu_blend - 2.0) + 1000.0; + } rethetac = C_TU1 + C_TU2 * exp(-C_TU3 * Tu_L * FPG); break; diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index 718d575527e0..b71d517f1411 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -397,6 +397,7 @@ class CSourcePieceWise_TransSLM final : public CNumerics { su2double Re_t; su2double Corr_Rec = 1.0; su2double AuxVar = 0.0; /*!< \brief Wall-normal derivative of the wall-normal velocity (Menter correlation). */ + su2double CrossFlowPsi = 0.0; /*!< \brief Wall-normal change of the vorticity direction times the wall distance. */ su2double F2; su2double Tu_Here = 0.0; su2double duds_Here = 0.0; @@ -415,6 +416,41 @@ class CSourcePieceWise_TransSLM final : public CNumerics { TransLMCorrelations TransCorrelations; + /*! + * \brief Magnitude of the streamwise vorticity, |U/|U| . Omega|. + */ + su2double StreamwiseVorticity(su2double vel_u, su2double vel_v, su2double vel_w, su2double Velocity_Mag) const { + const su2double velocity[3] = {vel_u, vel_v, vel_w}; + su2double streamwiseVort = 0.0; + for (auto iDim = 0u; iDim < nDim; iDim++) streamwiseVort += velocity[iDim] / Velocity_Mag * Vorticity_i[iDim]; + return fabs(streamwiseVort); + } + + /*! + * \brief Stationary cross-flow Reynolds number of Langtry et al., Lee and Baeder (AIAA 2021-1532), Eqs. 36-42. + * Eq. 36 is implicit in theta_t and is solved by fixed-point iteration, as in the LM2015 option of + * CSourcePieceWise_TransLM. + */ + su2double StationaryCrossFlowReynolds(su2double vel_u, su2double vel_v, su2double vel_w, su2double Velocity_Mag, + su2double R_t, const CConfig* config) const { + const su2double H_CF = StreamwiseVorticity(vel_u, vel_v, vel_w, Velocity_Mag) * dist_i / Velocity_Mag; // Eq. 37 + const su2double DeltaH_CF = H_CF * (1.0 + min(R_t, 0.4)); // Eq. 38 + const su2double DeltaH_CF_Plus = max(0.1066 - DeltaH_CF, 0.0); // Eq. 39 + const su2double fDeltaH_CF_Plus = 6200 * DeltaH_CF_Plus + 50000 * DeltaH_CF_Plus * DeltaH_CF_Plus; // Eq. 40 + const su2double DeltaH_CF_Minus = max(-(0.1066 - DeltaH_CF), 0.0); // Eq. 41 + const su2double fDeltaH_CF_Minus = 75.0 * tanh(DeltaH_CF_Minus / 0.0125); // Eq. 42 + + const su2double h = config->GethRoughness(); + su2double reScf = 20.0, error = 1.0; + for (int iter = 0; iter < 100 && error > 1e-5; iter++) { + const su2double theta_t = max(1e-20, reScf * Laminar_Viscosity_i / (Density_i * Velocity_Mag / 0.82)); + const su2double reScfNew = -35.088 * log(h / theta_t) + 319.51 + fDeltaH_CF_Plus - fDeltaH_CF_Minus; + error = fabs(reScfNew - reScf) / fabs(reScf); + reScf = reScfNew; + } + return max(reScf, 1e-20); + } + public: /*! * \brief Constructor of the class. @@ -450,6 +486,7 @@ class CSourcePieceWise_TransSLM final : public CNumerics { AD::SetPreaccIn(ScalarVar_i, nVarTurb); AD::SetPreaccIn(ScalarVar_Grad_i, nVarTurb, nDim); AD::SetPreaccIn(AuxVar); + AD::SetPreaccIn(CrossFlowPsi); AD::SetPreaccIn(TransVar_i, nVar); AD::SetPreaccIn(TransVar_Grad_i, nVar, nDim); AD::SetPreaccIn(Volume); @@ -484,42 +521,40 @@ class CSourcePieceWise_TransSLM final : public CNumerics { Tu_Here = Tu_L; /*--- F_length ---*/ - su2double F_length = 100.0; + const su2double F_length = 100.0; // Menter et al. (2015), Eq. 6, and Lee and Baeder (2021), Eq. 7. /*--- F_onset ---*/ su2double R_t = 1.0; if (TurbFamily == TURB_FAMILY::KW) R_t = Density_i * ScalarVar_i[0] / (Laminar_Viscosity_i * ScalarVar_i[1]); + /*--- Lee and Baeder (AIAA 2021-1532), Eq. 6: k and omega are replaced by the viscosity ratio for SA. ---*/ if (TurbFamily == TURB_FAMILY::SA) R_t = Eddy_Viscosity_i / Laminar_Viscosity_i; + /*--- Menter et al. (2015), Eqs. 12-13, and Lee and Baeder (2021), Eq. 9. ---*/ const su2double lambda_theta = max(min(-7.57e-3 * AuxVar * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0128, 1.0), -1.0); duds_Here = AuxVar; lambda_theta_Here = lambda_theta; - - /*--- Corr_RetC correlation*/ - Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, lambda_theta, dist_i, VorticityMag, Velocity_Mag); - Corr_Rec = Re_t; // If the MENTER_SLM correlation is used then they are the same thing - - if (options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::CODER_SLM || options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MOD_EPPLER_SLM) { - // If these correlations are used, then the value of Corr_Rec has to be used instead of the TransVar[1] of the original LM model - F_length = TransCorrelations.FLength_Correlations(Tu_L, Re_t); - Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu_L, Re_t); - } + /*--- Critical Reynolds number, Menter et al. (2015), Eq. 14, and Lee and Baeder (2021), Eqs. 10-13. ---*/ + Re_t = TransCorrelations.ReThetaC_Correlations_SLM(Tu_L, lambda_theta, dist_i, VorticityMag, Velocity_Mag, + TurbFamily == TURB_FAMILY::SA); + Corr_Rec = Re_t; const su2double Re_v = Density_i * dist_i * dist_i * StrainMag_i / Laminar_Viscosity_i; Re_v_Here = Re_v; - const su2double F_onset1 = Re_v / (2.2 * Corr_Rec); - su2double F_onset2 = 1.0; - su2double F_onset3 = 1.0; - if (TurbFamily == TURB_FAMILY::KW) { - F_onset2 = min(F_onset1, 2.0); - F_onset3 = max(1.0 - pow(R_t / 3.5, 3.0), 0.0); - } - if (TurbFamily == TURB_FAMILY::SA) { - F_onset2 = min(max(F_onset1, pow(F_onset1, 4.0)), 4.0); - F_onset3 = max(2.0 - pow(R_t / 2.5, 3.0), 0.0); + + /*--- Menter et al. (2015), Eqs. 4-5, and Lee and Baeder (2021), Eqs. 4-5 (the same for SST and SA). ---*/ + su2double F_onset1 = Re_v / (2.2 * Corr_Rec); + + if (options.CrossFlow && TurbFamily == TURB_FAMILY::SA) { + /*--- Langtry et al. stationary cross-flow criterion, Lee and Baeder (2021), Eqs. 36-43. ---*/ + const su2double Re_scf = StationaryCrossFlowReynolds(vel_u, vel_v, vel_w, Velocity_Mag, R_t, config); + const su2double c_scf = 0.94; + F_onset1 = max(F_onset1, c_scf * Re_v / (2.2 * Re_scf)); } + + const su2double F_onset2 = min(F_onset1, 2.0); + const su2double F_onset3 = max(1.0 - pow(R_t / 3.5, 3.0), 0.0); su2double F_onset = max(F_onset2 - F_onset3, 0.0); F_onset1_Here = F_onset1; @@ -527,11 +562,22 @@ class CSourcePieceWise_TransSLM final : public CNumerics { F_onset3_Here = F_onset3; F_onset_Here = F_onset; - if (options.CrossFlow) { + if (options.CrossFlow && TurbFamily == TURB_FAMILY::SA) { + /*--- Menter and Smirnov C1-based cross-flow criterion, Lee and Baeder (2021), Eqs. 25-35. ---*/ + const su2double lambda_CF = min(max(-7.57e-3 * AuxVar * dist_i * dist_i * Density_i / Laminar_Viscosity_i + 0.0174, 0.0), 0.0477); + const su2double g_CF = min(max(27864.0 * pow(lambda_CF, 3) - 1962.0 * pow(lambda_CF, 2) + 54.3 * lambda_CF + 1.0, 1.0), 2.3); + const su2double G_CF = 0.684 / g_CF; + const su2double C_RSF = 1.35; // Calibrated for SA by Lee and Baeder (1.0 in the original model). + const su2double T_C1 = C_RSF / 150.0 * G_CF * CrossFlowPsi * Re_v; + const su2double F_onset_CF = min(max(100.0 * (T_C1 - 1.0), 0.0), 1.0); + F_onset = max(F_onset, F_onset_CF); + } - // Taken from Vallinayagam Pillai, S., & Lardeau, S. (2017). "Accounting crossflow effects in one-equation + if (options.CrossFlow && TurbFamily == TURB_FAMILY::KW) { + + // Taken from Vallinayagam Pillai, S., & Lardeau, S. (2017). "Accounting crossflow effects in one-equation // local correlation-based transition model."" In 8th AIAA Theoretical Fluid Mechanics Conference (p. 3159). - + // Computation of shape factor const su2double k = 0.25 - lambda_theta; const su2double FirstTerm = 4.14 * k; @@ -550,23 +596,11 @@ class CSourcePieceWise_TransSLM final : public CNumerics { Re_Crit_CF = (300.0/PI_NUMBER) * atan(0.106/(pow(H-2.3, 2.05))); } - // Helicity computation - su2double VelocityNormalized[3]; - VelocityNormalized[0] = vel_u / Velocity_Mag; - VelocityNormalized[1] = vel_v / Velocity_Mag; - if (nDim == 3) VelocityNormalized[2] = vel_w / Velocity_Mag; - - su2double StreamwiseVort = 0.0; - for (auto iDim = 0u; iDim < nDim; iDim++) { - StreamwiseVort += VelocityNormalized[iDim] * Vorticity_i[iDim]; - } - StreamwiseVort = abs(StreamwiseVort); - - const su2double H_CF = StreamwiseVort * dist_i / Velocity_Mag; + const su2double H_CF = StreamwiseVorticity(vel_u, vel_v, vel_w, Velocity_Mag) * dist_i / Velocity_Mag; // Computation of Delta_H_CF. Here I have included directly R_t as the ration between turb and lam viscosity const su2double Delta_H_CF = H_CF * (1.0 + min(Eddy_Viscosity_i / Laminar_Viscosity_i, 0.4)); - + // Take into account for roughness const su2double h_0 = 0.25e-6; const su2double C_r = 2.0 - pow(0.5, config->GethRoughness()/h_0); @@ -580,26 +614,33 @@ class CSourcePieceWise_TransSLM final : public CNumerics { F_onset = max(F_onset, F_onset_CF); } - + + /*--- Menter et al. (2015), Eq. 5, and Lee and Baeder (2021), Eq. 6. ---*/ const su2double f_turb = exp(-pow(R_t / 2, 4)); - /*-- production term of Intermeittency(Gamma) --*/ - const su2double Pg = - F_length * Density_i * StrainMag_i * F_onset * TransVar_i[0] * (1.0 - TransVar_i[0]); + /*--- Production and destruction of the intermittency, Menter et al. (2015), Eqs. 2-3, and Lee and Baeder + * (2021), Eqs. 2-3, written as gamma*(P - D) with (Eqs. 22-23) ---*/ + const su2double P = F_length * StrainMag_i * (1.0 - TransVar_i[0]) * F_onset; + const su2double D = c_a2 * VorticityMag * f_turb * (c_e2 * TransVar_i[0] - 1.0); + const su2double Pg = Density_i * TransVar_i[0] * P; + const su2double Dg = Density_i * TransVar_i[0] * D; - /*-- destruction term of Intermeittency(Gamma) --*/ - const su2double Dg = c_a2 * Density_i * VorticityMag * TransVar_i[0] * f_turb * (c_e2 * TransVar_i[0] - 1.0); - Prod_Here = Pg; Destr_Here = Dg; /*--- Source ---*/ Residual += (Pg - Dg) * Volume; - /*--- Implicit part ---*/ - Jacobian_i[0] = (F_length * StrainMag_i * F_onset * (1 - 2*TransVar_i[0]) - - c_a2 * VorticityMag * f_turb * (2.0 * c_e2 * TransVar_i[0] - 1.0)) * - Volume; + /*--- Implicit part, per unit rho*gamma. ---*/ + if (TurbFamily == TURB_FAMILY::SA) { + /*--- Positivity of the implicit operator, Lee and Baeder (2021), Eq. 24. ---*/ + const su2double dP = -F_length * StrainMag_i * F_onset; + const su2double dD = c_a2 * VorticityMag * f_turb * c_e2; + Jacobian_i[0] = -(max(D - P, 0.0) + max(dD - dP, 0.0) * TransVar_i[0]) * Volume; + } else { + Jacobian_i[0] = (F_length * StrainMag_i * F_onset * (1 - 2*TransVar_i[0]) - + c_a2 * VorticityMag * f_turb * (2.0 * c_e2 * TransVar_i[0] - 1.0)) * Volume; + } } @@ -623,6 +664,7 @@ class CSourcePieceWise_TransSLM final : public CNumerics { inline su2double GetF_onset3() override {return F_onset3_Here;} inline su2double GetF_onset() override {return F_onset_Here;} inline void SetAuxVar(su2double val_AuxVar) override { AuxVar = val_AuxVar;} + inline void SetCrossFlowStrength(su2double val_Psi) override { CrossFlowPsi = val_Psi; } // non serve più inline void SetF2(su2double val_F2) override { F2 = val_F2;} diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index bba75fc6fb75..543a236aa4ea 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -80,6 +80,7 @@ class CSourceBase_TurbSA : public CNumerics { const bool axisymmetric = false; bool transition_LM; + bool transition_SLM; /*!< \brief One-equation (simplified) LM model. */ /*! * \brief Add contribution from diffusion due to axisymmetric formulation to 2D residual @@ -195,7 +196,8 @@ class CSourceBase_TurbSA : public CNumerics { idx(nDim, config->GetnSpecies()), options(config->GetSAParsedOptions()), axisymmetric(config->GetAxisymmetric()), - transition_LM(config->GetKind_Trans_Model() == TURB_TRANS_MODEL::LM) { + transition_LM(config->GetKind_Trans_Model() == TURB_TRANS_MODEL::LM), + transition_SLM(transition_LM && config->GetLMParsedOptions().SLM) { /*--- Setup the Jacobian pointer, we need to return su2double** but we know * the Jacobian is 1x1 so we use this trick to avoid heap allocation. ---*/ /*--- Setup the Jacobian pointer (size increased for Stochastic Backscatter Model). ---*/ @@ -323,6 +325,15 @@ class CSourceBase_TurbSA : public CNumerics { var.intermittency = intermittency_eff_i; var.interDestrFactor = 1; + } else if (transition_SLM) { + + /*--- Lee and Baeder (AIAA 2021-1532), Eqs. 17-18: the scaled intermittency, which is zero in the laminar + * boundary layer, multiplies the production, and max(gamma_s, 0.1) the destruction. ---*/ + const su2double c_e2 = 50.0; + const su2double gamma_s = max(min((min(intermittency_i, 1.0) - 1.0 / c_e2) / (1.0 - 1.0 / c_e2), 1.0), 0.0); + var.intermittency = gamma_s; + var.interDestrFactor = max(gamma_s, 0.1); + } else if (transition_LM){ var.intermittency = intermittency_eff_i; diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 241fd870d634..19cc3285175e 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -210,12 +210,22 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain if (options.SLM && options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) { + /*--- With cross-flow and SA, the auxiliary variables 1-3 are the direction of the vorticity, e_omega, of which + * the gradient gives the cross-flow strength of Lee and Baeder (AIAA 2021-1532), Eqs. 31-33. ---*/ + const bool crossFlowSA = options.CrossFlow && TurbFamily == TURB_FAMILY::SA; + auto* flowNodes = su2staticcast_p(solver_container[FLOW_SOL]->GetNodes()); SU2_OMP_FOR_STAT(omp_chunk_size) - for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { auto Normal = geometry->nodes->GetNormal(iPoint); nodes->SetAuxVar(iPoint, 0, flowNodes->GetProjVel(iPoint, Normal)); nodes->SetNormal(iPoint, Normal[0], Normal[1], Normal[2]); + if (crossFlowSA) { + const auto Vorticity = flowNodes->GetVorticity(iPoint); + const su2double VorticityMag = GeometryToolbox::Norm(3, Vorticity); + for (auto iDim = 0u; iDim < 3; iDim++) + nodes->SetAuxVar(iPoint, 1 + iDim, VorticityMag > 1e-12 ? Vorticity[iDim] / VorticityMag : 0.0); + } } END_SU2_OMP_FOR @@ -227,6 +237,8 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain } + /*--- After the gradients, auxiliary variable 0 becomes dV/dy = grad(n . V) . n and, with cross-flow and SA, + * auxiliary variable 1 becomes Psi = |n . grad(e_omega)| d_w (Lee and Baeder, Eqs. 32-33). ---*/ SU2_OMP_FOR_STAT(omp_chunk_size) for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { su2double AuxVarHere = 0.0; @@ -234,6 +246,14 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain for (auto iDim = 0u; iDim < nDim; iDim++) AuxVarHere += Normal[iDim] * nodes->GetAuxVarGradient(iPoint, 0, iDim); nodes->SetAuxVar(iPoint, 0, AuxVarHere); + + if (crossFlowSA) { + su2double phi[3] = {0.0, 0.0, 0.0}; + for (auto iVar = 0u; iVar < 3; iVar++) + for (auto iDim = 0u; iDim < nDim; iDim++) + phi[iVar] += Normal[iDim] * nodes->GetAuxVarGradient(iPoint, 1 + iVar, iDim); + nodes->SetAuxVar(iPoint, 1, GeometryToolbox::Norm(3, phi) * geometry->nodes->GetWall_Distance(iPoint)); + } } END_SU2_OMP_FOR @@ -434,6 +454,7 @@ void CTransLMSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta if(options.SLM) { if (options.Correlation_SLM == TURB_TRANS_CORRELATION_SLM::MENTER_SLM) numerics->SetAuxVar(nodes->GetAuxVar(iPoint, 0)); + if (options.CrossFlow && TurbFamily == TURB_FAMILY::SA) numerics->SetCrossFlowStrength(nodes->GetAuxVar(iPoint, 1)); numerics->SetF2(turbNodes->GetF2blending(iPoint)); } diff --git a/SU2_CFD/src/variables/CTransLMVariable.cpp b/SU2_CFD/src/variables/CTransLMVariable.cpp index f35d98d6c3df..15cd728a945e 100644 --- a/SU2_CFD/src/variables/CTransLMVariable.cpp +++ b/SU2_CFD/src/variables/CTransLMVariable.cpp @@ -55,7 +55,9 @@ CTransLMVariable::CTransLMVariable(su2double Intermittency, su2double ReThetaT, if (options.SLM) { Re_t.resize(nPoint) = ReThetaT; - nAuxVar = 1; + /*--- Wall-normal velocity, and with cross-flow for SA the three components of the vorticity direction. ---*/ + const bool crossFlowSA = options.CrossFlow && TurbModelFamily(config->GetKind_Turb_Model()) == TURB_FAMILY::SA; + nAuxVar = crossFlowSA ? 4 : 1; Grad_AuxVar.resize(nPoint, nAuxVar, nDim, su2double(0.0)); AuxVar.resize(nPoint, nAuxVar) = su2double(0.0); Tu.resize(nPoint) = su2double(0.0); From fc979ed9f9f3a2f84f9a334435c9583914176005 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:50:32 +0200 Subject: [PATCH 52/61] Register the intermittencies as preaccumulation inputs of the SA source The SA source uses the intermittency of the LM models but did not declare it as a preaccumulation input, so its derivative was lost in AD. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- SU2_CFD/include/numerics/turbulent/turb_sources.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp index 543a236aa4ea..c0f506f0ec8f 100644 --- a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -221,6 +221,7 @@ class CSourceBase_TurbSA : public CNumerics { AD::SetPreaccIn(PrimVar_Grad_i + idx.Velocity(), nDim, nDim); AD::SetPreaccIn(ScalarVar_Grad_i, nVar, nDim); AD::SetPreaccIn(stochSource, 3); + if (transition_LM) AD::SetPreaccIn(intermittency_i, intermittency_eff_i); /*--- Common auxiliary variables and constants of the model. ---*/ CSAVariables var; From 55fe05d5497bb4ec189af7f0c5babd58ad9ae7f0 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:56:53 +0200 Subject: [PATCH 53/61] Limit the roughness height in the Langtry cross-flow correlation The stationary cross-flow Reynolds number of Langtry et al. contains log(h / theta_t), which diverges for HROUGHNESS= 0. Limit h from below to 0.25 micrometers, the smallest roughness for which the correlation was validated by Lee and Baeder (AIAA 2021-1532) and the reference height h0 of Vallinayagam Pillai and Lardeau (AIAA 2017-3159). Applied to the SA cross-flow of the simplified model and to the LM2015 option of the two-equation model. The roughness factor C_r of the SST cross-flow model is finite for h = 0 and is unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- .../numerics/turbulent/transition/trans_sources.hpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index b71d517f1411..bc9aa35d318f 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -29,6 +29,12 @@ #include "../../scalar/scalar_sources.hpp" #include "./trans_correlations.hpp" +/*--- Lower limit of the RMS roughness height in the log(h / theta_t) of the Langtry et al. stationary cross-flow + * correlation, which diverges for h = 0: 0.25 micrometers, the smallest roughness for which the correlation was + * validated by Lee and Baeder (AIAA 2021-1532, Radeztsky et al. data) and the reference height h0 of Vallinayagam + * Pillai and Lardeau (AIAA 2017-3159, Eq. 9). Smoother surfaces are treated as this one. HROUGHNESS is in meters. ---*/ +constexpr passivedouble LANGTRY_CF_MIN_ROUGHNESS = 0.25e-6; + /*! * \class CSourcePieceWise_TranLM * \brief Class for integrating the source terms of the LM transition model equations. @@ -301,7 +307,8 @@ class CSourcePieceWise_TransLM final : public CNumerics { thetat_SCF = rethetat_SCF_old * Laminar_Viscosity_i / (Density_i * (Velocity_Mag / 0.82)); thetat_SCF = max(1e-20, thetat_SCF); - ReThetat_SCF = -35.088 * log(hRoughness / thetat_SCF) + 319.51 + fDeltaH_CF_Plus - fDeltaH_CF_Minus; + ReThetat_SCF = -35.088 * log(max(hRoughness, su2double(LANGTRY_CF_MIN_ROUGHNESS)) / thetat_SCF) + 319.51 + + fDeltaH_CF_Plus - fDeltaH_CF_Minus; error = abs(ReThetat_SCF - rethetat_SCF_old) / rethetat_SCF_old; @@ -440,7 +447,7 @@ class CSourcePieceWise_TransSLM final : public CNumerics { const su2double DeltaH_CF_Minus = max(-(0.1066 - DeltaH_CF), 0.0); // Eq. 41 const su2double fDeltaH_CF_Minus = 75.0 * tanh(DeltaH_CF_Minus / 0.0125); // Eq. 42 - const su2double h = config->GethRoughness(); + const su2double h = max(config->GethRoughness(), su2double(LANGTRY_CF_MIN_ROUGHNESS)); su2double reScf = 20.0, error = 1.0; for (int iter = 0; iter < 100 && error > 1e-5; iter++) { const su2double theta_t = max(1e-20, reScf * Laminar_Viscosity_i / (Density_i * Velocity_Mag / 0.82)); From 3958556de4e47afe684c33567e0d3fa7b9160783 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 17:57:18 +0200 Subject: [PATCH 54/61] Cite the equations of Vallinayagam Pillai and Lardeau (2017) in the SST cross-flow model The implementation matches Eqs. 2-10 and 17-18 of AIAA 2017-3159. The sign of Eq. 2 differs from the printed one, which gives a negative critical Reynolds number; the comment now explains it. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- .../turbulent/transition/trans_sources.hpp | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index bc9aa35d318f..46a8abc6e44b 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -582,10 +582,11 @@ class CSourcePieceWise_TransSLM final : public CNumerics { if (options.CrossFlow && TurbFamily == TURB_FAMILY::KW) { - // Taken from Vallinayagam Pillai, S., & Lardeau, S. (2017). "Accounting crossflow effects in one-equation - // local correlation-based transition model."" In 8th AIAA Theoretical Fluid Mechanics Conference (p. 3159). + /*--- Vallinayagam Pillai and Lardeau, "Accounting crossflow effects in one-equation local correlation-based + * transition model", AIAA 2017-3159 (equation numbers below). ---*/ - // Computation of shape factor + // Shape factor, Eq. 3 with k = 0.25 - lambda (lambda_theta_L of the gamma model), limited to 2.7 above which + // the crossflow criterion does not apply (text after Eq. 3) const su2double k = 0.25 - lambda_theta; const su2double FirstTerm = 4.14 * k; const su2double SecondTerm = 83.5 * pow(k, 2.0); @@ -594,30 +595,31 @@ class CSourcePieceWise_TransSLM final : public CNumerics { const su2double FifthTerm = 4576.0 * pow(k, 5.0); const su2double H = min(2.0 + FirstTerm - SecondTerm + ThirdTerm - ForthTerm + FifthTerm, 2.7); - // Computation of critical cross flow Reynolds number + // Critical crossflow Reynolds number, Eq. 2 su2double Re_Crit_CF = 0.0; if(H < 2.3) { Re_Crit_CF = 150.0; } else { - // Correct from paper since for H = 2.3 it was not continuous if a minus sign is added here + // Eq. 2 is printed with a minus sign, which gives -150 at H = 2.3 and negative critical Reynolds numbers; + // the positive sign makes it continuous with the value 150 below H = 2.3 Re_Crit_CF = (300.0/PI_NUMBER) * atan(0.106/(pow(H-2.3, 2.05))); } const su2double H_CF = StreamwiseVorticity(vel_u, vel_v, vel_w, Velocity_Mag) * dist_i / Velocity_Mag; - // Computation of Delta_H_CF. Here I have included directly R_t as the ration between turb and lam viscosity + // Crossflow strength H_cf, Eqs. 4-6, and Delta_H_cf, Eq. 8 const su2double Delta_H_CF = H_CF * (1.0 + min(Eddy_Viscosity_i / Laminar_Viscosity_i, 0.4)); - // Take into account for roughness + // Roughness, Eq. 9, h0 = 0.25 micrometers (HROUGHNESS in meters) const su2double h_0 = 0.25e-6; const su2double C_r = 2.0 - pow(0.5, config->GethRoughness()/h_0); - // Construct Cross flow activation function + // f_cf, Eqs. 7 and 10, with C_cf = 1 const su2double C_CF = 1.0; const su2double f_CF = (C_CF * C_r * Delta_H_CF * Corr_Rec) / Re_Crit_CF; const su2double F_onset_CF = min(max(0.0, f_CF - 1.0), 1.0); - // Adjust onset function for intermittency + // Eqs. 17-18 F_onset = max(F_onset, F_onset_CF); } From 53c15bb058ad4f874a5b7c755a595c0c2091df05 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 18:16:00 +0200 Subject: [PATCH 55/61] Limit the cross-flow roughness height to 1e-8 and print it at startup The papers give no calibration limit for small roughness heights, so the limit of the previous commit (0.25 micrometers, the smallest validated height) is replaced by h >= 1e-8, in the units of HROUGHNESS. It applies to log(h/theta_t) of the Langtry et al. correlation (SA cross-flow of the simplified model, and the cross-flow option of the two-equation model) and to h/h0 of the SST cross-flow model of Vallinayagam Pillai and Lardeau. The limit and whether HROUGHNESS is below it are printed at startup. h and theta_t are both in mesh length units (reference length 1), so log(h/theta_t) does not depend on REF_DIMENSIONALIZATION. Also add the missing end of line after the name of the simplified model without cross-flow. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- Common/include/option_structure.hpp | 9 +++++++++ Common/src/CConfig.cpp | 10 +++++++++- .../turbulent/transition/trans_sources.hpp | 14 ++++---------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp index f7c547772396..2d0664281b15 100644 --- a/Common/include/option_structure.hpp +++ b/Common/include/option_structure.hpp @@ -1432,6 +1432,15 @@ enum class TURB_TRANS_CORRELATION_SLM { DEFAULT /*!< \brief Kind of transition correlation model. */ }; +/*! + * \brief Lower limit of the roughness height (HROUGHNESS, same units) in the cross-flow corrections of the LM models, + * where it enters a logarithm (Langtry et al., log(h/theta_t)) or a ratio (Vallinayagam Pillai and Lardeau, + * h/h0). The papers give no calibration limit for small heights, so a small value keeps these terms finite + * for smooth surfaces (h = 0). h and theta_t are both in mesh length units (the reference length of the + * non-dimensionalization is 1), so log(h/theta_t) is consistent for any REF_DIMENSIONALIZATION. + */ +constexpr double LM_CROSSFLOW_MIN_ROUGHNESS = 1e-8; + /*! * \brief Structure containing parsed LM options. */ diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 4181f9681596..f61803a9a861 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -6736,10 +6736,18 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { cout << " (2015)"; } cout << endl; + cout << "Roughness height of the cross-flow model (HROUGHNESS, in mesh length units): limited to at least " + << LM_CROSSFLOW_MIN_ROUGHNESS << " to keep log(h/theta_t) and h/h0 finite (the papers give no\n" + << "calibration limit for small heights); "; + if (hRoughness < LM_CROSSFLOW_MIN_ROUGHNESS) + cout << "the given value " << hRoughness << " is below it, " << LM_CROSSFLOW_MIN_ROUGHNESS << " is used." << endl; + else + cout << "the given value " << hRoughness << " is used." << endl; } else { if (!lmParsedOptions.SLM) { - cout << " (2009)" << endl; + cout << " (2009)"; } + cout << endl; } break; } diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index 46a8abc6e44b..678e0802328d 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -29,12 +29,6 @@ #include "../../scalar/scalar_sources.hpp" #include "./trans_correlations.hpp" -/*--- Lower limit of the RMS roughness height in the log(h / theta_t) of the Langtry et al. stationary cross-flow - * correlation, which diverges for h = 0: 0.25 micrometers, the smallest roughness for which the correlation was - * validated by Lee and Baeder (AIAA 2021-1532, Radeztsky et al. data) and the reference height h0 of Vallinayagam - * Pillai and Lardeau (AIAA 2017-3159, Eq. 9). Smoother surfaces are treated as this one. HROUGHNESS is in meters. ---*/ -constexpr passivedouble LANGTRY_CF_MIN_ROUGHNESS = 0.25e-6; - /*! * \class CSourcePieceWise_TranLM * \brief Class for integrating the source terms of the LM transition model equations. @@ -307,7 +301,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { thetat_SCF = rethetat_SCF_old * Laminar_Viscosity_i / (Density_i * (Velocity_Mag / 0.82)); thetat_SCF = max(1e-20, thetat_SCF); - ReThetat_SCF = -35.088 * log(max(hRoughness, su2double(LANGTRY_CF_MIN_ROUGHNESS)) / thetat_SCF) + 319.51 + + ReThetat_SCF = -35.088 * log(max(hRoughness, su2double(LM_CROSSFLOW_MIN_ROUGHNESS)) / thetat_SCF) + 319.51 + fDeltaH_CF_Plus - fDeltaH_CF_Minus; error = abs(ReThetat_SCF - rethetat_SCF_old) / rethetat_SCF_old; @@ -447,7 +441,7 @@ class CSourcePieceWise_TransSLM final : public CNumerics { const su2double DeltaH_CF_Minus = max(-(0.1066 - DeltaH_CF), 0.0); // Eq. 41 const su2double fDeltaH_CF_Minus = 75.0 * tanh(DeltaH_CF_Minus / 0.0125); // Eq. 42 - const su2double h = max(config->GethRoughness(), su2double(LANGTRY_CF_MIN_ROUGHNESS)); + const su2double h = max(config->GethRoughness(), su2double(LM_CROSSFLOW_MIN_ROUGHNESS)); su2double reScf = 20.0, error = 1.0; for (int iter = 0; iter < 100 && error > 1e-5; iter++) { const su2double theta_t = max(1e-20, reScf * Laminar_Viscosity_i / (Density_i * Velocity_Mag / 0.82)); @@ -610,9 +604,9 @@ class CSourcePieceWise_TransSLM final : public CNumerics { // Crossflow strength H_cf, Eqs. 4-6, and Delta_H_cf, Eq. 8 const su2double Delta_H_CF = H_CF * (1.0 + min(Eddy_Viscosity_i / Laminar_Viscosity_i, 0.4)); - // Roughness, Eq. 9, h0 = 0.25 micrometers (HROUGHNESS in meters) + // Roughness, Eq. 9, h0 = 0.25 micrometers: HROUGHNESS and the mesh must be in meters const su2double h_0 = 0.25e-6; - const su2double C_r = 2.0 - pow(0.5, config->GethRoughness()/h_0); + const su2double C_r = 2.0 - pow(0.5, max(config->GethRoughness(), LM_CROSSFLOW_MIN_ROUGHNESS)/h_0); // f_cf, Eqs. 7 and 10, with C_cf = 1 const su2double C_CF = 1.0; From aefa3c92c9f6a5fac3f7c40aa6790d778448eefb Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 20:44:51 +0200 Subject: [PATCH 56/61] Fix the AD build of the cross-flow vorticity direction The two branches of the conditional had an AD expression and a double. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- SU2_CFD/src/solvers/CTransLMSolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 19cc3285175e..878a46ea3b6e 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -224,7 +224,7 @@ void CTransLMSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain const auto Vorticity = flowNodes->GetVorticity(iPoint); const su2double VorticityMag = GeometryToolbox::Norm(3, Vorticity); for (auto iDim = 0u; iDim < 3; iDim++) - nodes->SetAuxVar(iPoint, 1 + iDim, VorticityMag > 1e-12 ? Vorticity[iDim] / VorticityMag : 0.0); + nodes->SetAuxVar(iPoint, 1 + iDim, VorticityMag > 1e-12 ? su2double(Vorticity[iDim] / VorticityMag) : su2double(0.0)); } } END_SU2_OMP_FOR From 56a6d92e8576671291602ec7fc422bf66d1d7b85 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 20:47:48 +0200 Subject: [PATCH 57/61] Stop with an error for discrete adjoints with a transition model The discrete adjoint solvers do not create the transition solver, but the SA and SST sources read its solution when KIND_TRANS_MODEL is set: with MATH_PROBLEM= DISCRETE_ADJOINT and LM (two-equation or simplified) SU2_CFD_AD crashed with a segmentation fault (null pointer) on the E387 case. Stop with a clear error instead. This also applies to the two-equation LM model of develop. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- Common/src/CConfig.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index f61803a9a861..cd1e4b6f4388 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -3835,6 +3835,13 @@ void CConfig::SetPostprocessing(SU2_COMPONENT val_software, unsigned short val_i SU2_MPI::Error("COMPRESSIBILITY-WILCOX only supported for SOLVER= RANS", CURRENT_FUNCTION); } + /*--- The transition solver has no discrete adjoint: the adjoint solvers do not create it, and the turbulence + * sources would read a missing transition solution. ---*/ + if (DiscreteAdjoint && Kind_Trans_Model != TURB_TRANS_MODEL::NONE) { + SU2_MPI::Error("KIND_TRANS_MODEL= LM is not available for discrete adjoint simulations (MATH_PROBLEM= DISCRETE_ADJOINT).", + CURRENT_FUNCTION); + } + /*--- Postprocess LM_OPTIONS into structure. ---*/ if (Kind_Trans_Model == TURB_TRANS_MODEL::LM) { lmParsedOptions = ParseLMOptions(LM_Options, nLM_Options, rank, Kind_Turb_Model); From b2a24aa09def9ffad44b9a8b11c30a9e9b6985d6 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Wed, 23 Sep 2026 21:22:26 +0200 Subject: [PATCH 58/61] Add regression tests for the simplified LM model on the prolate spheroid Four tests on the 6:1 prolate spheroid at 15 degrees (INC_RANS, coarse unstructured grid of 100958 points): SST and SA with MENTER_SLM, with and without cross-flow. Each runs 5 iterations from a converged SST or SA transitional solution; the cross-flow tests restart from the solution of their base model. The grid and the solutions are in su2code/TestCases, branch feature_Trans_SLM. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- TestCases/hybrid_regression.py | 15 +++++ TestCases/parallel_regression.py | 15 +++++ TestCases/serial_regression.py | 15 +++++ .../prolate_spheroid/sa_slm_menter.cfg | 64 ++++++++++++++++++ .../sa_slm_menter_crossflow.cfg | 65 ++++++++++++++++++ .../prolate_spheroid/sst_slm_menter.cfg | 65 ++++++++++++++++++ .../sst_slm_menter_crossflow.cfg | 66 +++++++++++++++++++ 7 files changed, 305 insertions(+) create mode 100644 TestCases/transition/prolate_spheroid/sa_slm_menter.cfg create mode 100644 TestCases/transition/prolate_spheroid/sa_slm_menter_crossflow.cfg create mode 100644 TestCases/transition/prolate_spheroid/sst_slm_menter.cfg create mode 100644 TestCases/transition/prolate_spheroid/sst_slm_menter_crossflow.cfg diff --git a/TestCases/hybrid_regression.py b/TestCases/hybrid_regression.py index cb34f9a48528..d471266dae2a 100644 --- a/TestCases/hybrid_regression.py +++ b/TestCases/hybrid_regression.py @@ -553,6 +553,21 @@ def main(): ddes_flatplate.unsteady = True test_list.append(ddes_flatplate) + # Simplified (one-equation) LM model on the 6:1 prolate spheroid at 15 deg, restarting from converged solutions + slm_spheroid_vals = {"sst_slm_menter": [-12.005703, -10.934023, -13.049797, -7.833317, -11.020316, 0.035351, 0.019157], + "sst_slm_menter_crossflow": [-12.005701, -10.933421, -11.401809, -6.035958, -6.621244, 0.035351, 0.019157], + "sa_slm_menter": [-10.467338, -8.467659, -12.443723, -6.570030, 0.035277, 0.017760], + "sa_slm_menter_crossflow": [-10.475794, -8.467045, -12.157988, -5.847505, 0.035277, 0.017760]} + for model, vals in slm_spheroid_vals.items(): + slm_spheroid = TestCase('slm_spheroid_' + model) + slm_spheroid.cfg_dir = "transition/prolate_spheroid" + slm_spheroid.cfg_file = model + ".cfg" + slm_spheroid.test_iter = 5 + slm_spheroid.test_vals = vals + slm_spheroid.grid_file = "spheroid_tiny.su2" + slm_spheroid.decompress = True + test_list.append(slm_spheroid) + # unsteady pitching NACA0015, SA unst_inc_turb_naca0015_sa = TestCase('unst_inc_turb_naca0015_sa') unst_inc_turb_naca0015_sa.cfg_dir = "unsteady/pitching_naca0015_rans_inc" diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index 87edd6666a17..2fcb4a774394 100755 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -939,6 +939,21 @@ def main(): schubauer_klebanoff_transition.test_vals = [-8.215651, -13.239431, 0.000048, 0.007983] test_list.append(schubauer_klebanoff_transition) + # Simplified (one-equation) LM model on the 6:1 prolate spheroid at 15 deg, restarting from converged solutions + slm_spheroid_vals = {"sst_slm_menter": [-12.005925, -10.934249, -13.049871, -7.833387, -11.020240, 0.035351, 0.019157], + "sst_slm_menter_crossflow": [-12.005896, -10.933645, -11.401809, -6.035959, -6.621244, 0.035351, 0.019157], + "sa_slm_menter": [-10.467263, -8.467663, -12.443722, -6.570030, 0.035277, 0.017760], + "sa_slm_menter_crossflow": [-10.475719, -8.467049, -12.157988, -5.847505, 0.035277, 0.017760]} + for model, vals in slm_spheroid_vals.items(): + slm_spheroid = TestCase('slm_spheroid_' + model) + slm_spheroid.cfg_dir = "transition/prolate_spheroid" + slm_spheroid.cfg_file = model + ".cfg" + slm_spheroid.test_iter = 5 + slm_spheroid.test_vals = vals + slm_spheroid.grid_file = "spheroid_tiny.su2" + slm_spheroid.decompress = True + test_list.append(slm_spheroid) + ##################################### ### Cont. adj. compressible Euler ### ##################################### diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py index 1479f3f11cc7..19cc0c5388b8 100755 --- a/TestCases/serial_regression.py +++ b/TestCases/serial_regression.py @@ -628,6 +628,21 @@ def main(): schubauer_klebanoff_transition.test_vals = [-8.284308, -13.239421, 0.000057, 0.007982] test_list.append(schubauer_klebanoff_transition) + # Simplified (one-equation) LM model on the 6:1 prolate spheroid at 15 deg, restarting from converged solutions + slm_spheroid_vals = {"sst_slm_menter": [-12.005703, -10.934023, -13.049797, -7.833317, -11.020316, 0.035351, 0.019157], + "sst_slm_menter_crossflow": [-12.005701, -10.933421, -11.401809, -6.035958, -6.621244, 0.035351, 0.019157], + "sa_slm_menter": [-10.467338, -8.467659, -12.443723, -6.570030, 0.035277, 0.017760], + "sa_slm_menter_crossflow": [-10.475794, -8.467045, -12.157988, -5.847505, 0.035277, 0.017760]} + for model, vals in slm_spheroid_vals.items(): + slm_spheroid = TestCase('slm_spheroid_' + model) + slm_spheroid.cfg_dir = "transition/prolate_spheroid" + slm_spheroid.cfg_file = model + ".cfg" + slm_spheroid.test_iter = 5 + slm_spheroid.test_vals = vals + slm_spheroid.grid_file = "spheroid_tiny.su2" + slm_spheroid.decompress = True + test_list.append(slm_spheroid) + ##################################### ### Cont. adj. compressible Euler ### ##################################### diff --git a/TestCases/transition/prolate_spheroid/sa_slm_menter.cfg b/TestCases/transition/prolate_spheroid/sa_slm_menter.cfg new file mode 100644 index 000000000000..3fc65c78377c --- /dev/null +++ b/TestCases/transition/prolate_spheroid/sa_slm_menter.cfg @@ -0,0 +1,64 @@ +% Transition on the 6:1 prolate spheroid at 15 degrees angle of attack, one-equation (simplified) LM model +% SA (Lee and Baeder, AIAA 2021-1532). +% Coarse unstructured grid (100958 points), restart from a converged SA + MENTER_SLM solution +% (solution_flow_sa_slm.dat), so that the transition front is established. +% +% ------------------------------ PROBLEM DEFINITION ------------------------------% +SOLVER= INC_RANS +KIND_TURB_MODEL= SA +KIND_TRANS_MODEL= LM +LM_OPTIONS= ( SLM, MENTER_SLM ) +FREESTREAM_TURBULENCEINTENSITY= 0.001 +FREESTREAM_TURB2LAMVISCRATIO= 5.0 +MATH_PROBLEM= DIRECT +RESTART_SOL= YES +% +% ------------------------------ FREE-STREAM -------------------------------------% +INC_DENSITY_INIT= 1.177 +INC_TEMPERATURE_INIT= 300 +INC_VELOCITY_INIT= ( 43.4667, 0.0, 11.647 ) +INC_NONDIM= INITIAL_VALUES +VISCOSITY_MODEL= CONSTANT_VISCOSITY +MU_CONSTANT= 1.853e-05 +% +% ------------------------------ REFERENCE VALUES --------------------------------% +REF_ORIGIN_MOMENT_X= 0.25 +REF_ORIGIN_MOMENT_Y= 0.00 +REF_ORIGIN_MOMENT_Z= 0.00 +REF_LENGTH= 2.4 +REF_AREA= 0 +% +% ------------------------------ BOUNDARY CONDITIONS -----------------------------% +MARKER_HEATFLUX= ( Ellipsoid, 0.0 ) +MARKER_FAR= ( Farfield ) +MARKER_PLOTTING= ( Ellipsoid ) +MARKER_MONITORING= ( Ellipsoid ) +% +% ------------------------------ NUMERICS ----------------------------------------% +NUM_METHOD_GRAD= GREEN_GAUSS +CFL_NUMBER= 20 +CFL_ADAPT= NO +ITER= 5 +LINEAR_SOLVER= FGMRES +LINEAR_SOLVER_PREC= ILU +LINEAR_SOLVER_ERROR= 1E-6 +LINEAR_SOLVER_ITER= 10 +CONV_NUM_METHOD_FLOW= JST +MUSCL_FLOW= NO +JST_SENSOR_COEFF= ( 0.5, 0.02 ) +TIME_DISCRE_FLOW= EULER_IMPLICIT +CONV_NUM_METHOD_TURB= SCALAR_UPWIND +MUSCL_TURB= NO +TIME_DISCRE_TURB= EULER_IMPLICIT +CONV_RESIDUAL_MINVAL= -12 +CONV_FIELD= ( RMS_PRESSURE ) +% +% ------------------------------ INPUT/OUTPUT ------------------------------------% +MESH_FILENAME= spheroid_tiny.su2 +MESH_FORMAT= SU2 +SOLUTION_FILENAME= solution_flow_sa_slm.dat +RESTART_FILENAME= restart_flow.dat +OUTPUT_FILES= (RESTART) +OUTPUT_WRT_FREQ= 1000 +SCREEN_OUTPUT= (INNER_ITER, RMS_PRESSURE, RMS_VELOCITY-X, RMS_NU_TILDE, RMS_INTERMITTENCY, LIFT, DRAG) +HISTORY_OUTPUT= (ITER, RMS_RES, AERO_COEFF) diff --git a/TestCases/transition/prolate_spheroid/sa_slm_menter_crossflow.cfg b/TestCases/transition/prolate_spheroid/sa_slm_menter_crossflow.cfg new file mode 100644 index 000000000000..b994c5315c55 --- /dev/null +++ b/TestCases/transition/prolate_spheroid/sa_slm_menter_crossflow.cfg @@ -0,0 +1,65 @@ +% Transition on the 6:1 prolate spheroid at 15 degrees angle of attack, one-equation (simplified) LM model +% SA (Lee and Baeder, AIAA 2021-1532) with cross-flow. +% Coarse unstructured grid (100958 points), restart from a converged SA + MENTER_SLM solution +% (solution_flow_sa_slm.dat), so that the transition front is established. +% +% ------------------------------ PROBLEM DEFINITION ------------------------------% +SOLVER= INC_RANS +KIND_TURB_MODEL= SA +KIND_TRANS_MODEL= LM +LM_OPTIONS= ( SLM, MENTER_SLM, CROSSFLOW ) +FREESTREAM_TURBULENCEINTENSITY= 0.001 +FREESTREAM_TURB2LAMVISCRATIO= 5.0 +HROUGHNESS= 3.3e-6 +MATH_PROBLEM= DIRECT +RESTART_SOL= YES +% +% ------------------------------ FREE-STREAM -------------------------------------% +INC_DENSITY_INIT= 1.177 +INC_TEMPERATURE_INIT= 300 +INC_VELOCITY_INIT= ( 43.4667, 0.0, 11.647 ) +INC_NONDIM= INITIAL_VALUES +VISCOSITY_MODEL= CONSTANT_VISCOSITY +MU_CONSTANT= 1.853e-05 +% +% ------------------------------ REFERENCE VALUES --------------------------------% +REF_ORIGIN_MOMENT_X= 0.25 +REF_ORIGIN_MOMENT_Y= 0.00 +REF_ORIGIN_MOMENT_Z= 0.00 +REF_LENGTH= 2.4 +REF_AREA= 0 +% +% ------------------------------ BOUNDARY CONDITIONS -----------------------------% +MARKER_HEATFLUX= ( Ellipsoid, 0.0 ) +MARKER_FAR= ( Farfield ) +MARKER_PLOTTING= ( Ellipsoid ) +MARKER_MONITORING= ( Ellipsoid ) +% +% ------------------------------ NUMERICS ----------------------------------------% +NUM_METHOD_GRAD= GREEN_GAUSS +CFL_NUMBER= 20 +CFL_ADAPT= NO +ITER= 5 +LINEAR_SOLVER= FGMRES +LINEAR_SOLVER_PREC= ILU +LINEAR_SOLVER_ERROR= 1E-6 +LINEAR_SOLVER_ITER= 10 +CONV_NUM_METHOD_FLOW= JST +MUSCL_FLOW= NO +JST_SENSOR_COEFF= ( 0.5, 0.02 ) +TIME_DISCRE_FLOW= EULER_IMPLICIT +CONV_NUM_METHOD_TURB= SCALAR_UPWIND +MUSCL_TURB= NO +TIME_DISCRE_TURB= EULER_IMPLICIT +CONV_RESIDUAL_MINVAL= -12 +CONV_FIELD= ( RMS_PRESSURE ) +% +% ------------------------------ INPUT/OUTPUT ------------------------------------% +MESH_FILENAME= spheroid_tiny.su2 +MESH_FORMAT= SU2 +SOLUTION_FILENAME= solution_flow_sa_slm.dat +RESTART_FILENAME= restart_flow.dat +OUTPUT_FILES= (RESTART) +OUTPUT_WRT_FREQ= 1000 +SCREEN_OUTPUT= (INNER_ITER, RMS_PRESSURE, RMS_VELOCITY-X, RMS_NU_TILDE, RMS_INTERMITTENCY, LIFT, DRAG) +HISTORY_OUTPUT= (ITER, RMS_RES, AERO_COEFF) diff --git a/TestCases/transition/prolate_spheroid/sst_slm_menter.cfg b/TestCases/transition/prolate_spheroid/sst_slm_menter.cfg new file mode 100644 index 000000000000..1be03155666d --- /dev/null +++ b/TestCases/transition/prolate_spheroid/sst_slm_menter.cfg @@ -0,0 +1,65 @@ +% Transition on the 6:1 prolate spheroid at 15 degrees angle of attack, one-equation (simplified) LM model +% SST (Menter et al. 2015). +% Coarse unstructured grid (100958 points), restart from a converged SST + MENTER_SLM solution +% (solution_flow_sst_slm.dat), so that the transition front is established. +% +% ------------------------------ PROBLEM DEFINITION ------------------------------% +SOLVER= INC_RANS +KIND_TURB_MODEL= SST +SST_OPTIONS= ( KATO-LAUNDER ) +KIND_TRANS_MODEL= LM +LM_OPTIONS= ( SLM, MENTER_SLM ) +FREESTREAM_TURBULENCEINTENSITY= 0.001 +FREESTREAM_TURB2LAMVISCRATIO= 5.0 +MATH_PROBLEM= DIRECT +RESTART_SOL= YES +% +% ------------------------------ FREE-STREAM -------------------------------------% +INC_DENSITY_INIT= 1.177 +INC_TEMPERATURE_INIT= 300 +INC_VELOCITY_INIT= ( 43.4667, 0.0, 11.647 ) +INC_NONDIM= INITIAL_VALUES +VISCOSITY_MODEL= CONSTANT_VISCOSITY +MU_CONSTANT= 1.853e-05 +% +% ------------------------------ REFERENCE VALUES --------------------------------% +REF_ORIGIN_MOMENT_X= 0.25 +REF_ORIGIN_MOMENT_Y= 0.00 +REF_ORIGIN_MOMENT_Z= 0.00 +REF_LENGTH= 2.4 +REF_AREA= 0 +% +% ------------------------------ BOUNDARY CONDITIONS -----------------------------% +MARKER_HEATFLUX= ( Ellipsoid, 0.0 ) +MARKER_FAR= ( Farfield ) +MARKER_PLOTTING= ( Ellipsoid ) +MARKER_MONITORING= ( Ellipsoid ) +% +% ------------------------------ NUMERICS ----------------------------------------% +NUM_METHOD_GRAD= GREEN_GAUSS +CFL_NUMBER= 20 +CFL_ADAPT= NO +ITER= 5 +LINEAR_SOLVER= FGMRES +LINEAR_SOLVER_PREC= ILU +LINEAR_SOLVER_ERROR= 1E-6 +LINEAR_SOLVER_ITER= 10 +CONV_NUM_METHOD_FLOW= JST +MUSCL_FLOW= NO +JST_SENSOR_COEFF= ( 0.5, 0.02 ) +TIME_DISCRE_FLOW= EULER_IMPLICIT +CONV_NUM_METHOD_TURB= SCALAR_UPWIND +MUSCL_TURB= NO +TIME_DISCRE_TURB= EULER_IMPLICIT +CONV_RESIDUAL_MINVAL= -12 +CONV_FIELD= ( RMS_PRESSURE ) +% +% ------------------------------ INPUT/OUTPUT ------------------------------------% +MESH_FILENAME= spheroid_tiny.su2 +MESH_FORMAT= SU2 +SOLUTION_FILENAME= solution_flow_sst_slm.dat +RESTART_FILENAME= restart_flow.dat +OUTPUT_FILES= (RESTART) +OUTPUT_WRT_FREQ= 1000 +SCREEN_OUTPUT= (INNER_ITER, RMS_PRESSURE, RMS_VELOCITY-X, RMS_TKE, RMS_DISSIPATION, RMS_INTERMITTENCY, LIFT, DRAG) +HISTORY_OUTPUT= (ITER, RMS_RES, AERO_COEFF) diff --git a/TestCases/transition/prolate_spheroid/sst_slm_menter_crossflow.cfg b/TestCases/transition/prolate_spheroid/sst_slm_menter_crossflow.cfg new file mode 100644 index 000000000000..362a7f6d5792 --- /dev/null +++ b/TestCases/transition/prolate_spheroid/sst_slm_menter_crossflow.cfg @@ -0,0 +1,66 @@ +% Transition on the 6:1 prolate spheroid at 15 degrees angle of attack, one-equation (simplified) LM model +% SST (Menter et al. 2015) with cross-flow. +% Coarse unstructured grid (100958 points), restart from a converged SST + MENTER_SLM solution +% (solution_flow_sst_slm.dat), so that the transition front is established. +% +% ------------------------------ PROBLEM DEFINITION ------------------------------% +SOLVER= INC_RANS +KIND_TURB_MODEL= SST +SST_OPTIONS= ( KATO-LAUNDER ) +KIND_TRANS_MODEL= LM +LM_OPTIONS= ( SLM, MENTER_SLM, CROSSFLOW ) +FREESTREAM_TURBULENCEINTENSITY= 0.001 +FREESTREAM_TURB2LAMVISCRATIO= 5.0 +HROUGHNESS= 3.3e-6 +MATH_PROBLEM= DIRECT +RESTART_SOL= YES +% +% ------------------------------ FREE-STREAM -------------------------------------% +INC_DENSITY_INIT= 1.177 +INC_TEMPERATURE_INIT= 300 +INC_VELOCITY_INIT= ( 43.4667, 0.0, 11.647 ) +INC_NONDIM= INITIAL_VALUES +VISCOSITY_MODEL= CONSTANT_VISCOSITY +MU_CONSTANT= 1.853e-05 +% +% ------------------------------ REFERENCE VALUES --------------------------------% +REF_ORIGIN_MOMENT_X= 0.25 +REF_ORIGIN_MOMENT_Y= 0.00 +REF_ORIGIN_MOMENT_Z= 0.00 +REF_LENGTH= 2.4 +REF_AREA= 0 +% +% ------------------------------ BOUNDARY CONDITIONS -----------------------------% +MARKER_HEATFLUX= ( Ellipsoid, 0.0 ) +MARKER_FAR= ( Farfield ) +MARKER_PLOTTING= ( Ellipsoid ) +MARKER_MONITORING= ( Ellipsoid ) +% +% ------------------------------ NUMERICS ----------------------------------------% +NUM_METHOD_GRAD= GREEN_GAUSS +CFL_NUMBER= 20 +CFL_ADAPT= NO +ITER= 5 +LINEAR_SOLVER= FGMRES +LINEAR_SOLVER_PREC= ILU +LINEAR_SOLVER_ERROR= 1E-6 +LINEAR_SOLVER_ITER= 10 +CONV_NUM_METHOD_FLOW= JST +MUSCL_FLOW= NO +JST_SENSOR_COEFF= ( 0.5, 0.02 ) +TIME_DISCRE_FLOW= EULER_IMPLICIT +CONV_NUM_METHOD_TURB= SCALAR_UPWIND +MUSCL_TURB= NO +TIME_DISCRE_TURB= EULER_IMPLICIT +CONV_RESIDUAL_MINVAL= -12 +CONV_FIELD= ( RMS_PRESSURE ) +% +% ------------------------------ INPUT/OUTPUT ------------------------------------% +MESH_FILENAME= spheroid_tiny.su2 +MESH_FORMAT= SU2 +SOLUTION_FILENAME= solution_flow_sst_slm.dat +RESTART_FILENAME= restart_flow.dat +OUTPUT_FILES= (RESTART) +OUTPUT_WRT_FREQ= 1000 +SCREEN_OUTPUT= (INNER_ITER, RMS_PRESSURE, RMS_VELOCITY-X, RMS_TKE, RMS_DISSIPATION, RMS_INTERMITTENCY, LIFT, DRAG) +HISTORY_OUTPUT= (ITER, RMS_RES, AERO_COEFF) From c5b1ea62f0ce0566d2312bf74a4d282121d8e0ce Mon Sep 17 00:00:00 2001 From: rois1995 Date: Thu, 24 Sep 2026 11:55:43 +0200 Subject: [PATCH 59/61] Run the regression tests with the feature_Trans_SLM branch of TestCases Temporary, for the prolate spheroid data of su2code/TestCases#207. To be reverted to develop before merging. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- .github/workflows/regression.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index 76eb60ebc8f8..700f878f17dc 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -233,7 +233,7 @@ jobs: uses: docker://ghcr.io/su2code/su2/test-su2:260405-0054 with: # -t -c - args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} + args: -b ${{github.ref}} -t develop -c feature_Trans_SLM -s ${{matrix.testscript}} - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2:260405-0054 with: @@ -282,7 +282,7 @@ jobs: uses: docker://ghcr.io/su2code/su2/test-su2:260405-0054 with: # -t -c - args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} -a "--tapetests" + args: -b ${{github.ref}} -t develop -c feature_Trans_SLM -s ${{matrix.testscript}} -a "--tapetests" - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2:260405-0054 with: @@ -330,7 +330,7 @@ jobs: PMIX_MCA_gds: hash with: # -t -c - args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} -a "--tsan" + args: -b ${{github.ref}} -t develop -c feature_Trans_SLM -s ${{matrix.testscript}} -a "--tsan" - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2-tsan:260405-0054 with: @@ -375,7 +375,7 @@ jobs: uses: docker://ghcr.io/su2code/su2/test-su2-asan:260405-0054 with: # -t -c - args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} -a "--asan" + args: -b ${{github.ref}} -t develop -c feature_Trans_SLM -s ${{matrix.testscript}} -a "--asan" - name: Cleanup uses: docker://ghcr.io/su2code/su2/test-su2-asan:260405-0054 with: From 5478002e76a03bfc7716b571df5313c13cd13722 Mon Sep 17 00:00:00 2001 From: rois1995 Date: Mon, 28 Sep 2026 15:59:12 +0200 Subject: [PATCH 60/61] Accept LM2015 as the old name of CROSSFLOW, remove PRODLIM, output F_onset with the cross-flow terms - LM_OPTIONS= LM2015 (the name in develop) is accepted again, as CROSSFLOW. - PRODLIM was parsed but never used: P_k^lim is part of the one-equation model of Menter et al. (2015, Eq. 25) and is always applied with it. - The F_ONSET output of the one-equation model now includes the cross-flow corrections, as the value used by the source term. - config_template.cfg documents the LM_OPTIONS of both models. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- Common/include/option_structure.hpp | 5 +---- .../numerics/turbulent/transition/trans_sources.hpp | 4 +++- config_template.cfg | 7 ++++++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp index 2d0664281b15..d737719c187e 100644 --- a/Common/include/option_structure.hpp +++ b/Common/include/option_structure.hpp @@ -1377,7 +1377,6 @@ enum class LM_OPTIONS { NONE, /*!< \brief No option / default. */ CROSSFLOW, /*!< \brief Cross-flow corrections. */ SLM, /*!< \brief Simplified version. */ - PRODLIM, /*!< \brief Add production term to Pk. */ MALAN, /*!< \brief Kind of transition correlation model (Malan). */ SULUKSNA, /*!< \brief Kind of transition correlation model (Suluksna). */ KRAUSE, /*!< \brief Kind of transition correlation model (Krause). */ @@ -1394,8 +1393,8 @@ enum class LM_OPTIONS { static const MapType LM_Options_Map = { MakePair("NONE", LM_OPTIONS::NONE) MakePair("CROSSFLOW", LM_OPTIONS::CROSSFLOW) + MakePair("LM2015", LM_OPTIONS::CROSSFLOW) // name of the option before the one-equation model was added MakePair("SLM", LM_OPTIONS::SLM) - MakePair("PRODLIM", LM_OPTIONS::PRODLIM) MakePair("MALAN", LM_OPTIONS::MALAN) MakePair("SULUKSNA", LM_OPTIONS::SULUKSNA) MakePair("KRAUSE", LM_OPTIONS::KRAUSE) @@ -1447,7 +1446,6 @@ constexpr double LM_CROSSFLOW_MIN_ROUGHNESS = 1e-8; struct LM_ParsedOptions { LM_OPTIONS version = LM_OPTIONS::NONE; /*!< \brief LM base model. */ bool SLM = false; /*!< \brief Use simplified version. */ - bool ProdLim = false; /*!< \brief Add production term to Pk. */ bool CrossFlow = false; /*!< \brief Use cross-flow corrections. */ TURB_TRANS_CORRELATION Correlation = TURB_TRANS_CORRELATION::DEFAULT; TURB_TRANS_CORRELATION_SLM Correlation_SLM = TURB_TRANS_CORRELATION_SLM::DEFAULT; @@ -1469,7 +1467,6 @@ inline LM_ParsedOptions ParseLMOptions(const LM_OPTIONS *LM_Options, unsigned sh }; LMParsedOptions.SLM = IsPresent(LM_OPTIONS::SLM); - LMParsedOptions.ProdLim = IsPresent(LM_OPTIONS::PRODLIM); LMParsedOptions.CrossFlow = IsPresent(LM_OPTIONS::CROSSFLOW); diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index 678e0802328d..b570d578042a 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -561,7 +561,6 @@ class CSourcePieceWise_TransSLM final : public CNumerics { F_onset1_Here = F_onset1; F_onset2_Here = F_onset2; F_onset3_Here = F_onset3; - F_onset_Here = F_onset; if (options.CrossFlow && TurbFamily == TURB_FAMILY::SA) { /*--- Menter and Smirnov C1-based cross-flow criterion, Lee and Baeder (2021), Eqs. 25-35. ---*/ @@ -618,6 +617,9 @@ class CSourcePieceWise_TransSLM final : public CNumerics { } + /*--- Output value, including the cross-flow corrections. ---*/ + F_onset_Here = F_onset; + /*--- Menter et al. (2015), Eq. 5, and Lee and Baeder (2021), Eq. 6. ---*/ const su2double f_turb = exp(-pow(R_t / 2, 4)); diff --git a/config_template.cfg b/config_template.cfg index 7fefa98aa6f4..b46f166372a7 100644 --- a/config_template.cfg +++ b/config_template.cfg @@ -33,7 +33,12 @@ KIND_TRANS_MODEL= NONE % Value of RMS roughness for transition model HROUGHNESS= 1.0e-6 % -% Specify versions/correlations of the LM model (LM2015, MALAN, SULUKSNA, KRAUSE, KRAUSE_HYPER, MEDIDA, MEDIDA_BAEDER, MENTER_LANGTRY) +% Specify versions/correlations of the LM model: +% CROSSFLOW: cross-flow corrections (LM2015 is accepted as its old name). +% SLM: one-equation (simplified) model of Menter et al. 2015 instead of the two-equation model. +% Correlations of the two-equation model (one of): MALAN, SULUKSNA, KRAUSE, KRAUSE_HYPER, MEDIDA, MEDIDA_BAEDER, +% MENTER_LANGTRY (default MENTER_LANGTRY with SST, MALAN with SA). +% Correlations of the one-equation model (one of): MENTER_SLM (default), CODER_SLM, MOD_EPPLER_SLM. LM_OPTIONS= NONE % % Specify subgrid scale model(NONE, IMPLICIT_LES, SMAGORINSKY, WALE, VREMAN) From 7a886944cbbc6817ccce18fc837e1e55c6dbaeca Mon Sep 17 00:00:00 2001 From: rois1995 Date: Mon, 28 Sep 2026 17:09:55 +0200 Subject: [PATCH 61/61] Fix the LM inlet values, the SA intensity limit, the AD inputs and TURB_INDEX - BC_Inlet of the transition solver scaled gamma and Re_theta_t as k and omega when an inlet profile file was used, although they are dimensionless and are not read from the file, and read a second variable that the one-equation model does not have. The nVar free-stream values are now used as they are. - With SA the turbulence intensity of the two-equation correlations is limited to 0.027 %, as with k-omega, since the correlations divide by it. - The AD preaccumulation registered two turbulence variables also for SA. - TURB_INDEX: the friction velocity is sqrt(nu |Omega|) at the wall in 2D and 3D (it used mu in 3D and the skin friction coefficient in 2D). - Debug comments replaced. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01LEL91DW5WPbPwgFtCvHga6 --- .../turbulent/transition/trans_sources.hpp | 19 +++++++++------- SU2_CFD/src/solvers/CTransLMSolver.cpp | 14 ++++-------- SU2_CFD/src/solvers/CTurbSASolver.cpp | 22 +++++-------------- 3 files changed, 21 insertions(+), 34 deletions(-) diff --git a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp index b570d578042a..336e60c273e0 100644 --- a/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp +++ b/SU2_CFD/include/numerics/turbulent/transition/trans_sources.hpp @@ -107,8 +107,10 @@ class CSourcePieceWise_TransLM final : public CNumerics { /*--- dU/dx = PrimVar_Grad[1][0] ---*/ AD::StartPreacc(); AD::SetPreaccIn(StrainMag_i); - AD::SetPreaccIn(ScalarVar_i, nVar); - AD::SetPreaccIn(ScalarVar_Grad_i, nVar, nDim); + /*--- The turbulence model has one variable (SA) or two (k-omega). ---*/ + const unsigned short nTurbVar = (TurbFamily == TURB_FAMILY::SA) ? 1 : 2; + AD::SetPreaccIn(ScalarVar_i, nTurbVar); + AD::SetPreaccIn(ScalarVar_Grad_i, nTurbVar, nDim); AD::SetPreaccIn(TransVar_i, nVar); AD::SetPreaccIn(TransVar_Grad_i, nVar, nDim); AD::SetPreaccIn(Volume); @@ -141,11 +143,12 @@ class CSourcePieceWise_TransLM final : public CNumerics { if (dist_i > 1e-10) { su2double Tu = 1.0; if (TurbFamily == TURB_FAMILY::KW) Tu = max(100.0 * sqrt(2.0 * ScalarVar_i[0] / 3.0) / Velocity_Mag, 0.027); - if (TurbFamily == TURB_FAMILY::SA) Tu = config->GetTurbulenceIntensity_FreeStream() * 100; + /*--- The same lower limit as for k-omega, the correlations divide by Tu. ---*/ + if (TurbFamily == TURB_FAMILY::SA) Tu = max(config->GetTurbulenceIntensity_FreeStream() * 100, 0.027); /*--- Corr_RetC correlation*/ const su2double Corr_Rec = TransCorrelations.ReThetaC_Correlations(Tu, TransVar_i[1]); - // AGGIUNTO PER DEBUG + // Stored for the output Corr_Rec_Here = Corr_Rec; /*--- F_length correlation*/ @@ -166,7 +169,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { if (TurbFamily == TURB_FAMILY::SA) R_t = Eddy_Viscosity_i / Laminar_Viscosity_i; const su2double Re_v = Density_i * dist_i * dist_i * StrainMag_i / Laminar_Viscosity_i; - // AGGIUNTO PER DEBUG + // Stored for the output Re_v_Here = Re_v; const su2double F_onset1 = Re_v / (2.193 * Corr_Rec); @@ -181,7 +184,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { F_onset3 = max(2.0 - pow(R_t / 2.5, 3.0), 0.0); } const su2double F_onset = max(F_onset2 - F_onset3, 0.0); - // AGGIUNTO PER DEBUG + // Stored for the output F_onset1_Here = F_onset1; F_onset2_Here = F_onset2; F_onset3_Here = F_onset3; @@ -265,7 +268,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { Retheta_old = Corr_Ret; } - // DEBUG + // Stored for the output lambda_theta_Here = lambda; duds_Here = du_ds; @@ -317,7 +320,7 @@ class CSourcePieceWise_TransLM final : public CNumerics { /*-- destruction term of Intermeittency(Gamma) --*/ const su2double Dg = c_a2 * Density_i * VorticityMag * TransVar_i[0] * f_turb * (c_e2 * TransVar_i[0] - 1.0); - // DEBUG + // Stored for the output Prod_Here = Pg; Destr_Here = Dg; diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 878a46ea3b6e..5d245e036645 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -541,16 +541,10 @@ void CTransLMSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, C for (auto iVertex = 0u; iVertex < geometry->nVertex[val_marker]; iVertex++) { const auto* V_inlet = flowSolver->GetCharacPrimVar(val_marker, iVertex); - /*--- Non-dimensionalize Inlet_TurbVars if Inlet-Files are used. ---*/ - su2double Inlet_Vars[MAXNVAR]; - Inlet_Vars[0] = Inlet_TurbVars[val_marker][iVertex][0]; - Inlet_Vars[1] = Inlet_TurbVars[val_marker][iVertex][1]; - if (config->GetInlet_Profile_From_File()) { - Inlet_Vars[0] /= pow(config->GetVelocity_Ref(), 2); - Inlet_Vars[1] *= config->GetViscosity_Ref() / (config->GetDensity_Ref() * pow(config->GetVelocity_Ref(), 2)); - } - - for (auto iVar = 0u; iVar < nVar; iVar++) ghostNodes->SetSolution(iVertex, iVar, Inlet_Vars[iVar]); + /*--- The transition variables are dimensionless and are not read from inlet profile files: the free-stream + values set in the constructor are used (nVar of them, one for the simplified model). ---*/ + for (auto iVar = 0u; iVar < nVar; iVar++) + ghostNodes->SetSolution(iVertex, iVar, Inlet_TurbVars[val_marker][iVertex][iVar]); SetGhostPrimitives(iVertex, V_inlet); diff --git a/SU2_CFD/src/solvers/CTurbSASolver.cpp b/SU2_CFD/src/solvers/CTurbSASolver.cpp index e6af4219df4d..9c96eea6b9aa 100644 --- a/SU2_CFD/src/solvers/CTurbSASolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSASolver.cpp @@ -310,22 +310,12 @@ void CTurbSASolver::Postprocessing(CGeometry *geometry, CSolver **solver_contain if (geometry->nodes->GetDomain(iPoint)) { const auto jPoint = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor(); - su2double FrictionVelocity = 0.0; - /*--- Formulation varies for 2D and 3D problems: in 3D the friction velocity is assumed to be sqrt(mu * |Omega|) - (provided by the reference paper https://doi.org/10.2514/6.1992-439), whereas in 2D we have to use the - standard definition sqrt(c_f / rho) since Omega = 0. ---*/ - if(nDim == 2){ - su2double shearStress = 0.0; - for(auto iDim = 0u; iDim < nDim; iDim++) { - shearStress += pow(solver_container[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, iDim), 2.0); - } - shearStress = sqrt(shearStress); - - FrictionVelocity = sqrt(shearStress/max(flowNodes->GetDensity(iPoint), 1e-20)); - } else { - su2double VorticityMag = max(GeometryToolbox::Norm(3, flowNodes->GetVorticity(iPoint)), 1e-12); - FrictionVelocity = sqrt(flowNodes->GetLaminarViscosity(iPoint)*VorticityMag); - } + /*--- Friction velocity u_tau = sqrt(tau_w / rho) = sqrt(nu |Omega|) at the wall, where the wall shear stress + is mu |Omega| (https://doi.org/10.2514/6.1992-439). The vorticity is also defined in 2D (z component). ---*/ + const su2double VorticityMag = max(GeometryToolbox::Norm(3, flowNodes->GetVorticity(iPoint)), 1e-12); + const su2double kinematicViscosity = + flowNodes->GetLaminarViscosity(iPoint) / max(flowNodes->GetDensity(iPoint), 1e-20); + const su2double FrictionVelocity = sqrt(kinematicViscosity * VorticityMag); const su2double wall_dist = geometry->nodes->GetWall_Distance(jPoint); const su2double Derivative = nodes->GetSolution(jPoint, 0) / wall_dist;