Skip to content

Fix biparabolic regression - #2865

Open
Syphonicc wants to merge 3 commits into
su2code:developfrom
Syphonicc:fix-biparabolic-regression
Open

Syphonicc wants to merge 3 commits into
su2code:developfrom
Syphonicc:fix-biparabolic-regression

Conversation

@Syphonicc

Copy link
Copy Markdown

Proposed Changes

Updates the biparabolic supersonic Euler case (TestCases/euler/biparabolic) so it runs on current develop, and adds it to serial_regression.py.

Config changes:

  • EXT_ITER → ITER (deprecated option prevented the config from parsing at all)
  • Fixed CFL_ADAPT_PARAM: factor-down and factor-up were swapped (1.5, 0.5 → 0.5, 1.5). SU2 rejects factor-down ≥ 1.0, but this was never caught because CFL_ADAPT was set to NO.
  • Switched CONV_NUM_METHOD_FLOW from JST to ROE with MUSCL_FLOW and the Venkatakrishnan limiter. The case diverged with JST at CFL 25, 5 and 1, so it wasn't a timestep issue — the central scheme wasn't robust enough for the shocks at Mach 1.7.
  • MGLEVEL 3 → 0
  • Removed unused adjoint, design-variable, and equivalent-area settings

Note on scope: the original config was set up for an adjoint-based sonic-boom (equivalent-area) design study rather than a direct solve, and the MARKER_NEARFIELD / EQUIV_AREA setup appears to be what was causing the divergence. I reduced it to a minimal direct Euler run so it works as a regression case happy to restore the design-related settings if you'd prefer the case keep that capability.

Regression entry uses test_iter = 25, with values verified reproducible across repeated runs. Residuals stall around -4 rather than reaching the -6 criterion at longer horizons let me know if you'd prefer different settings.

Tested locally with a serial build (MPI disabled). I'm new to SU2, and worked through this with AI assistance.

Related Work

Resolves #2864.

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.

- Replace deprecated EXT_ITER with ITER
- Fix swapped CFL_ADAPT_PARAM values (factor-down must be < 1.0)
- Switch from JST to ROE with MUSCL and Venkatakrishnan limiter for
  better robustness at Mach 1.7
- Remove unused adjoint, design-variable, and equivalent-area settings
- Disable multigrid and add case to serial_regression.py
@Syphonicc
Syphonicc force-pushed the fix-biparabolic-regression branch from 6d513e2 to a60faaa Compare August 9, 2026 04:03
@bigfooted

Copy link
Copy Markdown
Contributor

Thanks! Please keep the adjoint stuff so the file can then be re-used for an adjoint setup as well. With these settings, does it converge completely, can you post a plot of the residuals as function of iterations here?
The residual values reported by github are slightly different from the ones you computed yourself, you can just copy-paste the github values and update them.

…te test_vals

- Restore adjoint, DV, and adjoint I/O settings (inert in DIRECT runs)
- Keep EQUIV_AREA and MARKER_NEARFIELD commented out: enabling them
  gives 760 non-physical points and rms[Rho] +3.4 instead of -3.9
- Update test_vals to CI-computed values
@Syphonicc

Copy link
Copy Markdown
Author

Thanks! Please keep the adjoint stuff so the file can then be re-used for an adjoint setup as well. With these settings, does it converge completely, can you post a plot of the residuals as function of iterations here? The residual values reported by github are slightly different from the ones you computed yourself, you can just copy-paste the github values and update them.

Adjoint settings restored put back the adjoint, DV, and adjoint I/O options. They're inert in a DIRECT run and the regression values are unchanged with them present.

EQUIV_AREA / MARKER_NEARFIELD I left commented out, with a note in the file explaining why. I tested this specifically: with everything else identical, re-enabling them gives Warning: there are 760 non-physical points in the solution and rms[Rho] sits at +3.43 at iteration 500, versus −3.7 without them. Happy to re-enable if you'd rather the direct case carry them, but it doesn't produce a usable solution as-is.

Convergence no, it doesn't converge completely. Residuals drop quickly for ~150 iterations, then plateau around −4 and stay there. I ran it out to 3000 iterations to check: rms[Rho] was −4.05 at 2000 and −3.93 at 3000, so it's a genuine stall rather than slow progress. Plot below.
biparabolic_residuals

@bigfooted

Copy link
Copy Markdown
Contributor

That convergence doesn't look good. Also, the equivalent area and nearfield conditions are important parts of this setup so I think it is best to keep those, since we already have a bunch of testcases that test the standard euler flow with a farfield BC. That probably means tinkering a bit with the settings to find out how to make it converge well.

@Syphonicc

Copy link
Copy Markdown
Author

That convergence doesn't look good. Also, the equivalent area and nearfield conditions are important parts of this setup so I think it is best to keep those, since we already have a bunch of testcases that test the standard euler flow with a farfield BC. That probably means tinkering a bit with the settings to find out how to make it converge well.

I dug into the nearfield setup and I think the problem is deeper than config settings. Findings, all tested with everything else held constant:

