Skip to content

Commit 0b6e0ad

Browse files
authored
Updating the Cross-Diffusion Term Discretisation in k-w SST Model (#2533)
1 parent c0bf007 commit 0b6e0ad

File tree

23 files changed

+389
-242
lines changed

23 files changed

+389
-242
lines changed

Common/include/CConfig.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,9 @@ class CConfig {
639639
su2double Relaxation_Factor_Adjoint; /*!< \brief Relaxation coefficient for variable updates of adjoint solvers. */
640640
su2double Relaxation_Factor_CHT; /*!< \brief Relaxation coefficient for the update of conjugate heat variables. */
641641
su2double EntropyFix_Coeff; /*!< \brief Entropy fix coefficient. */
642+
su2double MaxUpdateSST; /*!< \brief Cap for the Under-Relaxation Factor for SST Turbulent Variables*/
643+
su2double MaxUpdateSA; /*!< \brief Cap for the Under-Relaxation Factor for SA Turbulent Variables*/
644+
su2double MaxUpdateFlow; /*!< \brief Cap for the Under-Relaxation Factor for Flow Density and Energy Variables*/
642645
unsigned short nLocationStations, /*!< \brief Number of section cuts to make when outputting mesh and cp . */
643646
nWingStations; /*!< \brief Number of section cuts to make when calculating internal volume. */
644647
su2double Kappa_1st_AdjFlow, /*!< \brief Lax 1st order dissipation coefficient for adjoint flow equations (coarse multigrid levels). */
@@ -4233,6 +4236,24 @@ class CConfig {
42334236
*/
42344237
su2double GetRelaxation_Factor_CHT(void) const { return Relaxation_Factor_CHT; }
42354238

4239+
/*!
4240+
* \brief Get the maximum update ratio for flow variables- density and energy.
4241+
* \return Maximum allowable update ratio for flow variables.
4242+
*/
4243+
su2double GetMaxUpdateFractionFlow(void) const { return MaxUpdateFlow; }
4244+
4245+
/*!
4246+
* \brief Get the maximum update ratio for SA variable nu_tilde.
4247+
* \return Maximum allowable update ratio for SA variables.
4248+
*/
4249+
su2double GetMaxUpdateFractionSA(void) const { return MaxUpdateSA; }
4250+
4251+
/*!
4252+
* \brief Get the maximum update ratio for SST turbulence variables TKE and Omega.
4253+
* \return Maximum allowable update ratio for SST variables.
4254+
*/
4255+
su2double GetMaxUpdateFractionSST(void) const { return MaxUpdateSST; }
4256+
42364257
/*!
42374258
* \brief Get the number of samples used in quasi-Newton methods.
42384259
*/

Common/src/CConfig.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,13 @@ void CConfig::SetConfig_Options() {
19001900
addEnumOption("DISCADJ_LIN_PREC", Kind_DiscAdj_Linear_Prec, Linear_Solver_Prec_Map, ILU);
19011901
/* DESCRIPTION: Linear solver for the discete adjoint systems */
19021902

1903+
/* DESCRIPTION: Maximum update ratio value for flow density and energy variables */
1904+
addDoubleOption("MAX_UPDATE_FLOW", MaxUpdateFlow, 0.2);
1905+
/* DESCRIPTION: Maximum update ratio value for SA turbulence variable nu_tilde */
1906+
addDoubleOption("MAX_UPDATE_SA", MaxUpdateSA, 0.99);
1907+
/* DESCRIPTION: Maximum update ratio value for SST turbulence variables TKE and Omega */
1908+
addDoubleOption("MAX_UPDATE_SST", MaxUpdateSST, 1.0);
1909+
19031910
/*!\par CONFIG_CATEGORY: Convergence\ingroup Config*/
19041911
/*--- Options related to convergence ---*/
19051912

SU2_CFD/include/numerics/turbulent/turb_diffusion.hpp

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ class CAvgGrad_TurbSST final : public CAvgGrad_Scalar<FlowIndices> {
240240
const su2double sigma_k2;
241241
const su2double sigma_om1;
242242
const su2double sigma_om2;
243+
const bool use_accurate_jacobians;
243244

244245
su2double F1_i, F1_j; /*!< \brief Menter's first blending function */
245246

@@ -270,20 +271,50 @@ class CAvgGrad_TurbSST final : public CAvgGrad_Scalar<FlowIndices> {
270271
const su2double diff_j_omega = Laminar_Viscosity_j + sigma_omega_j*Eddy_Viscosity_j;
271272

272273
const su2double diff_kine = 0.5*(diff_i_kine + diff_j_kine);
273-
const su2double diff_omega = 0.5*(diff_i_omega + diff_j_omega);
274+
const su2double diff_omega_T1 = 0.5*(diff_i_omega + diff_j_omega);
275+
276+
/*--- We aim to treat the cross-diffusion as a diffusion term rather than a source term.
277+
* Re-writing the cross-diffusion contribution as λ/w ∇w ∇k, where λ = (2 (1- F1) ρ σ_ω2)
278+
* and expanding using the product rule for divergence theorem gives: ∇(w λ/w ∇k) - w ∇(λ/w ∇k).
279+
* Discretising using FVM, gives: (λ)_ij ∇k - w_c (λ/w)_ij ∇k. where w_c is the cell centre value ---*/
280+
281+
const su2double lambda_i = 2 * (1 - F1_i) * Density_i * sigma_omega_i;
282+
const su2double lambda_j = 2 * (1 - F1_j) * Density_j * sigma_omega_j;
283+
const su2double lambda_ij = 0.5 * (lambda_i + lambda_j);
284+
const su2double w_ij = 0.5 * (ScalarVar_i[1] + ScalarVar_j[1]);
285+
286+
const su2double diff_omega_T2 = lambda_ij;
287+
288+
const su2double diff_omega_T3 = -ScalarVar_i[1] * lambda_ij/w_ij;
274289

275290
Flux[0] = diff_kine*Proj_Mean_GradScalarVar[0];
276-
Flux[1] = diff_omega*Proj_Mean_GradScalarVar[1];
291+
Flux[1] = diff_omega_T1*Proj_Mean_GradScalarVar[1] + (diff_omega_T2 + diff_omega_T3)*Proj_Mean_GradScalarVar[0];
277292

278293
/*--- For Jacobians -> Use of TSL (Thin Shear Layer) approx. to compute derivatives of the gradients ---*/
279294
if (implicit) {
280295
const su2double proj_on_rho_i = proj_vector_ij/Density_i;
281-
Jacobian_i[0][0] = -diff_kine*proj_on_rho_i; Jacobian_i[0][1] = 0.0;
282-
Jacobian_i[1][0] = 0.0; Jacobian_i[1][1] = -diff_omega*proj_on_rho_i;
283-
284296
const su2double proj_on_rho_j = proj_vector_ij/Density_j;
285-
Jacobian_j[0][0] = diff_kine*proj_on_rho_j; Jacobian_j[0][1] = 0.0;
286-
Jacobian_j[1][0] = 0.0; Jacobian_j[1][1] = diff_omega*proj_on_rho_j;
297+
Jacobian_i[0][0] = -diff_kine*proj_on_rho_i;
298+
Jacobian_i[0][1] = 0.0;
299+
Jacobian_i[1][0] = (diff_omega_T2+diff_omega_T3)*-proj_on_rho_i;
300+
Jacobian_i[1][1] = -diff_omega_T1*proj_on_rho_i;
301+
302+
Jacobian_j[0][0] = diff_kine*proj_on_rho_j;
303+
Jacobian_j[0][1] = 0.0;
304+
Jacobian_j[1][0] = (diff_omega_T2+diff_omega_T3)*proj_on_rho_j;
305+
Jacobian_j[1][1] = diff_omega_T1*proj_on_rho_j;
306+
307+
if (use_accurate_jacobians) {
308+
Jacobian_i[0][0] = -diff_kine*proj_on_rho_i;
309+
Jacobian_i[0][1] = 0.0;
310+
Jacobian_i[1][0] = (diff_omega_T2 + diff_omega_T3)*-proj_on_rho_i;
311+
Jacobian_i[1][1] = -proj_on_rho_i * diff_omega_T1 - 2*lambda_ij*ScalarVar_j[1]/pow(ScalarVar_i[1]+ScalarVar_j[1],2) * Proj_Mean_GradScalarVar[0];
312+
313+
Jacobian_j[0][0] = diff_kine*proj_on_rho_j;
314+
Jacobian_j[0][1] = 0.0;
315+
Jacobian_j[1][0] = (diff_omega_T2 + diff_omega_T3)*proj_on_rho_j;
316+
Jacobian_j[1][1] = proj_on_rho_j * diff_omega_T1 + 2*lambda_ij*ScalarVar_i[1]/pow(ScalarVar_i[1]+ScalarVar_j[1],2) * Proj_Mean_GradScalarVar[0];
317+
}
287318
}
288319
}
289320

@@ -302,7 +333,8 @@ class CAvgGrad_TurbSST final : public CAvgGrad_Scalar<FlowIndices> {
302333
sigma_k1(constants[0]),
303334
sigma_k2(constants[1]),
304335
sigma_om1(constants[2]),
305-
sigma_om2(constants[3]) {
336+
sigma_om2(constants[3]),
337+
use_accurate_jacobians(config->GetUse_Accurate_Turb_Jacobians()) {
306338
}
307339

308340
/*!

SU2_CFD/include/numerics/turbulent/turb_sources.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,6 @@ class CSourcePieceWise_TurbSST final : public CNumerics {
772772
AD::SetPreaccIn(dist_i);
773773
AD::SetPreaccIn(F1_i);
774774
AD::SetPreaccIn(F2_i);
775-
AD::SetPreaccIn(CDkw_i);
776775
AD::SetPreaccIn(PrimVar_Grad_i, nDim + idx.Velocity(), nDim);
777776
AD::SetPreaccIn(Vorticity_i, 3);
778777
AD::SetPreaccIn(V_i[idx.Density()], V_i[idx.LaminarViscosity()], V_i[idx.EddyViscosity()]);
@@ -911,9 +910,7 @@ class CSourcePieceWise_TurbSST final : public CNumerics {
911910
Residual[0] -= dk * Volume;
912911
Residual[1] -= dw * Volume;
913912

914-
/*--- Cross diffusion ---*/
915-
916-
Residual[1] += (1.0 - F1_i) * CDkw_i * Volume;
913+
/*--- Cross diffusion is included in the viscous fluxes, discretisation in turb_diffusion.hpp ---*/
917914

918915
/*--- Contribution due to 2D axisymmetric formulation ---*/
919916

SU2_CFD/include/solvers/CFVMFlowSolverBase.inl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ void CFVMFlowSolverBase<V, R>::ComputeUnderRelaxationFactor(const CConfig* confi
558558
/* Loop over the solution update given by relaxing the linear
559559
system for this nonlinear iteration. */
560560

561-
const su2double allowableRatio = 0.2;
561+
const su2double allowableRatio = config->GetMaxUpdateFractionFlow();
562562

563563
SU2_OMP_FOR_STAT(omp_chunk_size)
564564
for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) {

SU2_CFD/include/solvers/CScalarSolver.hpp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,102 @@ class CScalarSolver : public CSolver {
146146
}
147147
}
148148

149+
/*!
150+
* \brief Compute the viscous flux for the turbulence equations at a particular edge for a non-conservative discretisation.
151+
* \tparam SolverSpecificNumericsTemp - lambda-function, to implement solver specific contributions to numerics.
152+
* \note The functor has to implement (iPoint, jPoint)
153+
* \param[in] iEdge - Edge for which we want to compute the flux
154+
* \param[in] geometry - Geometrical definition of the problem.
155+
* \param[in] solver_container - Container vector with all the solutions.
156+
* \param[in] numerics - Description of the numerical method.
157+
* \param[in] config - Definition of the particular problem.
158+
*/
159+
template<typename SolverSpecificNumericsFunc>
160+
void Viscous_Residual_NonCons(const unsigned long iEdge, const CGeometry* geometry, CSolver** solver_container,
161+
CNumerics* numerics, const CConfig* config, SolverSpecificNumericsFunc&& SolverSpecificNumerics) {
162+
const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);
163+
CFlowVariable* flowNodes = solver_container[FLOW_SOL] ?
164+
su2staticcast_p<CFlowVariable*>(solver_container[FLOW_SOL]->GetNodes()) : nullptr;
165+
166+
const auto iPoint = geometry->edges->GetNode(iEdge, 0);
167+
const auto jPoint = geometry->edges->GetNode(iEdge, 1);
168+
169+
/*--- Lambda function to compute the flux ---*/
170+
auto ComputeFlux = [&](unsigned long iPoint, unsigned long jPoint, const su2double* normal) {
171+
numerics->SetCoord(geometry->nodes->GetCoord(iPoint),geometry->nodes->GetCoord(jPoint));
172+
numerics->SetNormal(normal);
173+
174+
if (flowNodes) {
175+
numerics->SetPrimitive(flowNodes->GetPrimitive(iPoint), flowNodes->GetPrimitive(jPoint));
176+
}
177+
178+
/*--- Solver specific numerics contribution. ---*/
179+
SolverSpecificNumerics(iPoint, jPoint);
180+
181+
numerics->SetScalarVar(nodes->GetSolution(iPoint), nodes->GetSolution(jPoint));
182+
numerics->SetScalarVarGradient(nodes->GetGradient(iPoint), nodes->GetGradient(jPoint));
183+
184+
return numerics->ComputeResidual(config);
185+
};
186+
187+
/*--- Compute fluxes and jacobians i->j ---*/
188+
const su2double* normal = geometry->edges->GetNormal(iEdge);
189+
auto residual_ij = ComputeFlux(iPoint, jPoint, normal);
190+
191+
JacobianScalarType *Block_ii = nullptr, *Block_ij = nullptr, *Block_ji = nullptr, *Block_jj = nullptr;
192+
if (implicit) {
193+
Jacobian.GetBlocks(iEdge, iPoint, jPoint, Block_ii, Block_ij, Block_ji, Block_jj);
194+
}
195+
if (ReducerStrategy) {
196+
EdgeFluxes.SubtractBlock(iEdge, residual_ij);
197+
EdgeFluxesDiff.SetBlock(iEdge, residual_ij);
198+
if (implicit) {
199+
/*--- For the reducer strategy the Jacobians are averaged for simplicity. ---*/
200+
for (int iVar=0; iVar<nVar; iVar++)
201+
for (int jVar=0; jVar<nVar; jVar++) {
202+
Block_ij[iVar*nVar + jVar] -= 0.5 * SU2_TYPE::GetValue(residual_ij.jacobian_j[iVar][jVar]);
203+
Block_ji[iVar*nVar + jVar] += 0.5 * SU2_TYPE::GetValue(residual_ij.jacobian_i[iVar][jVar]);
204+
}
205+
}
206+
} else {
207+
LinSysRes.SubtractBlock(iPoint, residual_ij);
208+
if (implicit) {
209+
for (int iVar=0; iVar<nVar; iVar++)
210+
for (int jVar=0; jVar<nVar; jVar++) {
211+
Block_ii[iVar*nVar + jVar] -= SU2_TYPE::GetValue(residual_ij.jacobian_i[iVar][jVar]);
212+
Block_ij[iVar*nVar + jVar] -= SU2_TYPE::GetValue(residual_ij.jacobian_j[iVar][jVar]);
213+
}
214+
}
215+
}
216+
217+
/*--- Compute fluxes and jacobians j->i ---*/
218+
su2double flipped_normal[MAXNDIM];
219+
for (auto iDim = 0u; iDim < nDim; iDim++) flipped_normal[iDim] = -normal[iDim];
220+
221+
auto residual_ji = ComputeFlux(jPoint, iPoint, flipped_normal);
222+
if (ReducerStrategy) {
223+
EdgeFluxesDiff.AddBlock(iEdge, residual_ji);
224+
if (implicit) {
225+
for (int iVar=0; iVar<nVar; iVar++)
226+
for (int jVar=0; jVar<nVar; jVar++) {
227+
Block_ij[iVar*nVar + jVar] += 0.5 * SU2_TYPE::GetValue(residual_ji.jacobian_i[iVar][jVar]);
228+
Block_ji[iVar*nVar + jVar] -= 0.5 * SU2_TYPE::GetValue(residual_ji.jacobian_j[iVar][jVar]);
229+
}
230+
}
231+
} else {
232+
LinSysRes.SubtractBlock(jPoint, residual_ji);
233+
if (implicit) {
234+
/*--- The order of arguments were flipped in the evaluation of residual_ji, the Jacobian
235+
* associated with point i is stored in jacobian_j and point j in jacobian_i. ---*/
236+
for (int iVar=0; iVar<nVar; iVar++)
237+
for (int jVar=0; jVar<nVar; jVar++) {
238+
Block_ji[iVar*nVar + jVar] -= SU2_TYPE::GetValue(residual_ji.jacobian_j[iVar][jVar]);
239+
Block_jj[iVar*nVar + jVar] -= SU2_TYPE::GetValue(residual_ji.jacobian_i[iVar][jVar]);
240+
}
241+
}
242+
}
243+
}
244+
149245
/*!
150246
* \brief Generic implementation of the fluid interface boundary condition for scalar solvers.
151247
* \tparam SolverSpecificNumericsFunc - lambda that implements solver specific contributions to viscous numerics.

SU2_CFD/include/solvers/CTurbSSTSolver.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ class CTurbSSTSolver final : public CTurbSolver {
5353
CSolver **solver_container,
5454
const CConfig *config,
5555
unsigned short val_marker);
56+
57+
/*!
58+
* \brief Compute a suitable under-relaxation parameter to limit the change in the solution variables over
59+
* a nonlinear iteration for stability.
60+
* \param[in] config - Definition of the particular problem.
61+
*/
62+
void ComputeUnderRelaxationFactor(const CConfig *config);
63+
5664
public:
5765
/*!
5866
* \brief Constructor.

SU2_CFD/include/solvers/CTurbSolver.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,11 @@ class CTurbSolver : public CScalarSolver<CTurbVariable> {
147147
* \returns The number of extra variables.
148148
*/
149149
unsigned long RegisterSolutionExtra(bool input, const CConfig* config) final;
150+
151+
/*!
152+
* \brief Compute a suitable under-relaxation parameter to limit the change in the solution variables over
153+
* a nonlinear iteration for stability.
154+
* \param[in] allowableRatio - Maximum percentage update in variable per iteration.
155+
*/
156+
void ComputeUnderRelaxationFactorHelper(su2double allowableRatio);
150157
};

SU2_CFD/include/variables/CTurbVariable.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ class CTurbVariable : public CScalarVariable {
100100
*/
101101
inline void SetIntermittency(unsigned long iPoint, su2double val_intermittency) final { intermittency(iPoint) = val_intermittency; }
102102

103+
/*!
104+
* \brief Set the Diffusion Coefficients of TKE and omega equations.
105+
* \param[in] iPoint - Point index.
106+
* \param[in] val_DC_kw - diffusion coefficient value
107+
*/
108+
103109
/*!
104110
* \brief Register eddy viscosity (muT) as Input or Output of an AD recording.
105111
* \param[in] input - Boolean whether In- or Output should be registered.

0 commit comments

Comments
 (0)