SST eddy viscosity and F2
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.rstandverification_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).
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.