MARKER_NEARFIELD alone (with EQUIV_AREA= NO) gives 760 non-physical points and rms[Rho] = 3.4319. Enabling EQUIV_AREA= YES on top gives bit-identical results, so the EA post-processing isn't involved it's the nearfield BC itself.
Without the nearfield markers, rms[Rho] reaches −3.9 with no warnings.
I also corrected EA_INT_LIMIT from (-100, 100, 2.0) to (1.562, 4.562, 2.0) to match the actual nearfield extent in the mesh no effect on the solution.
In the mesh, upper_nearfield and lower_nearfield are coincident duplicate nodes, both on the line y = −2 with bit-identical x-coordinates (e.g. node 8 and node 56581 are both at x = 1.562149913, y = −2.0). So this is an internal interface construction rather than two surfaces above and below the airfoil.
The one working EA case in the suite, ea_naca64206, is 3D with a circumferential nearfield surface, which matches what config_template.cfg describes as required.

So this looks like the 2D coincident-node nearfield path being broken rather than a settings issue probably needs a look at the nearfield BC implementation. Happy to keep going if you can point me at the relevant code, or to close this if you'd rather handle it separately.

@kvnloo

kvnloo commented Sep 25, 2026

Copy link
Copy Markdown

Thanks @Syphonicc for separating the nearfield behavior from the equivalent-area post-processing. Following your request for code pointers, there is a dispatch detail that may help narrow the next check.

At the inspected revision 9cd08dcdf7fc8aab2660497ac02c3f67285efbbe:

  • Common/src/CConfig.cpp:6133–6142 assigns nearfield markers to NEARFIELD_BOUNDARY, separately from FLUID_INTERFACE.
  • SU2_CFD/src/integration/CIntegration.cpp:83–143 calls BC_Fluid_Interface, but its following boundary-condition switch has no NEARFIELD_BOUNDARY case.
  • SU2_CFD/include/solvers/CFVMFlowSolverBase.inl:1334–1387 only processes FLUID_INTERFACE markers and reads their sliding/donor states.

Could the next check be where the coincident nearfield nodes are intended to receive their paired-state/flux contribution in the direct solver? I may be missing another path, so this is a source-trace lead rather than a confirmed explanation of the divergence.

I would not simply broaden the interface guard: that path expects donor-state setup. Keeping the original nearfield/equivalent-area purpose seems important before choosing either a solver fix or a configuration migration.

AI disclosure: ChatGPT generated this comment and traced the source. The fork-only Actions run below collected complete matching source files at the pinned revision and verified their Git blob hashes. No CFD solve, mesh validation, or independent reproduction of the reported residuals was performed.

https://github.com/kvnloo/space-ros/actions/runs/36094835607

@Syphonicc

Copy link
Copy Markdown
Author

Thanks @kvnloo, that dispatch trace is right, and it has a definite answer: there is no path, and that is deliberate.

NEARFIELD_BOUNDARY was removed as dead code in 02c1e4d ("delete dead-code for 'nearfield' and 'interface' boundaries", @pcarruscag, Aug 2021), which took out the nearfield handling in CEulerSolver, CAdjEulerSolver, CTurbSASolver, CSolver and the geometry classes. So the reason you could not find where the coincident nodes get a paired state is that nothing has done that for four years.

Checking on current develop, every surviving use of NEARFIELD_BOUNDARY is either an exclusion or output:

  • exclusions (!= NEARFIELD_BOUNDARY) in the Green-Gauss gradients, the viscous force and y+ loops, CScalarSolver, CMultiGridIntegration, CHeatSolver, CIncEulerSolver and the geometry classes;
  • the marker assignment itself, Common/src/CConfig.cpp:6203;
  • mesh deformation, CLinearElasticity.cpp:1367;
  • the equivalent-area post-processing, CFlowCompOutput.cpp:489 -> SetNearfieldInverseDesign, gated on EQUIV_AREA.

grep -rn "case NEARFIELD_BOUNDARY" over Common and SU2_CFD returns nothing, so the marker reaches no boundary-condition routine in any dispatch. Faces on a MARKER_NEARFIELD boundary therefore get no flux contribution at all, which lines up with the divergence in this case: the config was written for the old adjoint equivalent-area workflow, and the part of that workflow that made the marker mean something in the direct solve is gone. The remaining EQUIV_AREA output path still exists, but it post-processes a solution rather than closing the boundary.

That makes me more comfortable with the scope choice in this PR: dropping the nearfield/equivalent-area settings from the regression case is not working around a solver bug, it is removing settings that no longer have an implementation behind them. Restoring the capability would be a separate piece of work, and not one I would attach to a regression-test fix.

@bigfooted @pcarruscag - separate question, and happy to open an issue for it rather than clutter this PR: should MARKER_NEARFIELD and EQUIV_AREA now warn or error in CConfig? At the moment a config can set a nearfield marker, parse cleanly, and run with those faces silently unclosed, which is how this test case came to be broken in the first place.

@kvnloo

kvnloo commented Sep 25, 2026

Copy link
Copy Markdown

Appreciate you taking a look, thanks 🙏

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.

3 participants