Skip to content

Fix/mhd cleaning speed#1235

Open
ChrisZYJ wants to merge 9 commits intoMFlowCode:masterfrom
ChrisZYJ:fix/mhd-cleaning-speed
Open

Fix/mhd cleaning speed#1235
ChrisZYJ wants to merge 9 commits intoMFlowCode:masterfrom
ChrisZYJ:fix/mhd-cleaning-speed

Conversation

@ChrisZYJ
Copy link
Contributor

@ChrisZYJ ChrisZYJ commented Feb 22, 2026

User description

Placing my changes here as I don't have write access to #1180


CodeAnt-AI Description

Fix MHD hyperbolic cleaning wave sign and enforce correct MHD wave_speeds

What Changed

  • Hyperbolic (Dedner/GLM) cleaning now clamps Riemann-wave bounds to +/- cleaning speed so cleaning waves have the correct sign and magnitude (fixes left-state sign error).
  • Validator now rejects configurations that set wave_speeds = 2 for MHD and requires wave_speeds = 1, producing a clear validation error.
  • Golden test outputs for MHD hyper-cleaning and rotor tests regenerated to reflect the corrected cleaning behavior.

Impact

✅ Fewer MHD hyper-cleaning instabilities during runs
✅ Clearer validation errors for incorrect MHD wave_speeds
✅ Test outputs match corrected MHD cleaning behavior

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

sbryngelson and others added 3 commits February 20, 2026 22:53
…ic speed

min(c_fast%L, -hyper_cleaning_speed) forces c_fast%L negative, but
fast magnetosonic speeds should be positive. Changed to max() to
match the right-state treatment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update golden files for hyper_cleaning and mhd_rotor tests to reflect
the corrected min/max sign for the left-state fast magnetosonic speed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codeant-ai codeant-ai bot added the size:L This PR changes 100-499 lines, ignoring generated files label Feb 22, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 8 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 22, 2026

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • Validation locality / duplication
    wave_speeds is retrieved and validated in multiple places (e.g. check_riemann_solver and the new check_mhd_simulation). Having duplicated checks risks inconsistent error messages and maintenance burden — consider centralizing logic or delegating all wave_speeds validation to one check.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
toolchain/mfc/case_validator.py (2)

1036-1037: Consider wave_speeds != 1 to align with the error message and guard against future additions.

The condition wave_speeds == 2 and the message "MHD requires wave_speeds = 1" are currently consistent (valid values are only 1 or 2), but expressing the constraint as != 1 better matches the stated requirement and stays correct if new wave_speeds values are ever introduced.

