Skip to content

Fix overwritten axisymmetric Jacobian in the SST source - #2986

Open
Syphonicc wants to merge 3 commits into
su2code:developfrom
Syphonicc:fix-sst-axisym-jacobian
Open

Syphonicc wants to merge 3 commits into
su2code:developfrom
Syphonicc:fix-sst-axisym-jacobian

Conversation

@Syphonicc

@Syphonicc Syphonicc commented Oct 16, 2026 •

Copy link
Copy Markdown

Title: Fix overwritten axisymmetric Jacobian in the SST source

Proposed Changes

In CSourcePieceWise_TurbSST::ComputeResidual, ResidualAxisymmetricConvectionDiffusion subtracts its
contribution from the diagonal of Jacobian_i, but the "Implicit part" right after it assigns
Jacobian_i[i][j] = ..., so that contribution was always discarded.

This PR:

  • calls the axisymmetric function after the implicit block, so its Jacobian contribution is kept;
  • uses the derivative w.r.t. the conservative variables (rho k, rho w), yinv * Volume * v (the previous
    dead code had yinv * Volume * rho * v);
  • keeps only the part that increases diagonal dominance, max(v, 0). With both signs of v, the term is
    destabilizing for flow towards the axis: on air_nozzle_restart it stalls at rms[Rho] ~ -5.6, instead of
    reaching -12 in 591 iterations.

Residuals are unchanged; only the convergence path differs, so the air_nozzle regression values are
updated. Results on air_nozzle_restart, a pipe with radial injection from a central rod, and an impinging
round jet show no change in convergence (see the discussion below).

Related Work

#2948 edits the same implicit block of the SST source.

PR Checklist

  • I am submitting my contribution to the develop branch.
  • My contribution generates no new compiler warnings (try with --warnlevel=3 when using meson).
  • My contribution is commented and consistent with SU2 style (https://su2code.github.io/docs_v7/Style-Guide/).
  • I used the pre-commit hook to prevent dirty commits and used pre-commit run --all to format old commits.
  • I have added a test case that demonstrates my contribution, if necessary.
  • I have updated appropriate documentation (Tutorials, Docs Page, config_template.cpp), if necessary.

@bigfooted

Copy link
Copy Markdown
Contributor

Since it does not harm the current case, and it is expected to help in certain other cases, I think the better approach is to keep the correct term with max(v,0).
An example testcase where this Jacobian would help is a pipe flow with a central rod that injects flow radially through a permeable (or perforated) wall. This is actually a pretty common setup. Do you have setups where there is a dominant radial velocity present close to the axisymmetry?

@bigfooted bigfooted self-assigned this Oct 17, 2026
@Syphonicc Syphonicc changed the title Remove dead axisymmetric Jacobian terms from the SST source Fix overwritten axisymmetric Jacobian in the SST source Oct 18, 2026
@Syphonicc

Copy link
Copy Markdown
Author

Thanks, makes sense. I've switched to keeping the exact derivative w.r.t. (rho k, rho w), yinv * Volume * max(v, 0), with the axisymmetric call moved after the implicit block so it is not overwritten. The air_nozzle regression values are updated (serial and MPI; I'll take the hybrid ones from CI since I don't have an OpenMP build).

I didn't have a case with dominant radial velocity near the axis, so I set up two (incompressible SST, 4000 iterations, fixed CFL, before = develop, after = this PR):

Pipe with a central rod (r0 = 5 mm, R = 50 mm) injecting radially at 5 m/s through a permeable section. Iterations to rms[P] = -11:

CFL develop this PR
20 not reached (-9.91) not reached (-9.91)
100 930 930
500 208 211
1000 165 165

Round jet impinging on a plate (H/D = 2, Re = 23000). rms[P] / rms[k] after 4000 iterations:

CFL develop this PR
20 -5.35 / -3.37 -5.35 / -3.37
100 -9.44 / -7.52 -9.44 / -7.52
500 -8.15 / -7.34 -8.15 / -7.33
1000 -7.20 / -6.90 -7.22 / -6.90

So no harm, but also no measurable benefit in these two. I think the reason is that, since the axisymmetric volume is the planar cell area, the term relative to the convective Jacobian is about dy/y. Away from the axis (rod surface, first cell 1e-5 m at r = 5 mm) that's ~0.002. Next to the axis it tends to Volume * dv/dr, which is small compared to the beta* omega Volume dissipation entry. Happy to add one of these as a regression case if it's useful.

@bigfooted

Copy link
Copy Markdown
Contributor

Thanks for the deep-dive. the current regressions touch the code so that's sufficient. If you can check that the regression tests are giving reasonable deviations, you can update the changed values.

@Syphonicc

Copy link
Copy Markdown
Author

Thanks! I went through all the failing regressions and updated the values. Max absolute change per test (log10 residuals, or the listed quantity):

Suite Test Max change Columns changed
serial turb_naca0012_sst, pywrapper_turb_naca0012_sst 1.7e-4 rms residuals only
serial turb_naca0012_sst_sust 6.0e-5 rms residuals only
serial jones_turbocharger_restart 1.0e-4 rms residuals only
parallel turb_naca0012_sst, pywrapper_turb_naca0012_sst 4.4e-5 rms residuals only
parallel jones_turbocharger_restart 4.4e-4 rms residuals only
hybrid turb_naca0012_sst 6.6e-4 rms residuals only
hybrid turb_naca0012_sst_sust 1.9e-4 rms residuals only
hybrid jones_turbocharger_restart 8.0e-4 rms residuals only
hybrid axi_rans_air_nozzle_restart 4.3e-3 mostly rms[k], rms[w]
parallel AD discadj_axisymmetric_rans 1.3e-3 adjoint turbulence residuals
vandv flatplate_sst1994m 2.1e-4 rms residuals only
vandv bump_sst1994m 5.3e-4 rms residuals only
vandv sandiajet_sst 7.5e-4 rms residuals only
tutorials transitional_flatplate_tutorial_T3Am 2.8e-5 rms residuals only

Forces, heat fluxes and the other integrated quantities are unchanged in all of them.

The axisymmetric cases (bold) are the ones where the Jacobian actually changes. The hybrid nozzle change (4.3e-3) is similar to the serial one I measured locally (4.7e-3).

The non-axisymmetric SST cases don't execute any changed code. Locally, develop and this PR are bit-identical on turb_naca0012_sst, both with -O3 and with -Dcpu-arch=skylake like CI. So I think these are round-off differences from how CI's compiler optimizes the inlined ComputeResidual after the call was moved. The deviations are at the 1e-4 level, residuals only.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants