SST eddy viscosity and F2

\[\mathrm{arg}_2 = \max\Big( \frac{2\sqrt{k}}{\beta^* d\omega},\, \frac{500\nu}{\omega d^2 Re} \Big), \qquad F_2 = \tanh(\mathrm{arg}_2^2)\]
\[\mu_t = \frac{\rho k} {\max(\omega,\,R F_2/a_1)}\,Re\]

Here \(R\) is the rate magnitude selected by the SST production option: the strain-rate magnitude when iprod_sst == 1, otherwise the vorticity magnitude. For velocity gradient \(\nabla\mathbf{u}\), the strain invariant is \(|S|=\sqrt{2 S_{ij}S_{ij}}\), with \(S_{ij}=\tfrac12(\partial_j u_i+\partial_i u_j)\). The alternative vorticity magnitude is \(|\Omega|=|\nabla\times\mathbf{u}|\). Both are computed by separately tested pure policy functions. The option selection is also isolated: exactly iprod_sst == 1 selects strain rate; all other integer values select vorticity. The selected quantity is passed unchanged to the Bradshaw limiter. The solver applies an optional laminar-viscosity ratio cap after this expression, implemented by the shared TurbCappedEddyViscosity() policy used by both SA and SST.

Intermediate checks cover both denominator branches: the \(\omega\) limit when \(R F_2/a_1 \leq \omega\), and the strain/vorticity limit when \(R F_2/a_1 > \omega\). The curve test also checks \(F_2(0)=0\) and \(F_2\to 1\) for large arg.

References

  • Menter SST; NASA TMR SST.

  • See sa_eddy_viscosity.rst and verification_layers.rst.

Pure APIs: SstStrainRateMagnitude, SstVorticityMagnitude, SstLimitingRateMagnitude, SstF2Argument, SstF2ArgFromTerms, SstF2FromArg, SstEddyViscosity.

Intermediate verification

The production path now obtains \(\mathrm{arg}_2\) through SstF2Argument(k, omega, d, betaStar, mu, rho, Re). This evaluates both the length-scale term and the viscous term before applying their maximum. Focused tests activate each term in turn, so the complete primitive-input formula is checked rather than only the final maximum of two supplied values.

The per-cell closure is now composed by SstComputeEddyViscosity(input). Its input record names the physical state and all nine velocity-gradient components; its result record exposes \(\mathrm{arg}_2\), \(F_2\), the selected rate magnitude, the uncapped \(\mu_t\), and the final laminar-ratio-capped value. TurbSrcFlux::CalcCellVist2Equ only maps the solver cell state into this input and writes the returned viscosity. Thus unit tests exercise the same ordered closure used by the production path, including production-option selection and the shared SA/SST cap policy.

This is a complete cell closure contract, not yet a mesh-level regression: the finite-volume loop, gradient reconstruction, wall-distance field, boundary ghost-cell copy, and converged flow solution remain covered by separate integration and CFD regression layers.

Closed-form checks of \(F_2(\mathrm{arg}_2)=\tanh(\mathrm{arg}_2^2)\) live in turb_sst_eddy_viscosity_test and theory table tools/verification/data/sst_f2_arg2_theory.csv (Contract Workbench Plot).

SST F2(arg2) theory curve

The rate invariants also have a coordinate-frame contract: under an orthogonal basis change Q, the gradient transforms as G’ = Q^T G Q; both |S| and |Omega| must remain unchanged. The focused tests check this invariance on a nontrivial gradient tensor and separately verify that rigid-body rotation has zero strain but nonzero vorticity. These checks protect the tensor interpretation, not only individual component arithmetic.

Production data flow

The production update is a cell-field operation, not a call with an already-populated viscosity. UTurbSrcFlux::CalcVist initializes the unstructured-grid and turbulence-field views, refreshes mean-flow gradients, then calls CalcVist2Equ for the two-equation models. For each interior cell, CalcVist2Equ reads the nine mean-velocity gradient components, density, \(k\), \(\\omega\), laminar viscosity, and wall distance from their corresponding fields. TurbSrcFlux::CalcCellVist2Equ adds the case-level SST constants and options initialized by TurbCom::Init (\(Re\), \(\\beta^*\), \(a_1\), iprod_sst, and the maximum viscosity ratio), evaluates SstComputeEddyViscosity, and writes the result back to the cell’s eddy-viscosity field.

The previous eddy-viscosity field value is not an input to this closure. The cell update therefore no longer reads it before computing the replacement. After all interior cells are updated, SetGhostCellVist copies the adjacent interior value to boundary ghost cells, and CalcVistMax scans the resulting field. This separates three contracts that should be verified independently: per-cell closure, field traversal/write-back, and ghost-cell synchronization.

The remaining integration gap is a mesh-backed test of that complete field path. The current pure policy tests validate the numerical closure; they do not by themselves prove that gradient and primitive fields are indexed correctly for every cell or that ghost values are synchronized as intended.