@@ -52,6 +52,9 @@ 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 ;
56+
57+ const bool use_accurate_jacobians;
5558
5659 /* !
5760 * \brief Adds any extra variables to AD
@@ -67,17 +70,39 @@ class CAvgGrad_TurbSA final : public CAvgGrad_Scalar<FlowIndices> {
6770
6871 /* --- Compute mean effective viscosity ---*/
6972
73+ /* --- First Term. Normal diffusion, and conservative part of the quadratic diffusion.
74+ * ||grad nu_t||^2 = div(nu_t grad nu_t) - nu_t div grad nu_t ---*/
7075 const su2double nu_i = Laminar_Viscosity_i/Density_i;
7176 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 ]);
77+ const su2double nu_e = 0.5 * (nu_i + nu_j + (1 + cb2) * (ScalarVar_i[0 ] + ScalarVar_j[0 ]));
78+ const su2double term_1 = nu_e;
7379
74- Flux[0 ] = nu_e*Proj_Mean_GradScalarVar[0 ]/sigma;
80+ /* Second Term (quadratic diffusion, non conservative). */
81+ const su2double nu_tilde_i = ScalarVar_i[0 ];
82+ const su2double term_2 = cb2 * nu_tilde_i;
7583
76- /* --- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/
84+ const su2double diffusion_coefficient = term_1 - term_2;
85+ Flux[0 ] = diffusion_coefficient * Proj_Mean_GradScalarVar[0 ] / sigma;
7786
7887 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;
88+ /* --- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/
89+ Jacobian_i[0 ][0 ] = -diffusion_coefficient * proj_vector_ij / sigma;
90+ Jacobian_j[0 ][0 ] = diffusion_coefficient * proj_vector_ij / sigma;
91+
92+ if (use_accurate_jacobians) {
93+ /* --- The diffusion coefficient is also a function of nu_t. ---*/
94+ const su2double dTerm1_dnut_i = (1 + cb2) * 0.5 ;
95+ const su2double dTerm1_dnut_j = (1 + cb2) * 0.5 ;
96+
97+ const su2double dTerm2_dnut_i = cb2;
98+ const su2double dTerm2_dnut_j = 0.0 ;
99+
100+ const su2double dDC_dnut_i = dTerm1_dnut_i - dTerm2_dnut_i;
101+ const su2double dDC_dnut_j = dTerm1_dnut_j - dTerm2_dnut_j;
102+
103+ Jacobian_i[0 ][0 ] += dDC_dnut_i * Proj_Mean_GradScalarVar[0 ] / sigma;
104+ Jacobian_j[0 ][0 ] += dDC_dnut_j * Proj_Mean_GradScalarVar[0 ] / sigma;
105+ }
81106 }
82107 }
83108
@@ -91,7 +116,8 @@ class CAvgGrad_TurbSA final : public CAvgGrad_Scalar<FlowIndices> {
91116 */
92117 CAvgGrad_TurbSA (unsigned short val_nDim, unsigned short val_nVar,
93118 bool correct_grad, const CConfig* config)
94- : CAvgGrad_Scalar<FlowIndices>(val_nDim, val_nVar, correct_grad, config) {}
119+ : CAvgGrad_Scalar<FlowIndices>(val_nDim, val_nVar, correct_grad, config),
120+ use_accurate_jacobians (config->GetUse_Accurate_Turb_Jacobians ()) {}
95121};
96122
97123/* !
@@ -118,6 +144,7 @@ class CAvgGrad_TurbSA_Neg final : public CAvgGrad_Scalar<FlowIndices> {
118144
119145 const su2double sigma = 2.0 /3.0 ;
120146 const su2double cn1 = 16.0 ;
147+ const su2double cb2 = 0.622 ;
121148
122149 /* !
123150 * \brief Adds any extra variables to AD
@@ -136,27 +163,39 @@ class CAvgGrad_TurbSA_Neg final : public CAvgGrad_Scalar<FlowIndices> {
136163 const su2double nu_i = Laminar_Viscosity_i/Density_i;
137164 const su2double nu_j = Laminar_Viscosity_j/Density_j;
138165
139- const su2double nu_ij = 0.5 *(nu_i+nu_j);
140- const su2double nu_tilde_ij = 0.5 *(ScalarVar_i[0 ] + ScalarVar_j[0 ]);
141-
142- su2double nu_e;
143-
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;
166+ const su2double nu_ij = 0.5 * (nu_i + nu_j);
167+ const su2double nu_tilde_i = ScalarVar_i[0 ];
168+ const su2double nu_tilde_j = ScalarVar_j[0 ];
169+ const su2double nu_tilde_ij = 0.5 * (nu_tilde_i + nu_tilde_j);
170+
171+ /* --- Following Diskin's implementation from 10.2514/1.J064629, they propose a new fn function
172+ * to be evaluated at the cell to maintain positivity in the diffusion coefficient, which is
173+ * used in both terms. The new fn term averaged across the face reverts to the original fn
174+ * function. ---*/
175+
176+ /* --- Second Term (LHS) ---*/
177+ const su2double zeta_i = ((1 + cb2) * nu_tilde_ij - cb2 * nu_tilde_i) / nu_ij;
178+ su2double fn_i = 1.0 ;
179+ if (zeta_i < 0.0 ) {
180+ fn_i = (cn1 + pow (zeta_i,3 )) / (cn1 - pow (zeta_i,3 ));
151181 }
152182
153- Flux[0 ] = nu_e*Proj_Mean_GradScalarVar[0 ]/sigma;
183+ const su2double term_1 = (nu_ij + (1 + cb2) * nu_tilde_ij * fn_i);
184+ const su2double term_2 = cb2 * nu_tilde_i * fn_i;
185+ Flux[0 ] = (term_1 - term_2) * Proj_Mean_GradScalarVar[0 ] / sigma;
154186
155- /* --- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/
187+ /* --- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients
188+ * Exact Jacobians were tested on multiple cases but resulted in divergence of all
189+ * simulations, hence only frozen diffusion coefficient (approximate) Jacobians are used. ---*/
156190
157191 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;
192+ const su2double diffusion_coefficient = (term_1 - term_2);
193+
194+ const su2double dGrad_dnut_i = -proj_vector_ij;
195+ const su2double dGrad_dnut_j = proj_vector_ij;
196+
197+ Jacobian_i[0 ][0 ] = diffusion_coefficient * dGrad_dnut_i / sigma;
198+ Jacobian_j[0 ][0 ] = diffusion_coefficient * dGrad_dnut_j / sigma;
160199 }
161200 }
162201
0 commit comments