♻️ Suggested change
-        self.prohibit(mhd and wave_speeds is not None and wave_speeds == 2,
+        self.prohibit(mhd and wave_speeds is not None and wave_speeds != 1,
                      "MHD requires wave_speeds = 1")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@toolchain/mfc/case_validator.py` around lines 1036 - 1037, The check in the
case validation currently prohibits only wave_speeds == 2 when MHD is enabled;
update the condition in the prohibit call (the one using self.prohibit with mhd
and wave_speeds) to reject any value other than 1 (i.e., use wave_speeds is not
None and wave_speeds != 1) so the error message "MHD requires wave_speeds = 1"
stays correct and remains future-proof; keep the same error string and the same
call site (the self.prohibit line referencing mhd and wave_speeds).

186-193: Update PHYSICS_DOCS to document the new wave_speeds = 1 MHD constraint.

The check_mhd entry's explanation does not reflect the new simulation-specific requirement, and check_mhd_simulation has no PHYSICS_DOCS entry at all. Per the contributing guidelines, physics constraints added to validator methods should be reflected in PHYSICS_DOCS so the auto-generated documentation stays accurate.

Suggested addition to PHYSICS_DOCS:

"check_mhd_simulation": {
    "title": "MHD Simulation Constraints",
    "category": "Feature Compatibility",
    "explanation": (
        "MHD simulations require riemann_solver = 1 (HLL) or 4 (HLLD). "
        "wave_speeds must be 1 (Roe averages) — wave_speeds = 2 is incompatible "
        "with the hyperbolic GLM cleaning speed treatment. "
        "HLLD is not available for RMHD. Hyperbolic cleaning requires 2D or 3D."
    ),
},

Based on learnings: "When adding a check_ method to case_validator.py, document its physics in the PHYSICS_DOCS dict with title, category, explanation, and optional math/references/exceptions."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@toolchain/mfc/case_validator.py` around lines 186 - 193, PHYSICS_DOCS is
missing documentation for the new wave_speeds constraint: update the "check_mhd"
explanation to mention the new requirement that wave_speeds = 1 for MHD and add
a new "check_mhd_simulation" entry in PHYSICS_DOCS describing riemann_solver = 1
(HLL) or 4 (HLLD), wave_speeds must be 1 (Roe averages) and that wave_speeds = 2
is incompatible with hyperbolic GLM cleaning, plus notes that HLLD is
unavailable for RMHD and hyperbolic cleaning requires 2D/3D; use the
PHYSICS_DOCS dict and reference the validator methods check_mhd and
check_mhd_simulation so the auto-generated docs reflect the new constraint.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/EC8F87D9/golden-metadata.txt`:
- Around line 1-7: The golden file was generated from a dirty workspace on
branch fix/mhd-cleaning-speed for test EC8F87D9; confirm whether the uncommitted
changes used to generate tests/golden-metadata.txt actually match the committed
fix by comparing the working tree to the commit (e.g., git status/diff against
commit 36bf82625f0ad02f42ceeb2fe0fba0eda80fab9f). If they differ, regenerate the
golden using a clean checkout of the intended commit and commit that golden (or
include the missing changes in the branch); if they match, update the metadata
to reflect a clean generation (remove “dirty” note or update the recorded Git
hash to the final commit) and leave the 1e-3 tolerance as-is since it is
intentionally loose for cross‑platform FP variability.

---

Duplicate comments:
In `@tests/B4DC99F9/golden-metadata.txt`:
- Line 7: The golden-metadata.txt for test "mhd_rotor" contains non-portable,
dirty-workspace and machine-specific info (commit shows as dirty and host
LAPTOP-OMEN); regenerate the golden metadata from a clean repo state (no
uncommitted changes) or CI runner so the commit hash is clean and
remove/normalize host-specific fields, then update the test's
golden-metadata.txt to the deterministic values (clean commit id and neutral
host/machine fields) so the test no longer depends on a local dirty workspace or
personal laptop.

---

Nitpick comments:
In `@toolchain/mfc/case_validator.py`:
- Around line 1036-1037: The check in the case validation currently prohibits
only wave_speeds == 2 when MHD is enabled; update the condition in the prohibit
call (the one using self.prohibit with mhd and wave_speeds) to reject any value
other than 1 (i.e., use wave_speeds is not None and wave_speeds != 1) so the
error message "MHD requires wave_speeds = 1" stays correct and remains
future-proof; keep the same error string and the same call site (the
self.prohibit line referencing mhd and wave_speeds).
- Around line 186-193: PHYSICS_DOCS is missing documentation for the new
wave_speeds constraint: update the "check_mhd" explanation to mention the new
requirement that wave_speeds = 1 for MHD and add a new "check_mhd_simulation"
entry in PHYSICS_DOCS describing riemann_solver = 1 (HLL) or 4 (HLLD),
wave_speeds must be 1 (Roe averages) and that wave_speeds = 2 is incompatible
with hyperbolic GLM cleaning, plus notes that HLLD is unavailable for RMHD and
hyperbolic cleaning requires 2D/3D; use the PHYSICS_DOCS dict and reference the
validator methods check_mhd and check_mhd_simulation so the auto-generated docs
reflect the new constraint.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/F057F8E6/golden-metadata.txt`:
- Line 13: The golden metadata shows "CMake v3.22.1 on LAPTOP-OMEN" (WSL2) which
may differ from CI and cause FP mismatches; re-run the test suite in the CI
environment (or reproduce the CI container/toolchain locally) to confirm the
committed goldens match CI results, and if they do not, regenerate the goldens
using the CI toolchain and update the golden files (or add CI-approved golden
artifacts) so that tests pass in CI; ensure the change references the metadata
entry "CMake v3.22.1 on LAPTOP-OMEN" when validating/regenerating.
- Line 7: The golden metadata shows the working tree was "(dirty)" for commit
b90fc2c922c770d767018bf7c7bf323c5dbe9e97 on branch fix/mhd-cleaning-speed;
inspect that commit and the working tree state by running a clean checkout of
that SHA (or checkout the branch and stash/reset local changes), then run git
status and git diff to identify any uncommitted changes; confirm any differences
are only environment/path items (e.g., local Fypp path or compiler wrapper) and
not code that affects physics/algorithms, regenerate the golden outputs from the
clean checkout and compare them to the current goldens (and update
tests/golden-metadata.txt only after proving reproducibility from the committed
tree) to ensure no unintended code changes were baked into the goldens.

@codecov
Copy link

codecov bot commented Feb 22, 2026

Codecov Report

❌ Patch coverage is 33.33333% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 44.95%. Comparing base (edff972) to head (8b37c79).

Files with missing lines Patch % Lines
src/simulation/m_riemann_solvers.fpp 33.33% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1235   +/-   ##
=======================================
  Coverage   44.94%   44.95%           
=======================================
  Files          70       70           
  Lines       20504    20504           
  Branches     1946     1946           
=======================================
+ Hits         9216     9217    +1     
  Misses      10166    10166           
+ Partials     1122     1121    -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sbryngelson
Copy link
Member

Supersedes #1180 (fixes #1201).

@codeant-ai codeant-ai bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Feb 22, 2026
@sbryngelson sbryngelson marked this pull request as draft February 26, 2026 00:12
@github-actions
Copy link

Claude Code Review

Head SHA: e553bbc

Files changed: 8

  • src/simulation/m_riemann_solvers.fpp (+6/-5) — core Riemann solver fix
  • toolchain/mfc/case_validator.py (+3/-0) — new MHD wave_speeds validation
  • tests/B4DC99F9/golden*.txt, tests/EC8F87D9/golden*.txt, tests/F057F8E6/golden*.txt — regenerated golden files

Summary

  • Moves the GLM hyper-cleaning wave speed constraint from the c_fast variables (fast magnetosonic speeds, computed per-cell) to s_L/s_R (the HLL Riemann solver wave speed estimates). The fix is physically correct: the Dedner/GLM cleaning system's eigenvalues ±c_h are lab-frame wave speeds and must bound the HLLC/HLL solver wave speeds, not the magnetosonic speed inputs.
  • The old code (min(c_fast%L, -hyper_cleaning_speed)) had a sign error: since c_fast%L > 0 always, min(c_fast%L, -hyper_cleaning_speed) always returned the (negative) cleaning speed, unconditionally clamping the left fast speed to −c_h regardless of the physical wave. This corrupted the Riemann solver inputs.
  • Adds a case validator rule blocking wave_speeds = 2 for MHD, consistent with the new Fortran logic where the new block is inside a wave_speeds == 1 branch.
  • Golden files are regenerated on a different machine (Intel → AMD), which is cosmetically noisy but expected.

Findings

1. Validator check may be under-constrainedtoolchain/mfc/case_validator.py (~line 1038)

self.prohibit(mhd and wave_speeds is not None and wave_speeds == 2,
             "MHD requires wave_speeds = 1")

The error message says "MHD requires wave_speeds = 1", implying only value 1 is valid. But the guard only prohibits value 2. If other non-1 values (e.g., 3) exist or are reachable, they would silently pass. Consider:

self.prohibit(mhd and wave_speeds is not None and wave_speeds != 1,
             "MHD requires wave_speeds = 1")

Minor consistency issue; not a correctness problem today if only values 1 and 2 are defined.

2. New hyper_cleaning block is inside the wave_speeds == 1 branchsrc/simulation/m_riemann_solvers.fpp (~line 692)

The new if (hyper_cleaning) block is nested inside the wave_speeds == 1 conditional (inferred from indentation). This is correct given the new validator rule. The old code applied the clamp unconditionally before the wave_speeds branch — that path is now removed. The net effect is consistent, but any existing cases with mhd=T and wave_speeds=2 will now get a validator error instead of a (broken) runtime clamp; this is the intended behavior.

3. Golden metadata diffs are noisytests/*/golden-metadata.txt

Metadata records machine-specific details (hostname, CPU, local paths). The actual golden.txt value changes are small and expected. No issue, but the metadata noise is a pre-existing limitation of the test infrastructure.


Overall

The core physics fix is correct and well-motivated. Moving the cleaning speed constraint from c_fast (wrong variable) to s_L/s_R (correct Riemann wave bounds) properly implements the GLM/Dedner eigenvalue requirement. The validator addition enforces the constraint at the Python layer. The one actionable item is tightening the validator condition from == 2 to != 1 to match the error message semantics.

@MFlowCode MFlowCode deleted a comment from github-actions bot Feb 26, 2026
@MFlowCode MFlowCode deleted a comment from github-actions bot Feb 26, 2026
@MFlowCode MFlowCode deleted a comment from codeant-ai bot Feb 26, 2026
@MFlowCode MFlowCode deleted a comment from codeant-ai bot Feb 26, 2026
@MFlowCode MFlowCode deleted a comment from codeant-ai bot Feb 26, 2026
@MFlowCode MFlowCode deleted a comment from codeant-ai bot Feb 26, 2026
@MFlowCode MFlowCode deleted a comment from coderabbitai bot Feb 26, 2026
@sbryngelson sbryngelson marked this pull request as ready for review March 9, 2026 13:16
Copilot AI review requested due to automatic review settings March 9, 2026 13:16
@qodo-code-review
Copy link
Contributor

Review Summary by Qodo

Fix MHD hyperbolic cleaning wave speed sign and enforce wave_speeds validation

🐞 Bug fix ✨ Enhancement

Grey Divider

Walkthroughs

Description
• Fixed MHD hyperbolic cleaning wave speed sign error in Riemann solver
  - Moved hyper-cleaning speed constraints from fast magnetosonic calculation to wave speed bounds
  - Changed left-state from min() to max() to ensure correct positive wave speeds
• Added validator to enforce wave_speeds = 1 for MHD simulations
  - Prevents incompatible wave_speeds = 2 configuration with clear error message
• Regenerated golden test files for MHD hyper-cleaning and rotor tests
  - Updated test metadata and outputs to reflect corrected cleaning behavior
Diagram
flowchart LR
  A["MHD Riemann Solver"] -->|"Remove incorrect min/max<br/>from fast magnetosonic"| B["Fast Magnetosonic Speed"]
  A -->|"Add hyper-cleaning constraints<br/>to wave speed bounds"| C["Wave Speed Bounds"]
  C -->|"s_L = min(s_L, -c_h)<br/>s_R = max(s_R, c_h)"| D["Corrected Dedner GLM Eigenvalues"]
  E["Configuration Validator"] -->|"Reject wave_speeds = 2<br/>for MHD"| F["Valid MHD Configuration"]
  D -->|"Regenerate golden files"| G["Updated Test Outputs"]
Loading

Grey Divider

File Changes

1. src/simulation/m_riemann_solvers.fpp 🐞 Bug fix +6/-5

Relocate hyper-cleaning constraints to wave speed bounds

• Removed incorrect hyper-cleaning speed constraints from fast magnetosonic speed calculation
• Relocated hyper-cleaning speed bounds to wave speed calculation section
• Applied min() to left-state and max() to right-state for Dedner GLM eigenvalues
• Added clarifying comment about (B_n, psi) subsystem eigenvalues in lab frame

src/simulation/m_riemann_solvers.fpp


2. toolchain/mfc/case_validator.py ✨ Enhancement +3/-0

Add MHD wave_speeds validation constraint

• Added validation check to prohibit wave_speeds = 2 for MHD simulations
• Enforces requirement that MHD runs must use wave_speeds = 1
• Provides clear error message for invalid configuration

toolchain/mfc/case_validator.py


3. tests/EC8F87D9/golden-metadata.txt 🧪 Tests +74/-87

Regenerate golden metadata for EC8F87D9 test

• Updated test generation timestamp and git commit hash
• Updated build environment paths and compiler information
• Reordered CMake configuration sections (pre_process, simulation, post_process, syscheck)
• Updated CPU information reflecting different test machine

tests/EC8F87D9/golden-metadata.txt


View more (5)
4. tests/F057F8E6/golden-metadata.txt 🧪 Tests +64/-69

Regenerate golden metadata for F057F8E6 test

• Updated test generation timestamp and git commit hash
• Updated build environment paths and compiler information
• Reordered CMake configuration sections
• Updated CPU information reflecting different test machine

tests/F057F8E6/golden-metadata.txt


5. tests/B4DC99F9/golden-metadata.txt 🧪 Tests +63/-68

Regenerate golden metadata for B4DC99F9 test

• Updated test generation timestamp and git commit hash
• Updated build environment paths and compiler information
• Reordered CMake configuration sections
• Updated CPU information reflecting different test machine

tests/B4DC99F9/golden-metadata.txt


6. tests/B4DC99F9/golden.txt 🧪 Tests +8/-8

Update golden output for B4DC99F9 test

• Updated golden output file to reflect corrected MHD hyperbolic cleaning behavior

tests/B4DC99F9/golden.txt


7. tests/EC8F87D9/golden.txt 🧪 Tests +7/-7

Update golden output for EC8F87D9 test

• Updated golden output file to reflect corrected MHD hyperbolic cleaning behavior

tests/EC8F87D9/golden.txt


8. tests/F057F8E6/golden.txt 🧪 Tests +7/-7

Update golden output for F057F8E6 test

• Updated golden output file to reflect corrected MHD hyperbolic cleaning behavior

tests/F057F8E6/golden.txt


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Mar 9, 2026

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Negative c_h flips bounds 🐞 Bug ✓ Correctness
Description
The new hyper_cleaning clamp in m_riemann_solvers.fpp assumes hyper_cleaning_speed is positive; if a
user supplies a negative c_h, s_L/s_R are clamped in the wrong direction and no longer bound the GLM
eigenvalues. The toolchain currently allows negative hyper_cleaning_speed because it has no range
constraint and check_mhd_simulation does not validate its sign.
Code

src/simulation/m_riemann_solvers.fpp[R692-695]

+                                if (hyper_cleaning) then
+                                    ! Dedner GLM: (B_n, psi) subsystem has eigenvalues +/- c_h in the lab frame.
+                                    s_L = min(s_L, -hyper_cleaning_speed)
+                                    s_R = max(s_R, hyper_cleaning_speed)
Evidence
The PR introduces sign-sensitive clamping of Riemann bounds using +/-hyper_cleaning_speed.
hyper_cleaning_speed is defined as a wave speed (c_h) but has no min/max constraints in the generic
parameter validation layer, and the physics validator does not prohibit negative values, so a
negative input can reach this code and invert the intended bounds.

src/simulation/m_riemann_solvers.fpp[692-696]
toolchain/mfc/params/descriptions.py[114-118]
toolchain/mfc/case_validator.py[1026-1046]
toolchain/mfc/params/definitions.py[594-633]
toolchain/mfc/params/schema.py[75-85]
toolchain/mfc/params/validate.py[69-96]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`hyper_cleaning_speed` (c_h) is used with an assumed positive sign in the new GLM wave-speed clamp (`s_L = min(s_L, -c_h)`, `s_R = max(s_R, c_h)`). Because the toolchain does not currently enforce `hyper_cleaning_speed &gt; 0`, a negative user value will silently invert the intended clamping and produce incorrect Riemann bounds.

### Issue Context
- `hyper_cleaning_speed` is described/treated as a wave speed magnitude (c_h).
- Generic parameter validation only enforces constraints declared in the registry/constraints table; `hyper_cleaning_speed` has no min/max constraint.
- Physics validation (`check_mhd_simulation`) currently validates compatibility flags (mhd, n, wave_speeds) but does not validate the sign/range of `hyper_cleaning_speed`.

### Fix Focus Areas
- Add explicit physics validation when `hyper_cleaning` is enabled:
 - toolchain/mfc/case_validator.py[1026-1047]
- Add a generic numeric constraint so negative values are rejected early:
 - toolchain/mfc/params/definitions.py[594-633]
- (Optional but recommended) Add similar positivity checks for `hyper_cleaning_tau` because it is used as a divisor in damping terms.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@github-actions
Copy link

github-actions bot commented Mar 9, 2026

Claude Code Review

Head SHA: 8b37c79

Files changed: 8

  • src/simulation/m_riemann_solvers.fpp (+6 / -5)
  • toolchain/mfc/case_validator.py (+3 / -0)
  • tests/B4DC99F9/golden.txt (+8 / -8)
  • tests/B4DC99F9/golden-metadata.txt (+63 / -68)
  • tests/EC8F87D9/golden.txt (+7 / -7)
  • tests/EC8F87D9/golden-metadata.txt (+74 / -87)
  • tests/F057F8E6/golden.txt (+7 / -7)
  • tests/F057F8E6/golden-metadata.txt (+64 / -69)

Summary

  • Core fix: Moves the Dedner/GLM hyper-cleaning wave-speed constraint from c_fast%{L,R} to s_{L,R} — physically correct, since s_L/s_R are the actual HLL signal speeds used to compute the Riemann flux, while c_fast is a non-negative magnetosonic magnitude.
  • Old code bug: c_fast%L = min(c_fast%L, -hyper_cleaning_speed) compared a positive magnitude to a negative value, so it unconditionally replaced c_fast%L with -hyper_cleaning_speed. This is wrong; the new code correctly bounds s_L ≤ -c_h and s_R ≥ +c_h.
  • Validator addition: Adds a Python-side check prohibiting wave_speeds = 2 when MHD is active.
  • Golden files: Three test suites (B4DC99F9, EC8F87D9, F057F8E6 — MHD hyper-cleaning tests) regenerated to reflect corrected numerical output. The metadata differences are environmental (different hostname/paths) and expected.

Findings

1. Incomplete validator condition — toolchain/mfc/case_validator.py (new lines ~880–886)

self.prohibit(mhd and wave_speeds is not None and wave_speeds == 2,
             "MHD requires wave_speeds = 1")

The error message says "MHD requires wave_speeds = 1", but the condition only blocks wave_speeds == 2. Any other non-default value (e.g. wave_speeds = 3) silently passes validation. The intent appears to be:

self.prohibit(mhd and wave_speeds is not None and wave_speeds != 1,
             "MHD requires wave_speeds = 1")

If only wave_speeds = 2 is the known problematic value and other values (3+) are either unsupported for MHD in general or work correctly, the condition (and the message) should be clarified. As written it is incomplete for a general "requires wave_speeds = 1" guarantee.

2. Placement of hyper-cleaning constraint relative to wave_speeds branches — src/simulation/m_riemann_solvers.fpp (~line 689)

The new if (hyper_cleaning) block is placed inside the wave_speeds == 1 signal-speed branch (the Einfeldt/Davis estimate). The removed code was in a location that applied to all wave_speeds paths. Now that the validator prohibits wave_speeds = 2 with MHD, that path is guarded. However, if a wave_speeds = 3 path exists (e.g., HLLD-type), the hyper-cleaning constraint will not be applied there, and the validator does not block that combination. This needs verification: either the constraint must be applied in all relevant wave_speeds branches, or the validator must block wave_speeds != 1 for MHD unconditionally.

3. Hyper-cleaning condition scope (minor) — m_riemann_solvers.fpp

The validator prohibits wave_speeds = 2 for all MHD, not just when hyper_cleaning = T. If the real constraint is only for hyper-cleaning runs, the validator check should also gate on hyper_cleaning:

self.prohibit(mhd and hyper_cleaning and wave_speeds is not None and wave_speeds != 1, ...)

If wave_speeds = 2 is genuinely incompatible with any MHD (not just hyper-cleaning), the current broader check is fine but should be documented.


Summary verdict

The core physics fix (moving the GLM cleaning speed bound from c_fast to s_L/s_R) is correct and necessary. The main concern before merging is tightening the validator to check wave_speeds != 1 rather than only wave_speeds == 2, and confirming whether the Riemann-solver fix also needs to apply in any wave_speeds = 3 code path.

@github-actions
Copy link

github-actions bot commented Mar 9, 2026

Claude Code Review

Head SHA: 8b37c79b6afc2d25fd3ffa52f88c98a6284ecb78

Files changed: 8

  • src/simulation/m_riemann_solvers.fpp (+6/-5)
  • toolchain/mfc/case_validator.py (+3/-0)
  • tests/B4DC99F9/golden.txt (+8/-8), golden-metadata.txt (+63/-68)
  • tests/EC8F87D9/golden.txt (+7/-7), golden-metadata.txt (+74/-87)
  • tests/F057F8E6/golden.txt (+7/-7), golden-metadata.txt (+64/-69)

Summary

  • Fixes MHD hyper-cleaning (Dedner/GLM) by clamping the HLL signal speeds s_L/s_R to ±hyper_cleaning_speed, instead of the previously incorrect clamping of the intermediate fast magnetosonic speeds c_fast%L/c_fast%R.
  • Adds a validator rule prohibiting wave_speeds = 2 for MHD runs, since the new constraint only applies inside the wave_speeds == 1 branch.
  • Regenerates golden files for three MHD hyper-cleaning/rotor tests with corrected numerical output.

Findings

[Medium — Correctness] src/simulation/m_riemann_solvers.fpp, line ~652 (removed block)

The old code incorrectly applied min(c_fast%L, -hyper_cleaning_speed). c_fast%L is a wave speed magnitude used to construct s_L as vel_L - c_fast%L. Clamping the magnitude to a negative value made no physical sense and produced a wrong left-state sign. Moving the clamp to the final signal speeds s_L/s_R (after they incorporate both velocity and wave speed) is the correct place to enforce s_L ≤ -c_h and s_R ≥ +c_h. This fix is correct.

[Low — Validator gap] toolchain/mfc/case_validator.py, new prohibition (~line 1031)

The guard wave_speeds is not None means a user who never sets wave_speeds (relying on the Fortran namelist default) will not be warned. If the Fortran default for wave_speeds is 1 this is safe, but the intent of the message—"MHD requires wave_speeds = 1"—would be better expressed as an allowlist check:

This would also catch any future unsupported values (3, 4, …) rather than only blocking 2.

[Low — Golden metadata churn] tests/*/golden-metadata.txt

The metadata files contain machine-specific paths (e.g., /home/chris/source/MFC_PR/build/venv/bin/fypp), CPU flag strings, and environment variables (CC, CXX, FC) that reflect the author's laptop rather than CI. The substantive golden.txt value changes (actual numerical output) are small and expected for a bug fix. The metadata diffs are noisy; if the project treats metadata as significant, these should be regenerated on CI hardware. This is pre-existing behavior, not introduced by this PR.


Overall

The core physics fix is correct and well-commented. The validator addition is a good guardrail. The minor validator gap (allowlist vs denylist) is worth tightening but is not blocking given that wave_speeds defaults to 1 in practice. No forbidden patterns (raw !/!, d0 literals, double-precision intrinsics) are introduced.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves stability and configuration safety for MHD runs with hyperbolic (Dedner/GLM) divergence cleaning by ensuring the Riemann fan bounds account for the cleaning wave speed and by rejecting incompatible wave_speeds settings for MHD cases.

Changes:

  • Clamp computed Riemann wave-speed bounds (s_L/s_R) to include the GLM cleaning eigenvalues ±c_h when hyper_cleaning is enabled.
  • Add a case-validator constraint requiring wave_speeds = 1 for MHD simulations (rejects wave_speeds = 2).
  • Regenerate golden test metadata records for affected test cases.

Reviewed changes

Copilot reviewed 5 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/simulation/m_riemann_solvers.fpp Adjusts wave-speed bounding to include hyperbolic cleaning waves via s_L/s_R clamping.
toolchain/mfc/case_validator.py Enforces an MHD-specific restriction on wave_speeds configuration.
tests/F057F8E6/golden-metadata.txt Regenerated test metadata to reflect updated configuration/run.
tests/EC8F87D9/golden-metadata.txt Regenerated test metadata to reflect updated configuration/run.
tests/B4DC99F9/golden-metadata.txt Regenerated test metadata to reflect updated configuration/run.


self.prohibit(mhd and riemann_solver is not None and riemann_solver not in [1, 4],
"MHD simulations require riemann_solver = 1 (HLL) or riemann_solver = 4 (HLLD)")
self.prohibit(mhd and wave_speeds is not None and wave_speeds == 2,
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MHD wave_speeds constraint is currently written as wave_speeds == 2, which implicitly relies on the global wave_speeds domain staying limited to {1,2}. For clarity and future-proofing (and to match the existing model_eqns=3 check style), consider expressing this as wave_speeds is not None and wave_speeds != 1 so any non-1 value is rejected for MHD.

Suggested change
self.prohibit(mhd and wave_speeds is not None and wave_speeds == 2,
self.prohibit(mhd and wave_speeds is not None and wave_speeds != 1,

Copilot uses AI. Check for mistakes.
Comment on lines +694 to +695
s_L = min(s_L, -hyper_cleaning_speed)
s_R = max(s_R, hyper_cleaning_speed)
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes hyper_cleaning_speed is positive (since you use both -hyper_cleaning_speed and hyper_cleaning_speed as left/right bounds). If a user provides a negative value (there’s no validation in the toolchain currently), the bounds become inverted and the Riemann fan won’t be properly enclosed. Consider clamping with abs(hyper_cleaning_speed) here and/or adding a case-validator constraint that hyper_cleaning_speed > 0 whenever hyper_cleaning=T.

Suggested change
s_L = min(s_L, -hyper_cleaning_speed)
s_R = max(s_R, hyper_cleaning_speed)
s_L = min(s_L, -abs(hyper_cleaning_speed))
s_R = max(s_R, abs(hyper_cleaning_speed))

Copilot uses AI. Check for mistakes.
Comment on lines +692 to +695
if (hyper_cleaning) then
! Dedner GLM: (B_n, psi) subsystem has eigenvalues +/- c_h in the lab frame.
s_L = min(s_L, -hyper_cleaning_speed)
s_R = max(s_R, hyper_cleaning_speed)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Negative c_h flips bounds 🐞 Bug ✓ Correctness

The new hyper_cleaning clamp in m_riemann_solvers.fpp assumes hyper_cleaning_speed is positive; if a
user supplies a negative c_h, s_L/s_R are clamped in the wrong direction and no longer bound the GLM
eigenvalues. The toolchain currently allows negative hyper_cleaning_speed because it has no range
constraint and check_mhd_simulation does not validate its sign.
Agent Prompt
### Issue description
`hyper_cleaning_speed` (c_h) is used with an assumed positive sign in the new GLM wave-speed clamp (`s_L = min(s_L, -c_h)`, `s_R = max(s_R, c_h)`). Because the toolchain does not currently enforce `hyper_cleaning_speed > 0`, a negative user value will silently invert the intended clamping and produce incorrect Riemann bounds.

### Issue Context
- `hyper_cleaning_speed` is described/treated as a wave speed magnitude (c_h).
- Generic parameter validation only enforces constraints declared in the registry/constraints table; `hyper_cleaning_speed` has no min/max constraint.
- Physics validation (`check_mhd_simulation`) currently validates compatibility flags (mhd, n, wave_speeds) but does not validate the sign/range of `hyper_cleaning_speed`.

### Fix Focus Areas
- Add explicit physics validation when `hyper_cleaning` is enabled:
  - toolchain/mfc/case_validator.py[1026-1047]
- Add a generic numeric constraint so negative values are rejected early:
  - toolchain/mfc/params/definitions.py[594-633]
- (Optional but recommended) Add similar positivity checks for `hyper_cleaning_tau` because it is used as a divisor in damping terms.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 9, 2026

📝 Walkthrough

Walkthrough

This pull request modifies MHD hyper_cleaning handling and adds validation enforcement. The Riemann solver changes relocate hyper_cleaning constraints from the fast magnetosonic speed computation to the wave-speed computation path, constraining left and right speeds when hyper_cleaning is enabled. A new validation rule is added to the case validator requiring wave_speeds equal to 1 when MHD is enabled. Additionally, multiple test metadata files are updated to reflect changes in build environment, compiler toolchain paths, Git branch references, and system architecture details from the test execution context.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: fixing MHD cleaning speed handling in the Riemann solver, which is the core technical modification in this PR.
Description check ✅ Passed The description is comprehensive and covers the key changes, fixes, and impacts. However, the required template sections (Type of change, Testing, Checklist) are not formally filled out, though the author provided a detailed CodeAnt-AI generated description instead.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2ba926bc-29d7-4305-9c11-8389468b83b5

📥 Commits

Reviewing files that changed from the base of the PR and between edff972 and 8b37c79.

📒 Files selected for processing (8)
  • src/simulation/m_riemann_solvers.fpp
  • tests/B4DC99F9/golden-metadata.txt
  • tests/B4DC99F9/golden.txt
  • tests/EC8F87D9/golden-metadata.txt
  • tests/EC8F87D9/golden.txt
  • tests/F057F8E6/golden-metadata.txt
  • tests/F057F8E6/golden.txt
  • toolchain/mfc/case_validator.py

Comment on lines +692 to +695
if (hyper_cleaning) then
! Dedner GLM: (B_n, psi) subsystem has eigenvalues +/- c_h in the lab frame.
s_L = min(s_L, -hyper_cleaning_speed)
s_R = max(s_R, hyper_cleaning_speed)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Require a positive hyper_cleaning_speed before applying this clamp.

This assumes hyper_cleaning_speed > 0. If the parameter is unset or negative, Line 694/Line 695 silently produce the wrong GLM bounds instead of preserving ±c_h. Please enforce positivity in validation and defensively normalize here as well.

Suggested hardening
-                                    s_L = min(s_L, -hyper_cleaning_speed)
-                                    s_R = max(s_R, hyper_cleaning_speed)
+                                    s_L = min(s_L, -abs(hyper_cleaning_speed))
+                                    s_R = max(s_R,  abs(hyper_cleaning_speed))

Based on learnings: Add physics validation checks in toolchain/mfc/case_validator.py via check_ methods for cross-parameter constraints beyond min/max.

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

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Development

Successfully merging this pull request may close these issues.

3 participants