Skip to content

Commit 5b56b32

Browse files
authored
Merge pull request #2508 from Bot-Enigma-0/feature_sa_diffusion
Updating SA-Diffusion term Discretisation
2 parents 814f21a + 344e939 commit 5b56b32

File tree

17 files changed

+245
-110
lines changed

17 files changed

+245
-110
lines changed

.github/workflows/regression.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ jobs:
211211
uses: docker://ghcr.io/su2code/su2/test-su2:240320-1536
212212
with:
213213
# -t <Tutorials-branch> -c <Testcases-branch>
214-
args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}}
214+
args: -b ${{github.ref}} -t develop -c feature_updated_SA_diffusion -s ${{matrix.testscript}}
215215
- name: Cleanup
216216
uses: docker://ghcr.io/su2code/su2/test-su2:240320-1536
217217
with:
@@ -306,7 +306,7 @@ jobs:
306306
uses: docker://ghcr.io/su2code/su2/test-su2-tsan:240320-1536
307307
with:
308308
# -t <Tutorials-branch> -c <Testcases-branch>
309-
args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} -a "--tsan"
309+
args: -b ${{github.ref}} -t develop -c feature_updated_SA_diffusion -s ${{matrix.testscript}} -a "--tsan"
310310
- name: Cleanup
311311
uses: docker://ghcr.io/su2code/su2/test-su2-tsan:240320-1536
312312
with:
@@ -351,7 +351,7 @@ jobs:
351351
uses: docker://ghcr.io/su2code/su2/test-su2-asan:240320-1536
352352
with:
353353
# -t <Tutorials-branch> -c <Testcases-branch>
354-
args: -b ${{github.ref}} -t develop -c develop -s ${{matrix.testscript}} -a "--asan"
354+
args: -b ${{github.ref}} -t develop -c feature_updated_SA_diffusion -s ${{matrix.testscript}} -a "--asan"
355355
- name: Cleanup
356356
uses: docker://ghcr.io/su2code/su2/test-su2-asan:240320-1536
357357
with:

Common/include/CConfig.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ class CConfig {
591591
MUSCL_AdjTurb; /*!< \brief MUSCL scheme for the adj turbulence equations.*/
592592
bool MUSCL_Species; /*!< \brief MUSCL scheme for the species equations.*/
593593
bool Use_Accurate_Jacobians; /*!< \brief Use numerically computed Jacobians for AUSM+up(2) and SLAU(2). */
594+
bool Use_Accurate_Turb_Jacobians; /*!< \brief Use numerically computed Jacobians for standard SA turbulence model. */
594595
bool EulerPersson; /*!< \brief Boolean to determine whether this is an Euler simulation with Persson shock capturing. */
595596
bool FSI_Problem = false,/*!< \brief Boolean to determine whether the simulation is FSI or not. */
596597
Multizone_Problem; /*!< \brief Boolean to determine whether we are solving a multizone problem. */
@@ -4516,6 +4517,12 @@ class CConfig {
45164517
*/
45174518
bool GetUse_Accurate_Jacobians(void) const { return Use_Accurate_Jacobians; }
45184519

4520+
/*!
4521+
* \brief Get whether to "Use Accurate Jacobians" for Standard SA turbulence model.
4522+
* \return yes/no.
4523+
*/
4524+
bool GetUse_Accurate_Turb_Jacobians(void) const { return Use_Accurate_Turb_Jacobians; }
4525+
45194526
/*!
45204527
* \brief Get the kind of integration scheme (explicit or implicit)
45214528
* for the flow equations.

Common/src/CConfig.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,6 +2006,8 @@ void CConfig::SetConfig_Options() {
20062006
/*!\brief CONV_NUM_METHOD_TURB
20072007
* \n DESCRIPTION: Convective numerical method \ingroup Config*/
20082008
addConvectOption("CONV_NUM_METHOD_TURB", Kind_ConvNumScheme_Turb, Kind_Centered_Turb, Kind_Upwind_Turb);
2009+
/*!\brief USE_ACCURATE_TURB_JACOBIANS \n DESCRIPTION: Use numerically computed Jacobians for Standard SA model \ingroup Config*/
2010+
addBoolOption("USE_ACCURATE_TURB_JACOBIANS", Use_Accurate_Turb_Jacobians, false);
20092011

20102012
/*!\brief MUSCL_ADJTURB \n DESCRIPTION: Check if the MUSCL scheme should be used \ingroup Config*/
20112013
addBoolOption("MUSCL_ADJTURB", MUSCL_AdjTurb, false);

SU2_CFD/include/numerics/turbulent/turb_diffusion.hpp

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class CAvgGrad_TurbSA final : public CAvgGrad_Scalar<FlowIndices> {
5252
using Base::Jacobian_j;
5353

5454
const su2double sigma = 2.0/3.0;
55+
const su2double cb2 = 0.622;
5556

5657
/*!
5758
* \brief Adds any extra variables to AD
@@ -67,17 +68,41 @@ class CAvgGrad_TurbSA final : public CAvgGrad_Scalar<FlowIndices> {
6768

6869
/*--- Compute mean effective viscosity ---*/
6970

70-
const su2double nu_i = Laminar_Viscosity_i/Density_i;
71-
const su2double nu_j = Laminar_Viscosity_j/Density_j;
72-
const su2double nu_e = 0.5*(nu_i+nu_j+ScalarVar_i[0]+ScalarVar_j[0]);
71+
/* First Term */
72+
su2double nu_i = Laminar_Viscosity_i/Density_i;
73+
su2double nu_j = Laminar_Viscosity_j/Density_j;
74+
su2double nu_e = 0.5*(nu_i + nu_j + (1+cb2)*(ScalarVar_i[0] + ScalarVar_j[0]));
75+
su2double term_1 = nu_e;
76+
77+
/* Second Term */
78+
su2double nu_tilde_i = ScalarVar_i[0];
79+
su2double term_2 = cb2 * nu_tilde_i;
80+
81+
Flux[0] = (term_1 - term_2)*Proj_Mean_GradScalarVar[0]/sigma;
82+
su2double dTerm1_dnut_i = (1+cb2)*0.5;
83+
su2double dTerm1_dnut_j = (1+cb2)*0.5;
84+
85+
su2double dTerm2_dnut_i = cb2;
86+
su2double dTerm2_dnut_j = 0.0;
87+
88+
su2double dDC_dnut_i = dTerm1_dnut_i - dTerm2_dnut_i;
89+
su2double dDC_dnut_j = dTerm1_dnut_j - dTerm2_dnut_j;
7390

74-
Flux[0] = nu_e*Proj_Mean_GradScalarVar[0]/sigma;
91+
su2double dGrad_dnut_i = -proj_vector_ij;
92+
su2double dGrad_dnut_j = proj_vector_ij;
7593

7694
/*--- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/
95+
su2double diffusion_coefficient = term_1 - term_2;
96+
bool UseExactJacobians = config->GetUse_Accurate_Turb_Jacobians();
7797

7898
if (implicit) {
79-
Jacobian_i[0][0] = (0.5*Proj_Mean_GradScalarVar[0]-nu_e*proj_vector_ij)/sigma;
80-
Jacobian_j[0][0] = (0.5*Proj_Mean_GradScalarVar[0]+nu_e*proj_vector_ij)/sigma;
99+
if (UseExactJacobians) {
100+
Jacobian_i[0][0] = (dDC_dnut_i*Proj_Mean_GradScalarVar[0] + dGrad_dnut_i*diffusion_coefficient)/sigma; //exact
101+
Jacobian_j[0][0] = (dDC_dnut_j*Proj_Mean_GradScalarVar[0] + dGrad_dnut_j*diffusion_coefficient)/sigma; //exact
102+
} else {
103+
Jacobian_i[0][0] = diffusion_coefficient*-proj_vector_ij/sigma; //frozen diffusion coefficients
104+
Jacobian_j[0][0] = diffusion_coefficient* proj_vector_ij/sigma; //frozen diffusion coefficients
105+
}
81106
}
82107
}
83108

@@ -118,6 +143,7 @@ class CAvgGrad_TurbSA_Neg final : public CAvgGrad_Scalar<FlowIndices> {
118143

119144
const su2double sigma = 2.0/3.0;
120145
const su2double cn1 = 16.0;
146+
const su2double cb2 = 0.622;
121147

122148
/*!
123149
* \brief Adds any extra variables to AD
@@ -137,27 +163,41 @@ class CAvgGrad_TurbSA_Neg final : public CAvgGrad_Scalar<FlowIndices> {
137163
const su2double nu_j = Laminar_Viscosity_j/Density_j;
138164

139165
const su2double nu_ij = 0.5*(nu_i+nu_j);
140-
const su2double nu_tilde_ij = 0.5*(ScalarVar_i[0] + ScalarVar_j[0]);
166+
const su2double nu_tilde_i = ScalarVar_i[0];
167+
const su2double nu_tilde_j = ScalarVar_j[0];
168+
const su2double nu_tilde_ij = 0.5*(nu_tilde_i + nu_tilde_j);
169+
170+
/* Following Diskin's implementation from 10.2514/1.J064629, they propose a new fn function
171+
to be evaluated at the cell to maintain positivity in the diffusion coefficient, which is
172+
used in both terms. The new fn term averaged across the face reverts to the original fn
173+
function. */
174+
175+
/*--- Second Term (LHS) ---*/
176+
su2double zeta_i = ((1 + cb2)*nu_tilde_ij - cb2*nu_tilde_i)/nu_ij;
177+
su2double fn_i;
178+
if (zeta_i >= 0.0) {
179+
fn_i = 1.0;
180+
} else {
181+
fn_i = (cn1 + pow(zeta_i,3.0))/(cn1 - pow(zeta_i,3.0));
182+
}
141183

142-
su2double nu_e;
184+
su2double term_1 = (nu_ij + (1 + cb2)*nu_tilde_ij*fn_i);
185+
su2double term_2 = cb2*nu_tilde_i*fn_i;
186+
Flux[0] = (term_1 - term_2)*Proj_Mean_GradScalarVar[0]/sigma;
143187

144-
if (nu_tilde_ij > 0.0) {
145-
nu_e = nu_ij + nu_tilde_ij;
146-
}
147-
else {
148-
const su2double Xi = nu_tilde_ij/nu_ij;
149-
const su2double fn = (cn1 + Xi*Xi*Xi)/(cn1 - Xi*Xi*Xi);
150-
nu_e = nu_ij + fn*nu_tilde_ij;
151-
}
188+
/*--- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients
189+
* Exact Jacobians were tested on multiple cases but resulted in divergence of all
190+
* simulations, hence only frozen diffusion coefficient (approximate) Jacobians are used. ---*/
152191

153-
Flux[0] = nu_e*Proj_Mean_GradScalarVar[0]/sigma;
192+
su2double diffusion_coefficient = (term_1 - term_2);
154193

155-
/*--- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/
194+
su2double dGrad_dnut_i = -proj_vector_ij;
195+
su2double dGrad_dnut_j = proj_vector_ij;
156196

157-
if (implicit) {
158-
Jacobian_i[0][0] = (0.5*Proj_Mean_GradScalarVar[0]-nu_e*proj_vector_ij)/sigma;
159-
Jacobian_j[0][0] = (0.5*Proj_Mean_GradScalarVar[0]+nu_e*proj_vector_ij)/sigma;
160-
}
197+
if (implicit) {
198+
Jacobian_i[0][0] = diffusion_coefficient * dGrad_dnut_i/sigma; //frozen diffusion
199+
Jacobian_j[0][0] = diffusion_coefficient * dGrad_dnut_j/sigma; //frozen diffusion
200+
}
161201
}
162202

163203
public:

SU2_CFD/include/numerics/turbulent/turb_sources.hpp

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,11 @@ class CSourceBase_TurbSA : public CNumerics {
243243
var.interDestrFactor = 1.0;
244244
}
245245

246-
/*--- Compute production, destruction and cross production and jacobian ---*/
247-
su2double Production = 0.0, Destruction = 0.0, CrossProduction = 0.0;
248-
SourceTerms::get(ScalarVar_i[0], var, Production, Destruction, CrossProduction, Jacobian_i[0]);
246+
/*--- Compute production, destruction and jacobian ---*/
247+
su2double Production = 0.0, Destruction = 0.0;
248+
SourceTerms::get(ScalarVar_i[0], var, Production, Destruction, Jacobian_i[0]);
249249

250-
Residual = (Production - Destruction + CrossProduction) * Volume;
250+
Residual = (Production - Destruction) * Volume;
251251

252252
if (axisymmetric) ResidualAxisymmetricDiffusion(var.sigma);
253253

@@ -423,24 +423,22 @@ struct Edw {
423423
};
424424

425425
/*!
426-
* \brief SA source terms classes: production, destruction and cross-productions term and their derivative.
426+
* \brief SA source terms classes: production and destruction term and their derivative.
427427
* \ingroup SourceDiscr
428428
* \param[in] nue: SA variable.
429429
* \param[in] var: Common SA variables struct.
430430
* \param[out] production: Production term.
431431
* \param[out] destruction: Destruction term.
432-
* \param[out] cross_production: CrossProduction term.
433432
* \param[out] jacobian: Derivative of the combined source term wrt nue.
434433
*/
435434
struct SourceTerms {
436435

437436
/*! \brief Baseline (Original SA model). */
438437
struct Bsl {
439438
static void get(const su2double& nue, const CSAVariables& var, su2double& production, su2double& destruction,
440-
su2double& cross_production, su2double& jacobian) {
439+
su2double& jacobian) {
441440
ComputeProduction(nue, var, production, jacobian);
442441
ComputeDestruction(nue, var, destruction, jacobian);
443-
ComputeCrossProduction(nue, var, cross_production, jacobian);
444442
}
445443

446444
static void ComputeProduction(const su2double& nue, const CSAVariables& var, su2double& production,
@@ -458,23 +456,17 @@ struct Bsl {
458456
jacobian -= var.interDestrFactor * ((var.cw1 * var.d_fw - cb1_k2 * var.d_ft2) * pow(nue, 2) + factor * 2 * nue) / var.dist_i_2;
459457
}
460458

461-
static void ComputeCrossProduction(const su2double& nue, const CSAVariables& var, su2double& cross_production,
462-
su2double&) {
463-
cross_production = var.cb2_sigma * var.norm2_Grad;
464-
/*--- No contribution to the jacobian. ---*/
465-
}
466459
};
467460

468461
/*! \brief Negative. */
469462
struct Neg {
470463
static void get(const su2double& nue, const CSAVariables& var, su2double& production, su2double& destruction,
471-
su2double& cross_production, su2double& jacobian) {
464+
su2double& jacobian) {
472465
if (nue > 0.0) {
473-
Bsl::get(nue, var, production, destruction, cross_production, jacobian);
466+
Bsl::get(nue, var, production, destruction, jacobian);
474467
} else {
475468
ComputeProduction(nue, var, production, jacobian);
476469
ComputeDestruction(nue, var, destruction, jacobian);
477-
ComputeCrossProduction(nue, var, cross_production, jacobian);
478470
}
479471
}
480472

@@ -493,10 +485,6 @@ struct Neg {
493485
jacobian -= 2 * dD_dnu * var.interDestrFactor;
494486
}
495487

496-
static void ComputeCrossProduction(const su2double& nue, const CSAVariables& var, su2double& cross_production,
497-
su2double& jacobian) {
498-
Bsl::ComputeCrossProduction(nue, var, cross_production, jacobian);
499-
}
500488
};
501489
};
502490

SU2_CFD/include/solvers/CScalarSolver.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class CScalarSolver : public CSolver {
7777

7878
/*--- Edge fluxes for reducer strategy (see the notes in CEulerSolver.hpp). ---*/
7979
CSysVector<su2double> EdgeFluxes; /*!< \brief Flux across each edge. */
80+
CSysVector<su2double> EdgeFluxes_Diff; /*!< \brief Flux difference across ij and ji for non-conservative discretisation. */
8081

8182
/*!
8283
* \brief The highest level in the variable hierarchy this solver can safely use.

SU2_CFD/include/solvers/CScalarSolver.inl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,12 @@ void CScalarSolver<VariableType>::SumEdgeFluxes(CGeometry* geometry) {
348348
for (auto iEdge : geometry->nodes->GetEdges(iPoint)) {
349349
if (iPoint == geometry->edges->GetNode(iEdge, 0))
350350
LinSysRes.AddBlock(iPoint, EdgeFluxes.GetBlock(iEdge));
351-
else
351+
else {
352352
LinSysRes.SubtractBlock(iPoint, EdgeFluxes.GetBlock(iEdge));
353+
if (EdgeFluxes_Diff.GetLocSize() > 0) {
354+
LinSysRes.SubtractBlock(iPoint, EdgeFluxes_Diff.GetBlock(iEdge));
355+
}
356+
}
353357
}
354358
}
355359
END_SU2_OMP_FOR

SU2_CFD/src/solvers/CTurbSASolver.cpp

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,11 @@ CTurbSASolver::CTurbSASolver(CGeometry *geometry, CConfig *config, unsigned shor
7373
LinSysRes.Initialize(nPoint, nPointDomain, nVar, 0.0);
7474
System.SetxIsZero(true);
7575

76-
if (ReducerStrategy)
76+
if (ReducerStrategy) {
7777
EdgeFluxes.Initialize(geometry->GetnEdge(), geometry->GetnEdge(), nVar, nullptr);
78-
78+
EdgeFluxes_Diff.Initialize(geometry->GetnEdge(), geometry->GetnEdge(), nVar, nullptr);
79+
}
80+
7981
if (config->GetExtraOutput()) {
8082
if (nDim == 2) { nOutputVariables = 13; }
8183
else if (nDim == 3) { nOutputVariables = 19; }
@@ -301,8 +303,95 @@ void CTurbSASolver::Viscous_Residual(const unsigned long iEdge, const CGeometry*
301303
};
302304

303305
/*--- Now instantiate the generic implementation with the functor above. ---*/
306+
const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);
307+
CFlowVariable* flowNodes = solver_container[FLOW_SOL] ?
308+
su2staticcast_p<CFlowVariable*>(solver_container[FLOW_SOL]->GetNodes()) : nullptr;
309+
310+
/*--- Points in edge ---*/
311+
auto iPoint = geometry->edges->GetNode(iEdge, 0);
312+
auto jPoint = geometry->edges->GetNode(iEdge, 1);
313+
314+
/*--- Helper function to compute the flux ---*/
315+
auto ComputeFlux = [&](unsigned long point_i, unsigned long point_j, const su2double* normal) {
316+
numerics->SetCoord(geometry->nodes->GetCoord(point_i),geometry->nodes->GetCoord(point_j));
317+
numerics->SetNormal(normal);
318+
319+
if (flowNodes) {
320+
numerics->SetPrimitive(flowNodes->GetPrimitive(point_i), flowNodes->GetPrimitive(point_j));
321+
}
322+
323+
numerics->SetScalarVar(nodes->GetSolution(point_i), nodes->GetSolution(point_j));
324+
numerics->SetScalarVarGradient(nodes->GetGradient(point_i), nodes->GetGradient(point_j));
325+
326+
return numerics->ComputeResidual(config);
327+
};
328+
329+
SolverSpecificNumerics(iPoint, jPoint);
330+
331+
/*--- Compute fluxes and jacobians i->j ---*/
332+
const su2double* normal = geometry->edges->GetNormal(iEdge);
333+
auto residual_ij = ComputeFlux(iPoint, jPoint, normal);
334+
if (ReducerStrategy) {
335+
EdgeFluxes.SubtractBlock(iEdge, residual_ij);
336+
EdgeFluxes_Diff.SetBlock(iEdge, residual_ij);
337+
if (implicit) {
338+
auto* Block_ij = Jacobian.GetBlock(iPoint, jPoint);
339+
auto* Block_ji = Jacobian.GetBlock(jPoint, iPoint);
340+
341+
for (int iVar=0; iVar<nVar; iVar++)
342+
for (int jVar=0; jVar<nVar; jVar++) {
343+
Block_ij[iVar*nVar + jVar] -= 0.5*SU2_TYPE::GetValue(residual_ij.jacobian_j[iVar][jVar]);
344+
Block_ji[iVar*nVar + jVar] += 0.5*SU2_TYPE::GetValue(residual_ij.jacobian_i[iVar][jVar]);
345+
}
346+
}
347+
}
348+
else {
349+
LinSysRes.SubtractBlock(iPoint, residual_ij);
350+
if (implicit) {
351+
auto* Block_ii = Jacobian.GetBlock(iPoint, iPoint);
352+
auto* Block_ij = Jacobian.GetBlock(iPoint, jPoint);
353+
354+
for (int iVar=0; iVar<nVar; iVar++)
355+
for (int jVar=0; jVar<nVar; jVar++) {
356+
Block_ii[iVar*nVar + jVar] -= SU2_TYPE::GetValue(residual_ij.jacobian_i[iVar][jVar]);
357+
Block_ij[iVar*nVar + jVar] -= SU2_TYPE::GetValue(residual_ij.jacobian_j[iVar][jVar]);
358+
}
359+
}
360+
}
304361

305-
Viscous_Residual_impl(SolverSpecificNumerics, iEdge, geometry, solver_container, numerics, config);
362+
/*--- Compute fluxes and jacobians j->i ---*/
363+
su2double flipped_normal[MAXNDIM];
364+
for (int iDim=0; iDim<nDim; iDim++)
365+
flipped_normal[iDim] = -normal[iDim];
366+
367+
auto residual_ji = ComputeFlux(jPoint, iPoint, flipped_normal);
368+
if (ReducerStrategy) {
369+
EdgeFluxes_Diff.AddBlock(iEdge, residual_ji);
370+
if (implicit) {
371+
auto* Block_ij = Jacobian.GetBlock(iPoint, jPoint);
372+
auto* Block_ji = Jacobian.GetBlock(jPoint, iPoint);
373+
374+
for (int iVar=0; iVar<nVar; iVar++)
375+
for (int jVar=0; jVar<nVar; jVar++) {
376+
Block_ij[iVar*nVar + jVar] += 0.5*SU2_TYPE::GetValue(residual_ji.jacobian_i[iVar][jVar]);
377+
Block_ji[iVar*nVar + jVar] -= 0.5*SU2_TYPE::GetValue(residual_ji.jacobian_j[iVar][jVar]);
378+
}
379+
}
380+
}
381+
else {
382+
LinSysRes.SubtractBlock(jPoint, residual_ji);
383+
if (implicit) {
384+
auto* Block_ji = Jacobian.GetBlock(jPoint, iPoint);
385+
auto* Block_jj = Jacobian.GetBlock(jPoint, jPoint);
386+
387+
//the order of arguments were flipped in the evaluation of residual_ji, the jacobian associated with point i is stored in jacobian_j and point j in jacobian_i
388+
for (int iVar=0; iVar<nVar; iVar++)
389+
for (int jVar=0; jVar<nVar; jVar++) {
390+
Block_ji[iVar*nVar + jVar] -= SU2_TYPE::GetValue(residual_ji.jacobian_j[iVar][jVar]);
391+
Block_jj[iVar*nVar + jVar] -= SU2_TYPE::GetValue(residual_ji.jacobian_i[iVar][jVar]);
392+
}
393+
}
394+
}
306395
}
307396

308397
void CTurbSASolver::Source_Residual(CGeometry *geometry, CSolver **solver_container,

0 commit comments

Comments
 (0)