Skip to content

Comments

Add directional, MPI, restart, and kernel regression tests#1213

Draft
sbryngelson wants to merge 7 commits intoMFlowCode:masterfrom
sbryngelson:better-tests
Draft

Add directional, MPI, restart, and kernel regression tests#1213
sbryngelson wants to merge 7 commits intoMFlowCode:masterfrom
sbryngelson:better-tests

Conversation

@sbryngelson
Copy link
Member

@sbryngelson sbryngelson commented Feb 21, 2026

User description

Summary

  • Direction symmetry tests: 3D shock tube rotated to x and y directions (default tests only exercise z). Catches direction-specific bugs in WENO reconstruction, Riemann solvers, and gradient calculations.
  • MPI consistency tests: ppn=2 for bubbles, viscous flows, and hypoelasticity. Catches broadcast/reduction bugs in physics modules that weren't previously tested with multiple MPI ranks.
  • Restart roundtrip tests: 1D and 3D tests that run straight, then restart from the midpoint and compare outputs. Verifies restart I/O fidelity and catches drift introduced by save/load cycles.
  • Kernel golden-value tests: Polydisperse bubbles (nb=3, poly_sigma=0.3) exercising bubble array indexing with multiple sizes—a code path not previously covered by the test suite.

Implementation Details

  • case.py: Added restart_check flag to TestCase and TestCaseBuilder, plus run_restart() method that does a two-phase execution (run to midpoint, delete D/, restart from midpoint)
  • cases.py: Four new test functions called after existing test generators, before sanity checks
  • test.py: After golden comparison succeeds, restart-flagged cases run the roundtrip check and compare against the straight-run pack

Test plan

  • Verify all new test cases generate unique UUIDs (sanity check 2 in list_cases())
  • Run ./mfc.sh test --generate to generate golden files for new cases
  • Run ./mfc.sh test to verify all new cases pass
  • Run MPI tests with --mpi flag for the 3 ppn=2 consistency tests
  • Verify restart roundtrip tests complete both phases without mismatch

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Opt-in restart verification: two-phase restart workflow to generate, prune, restart and validate checkpoint/restart fidelity without changing default runs.
    • Exposed restart-check option on test cases to enable the above verification.
  • Tests

    • Added four test suites: direction symmetry, MPI consistency, restart roundtrip, and kernel golden-value scenarios.
    • Integrated restart roundtrip checks into per-case validation when enabled.
  • Data

    • Added new golden/reference data files used by the tests.

CodeAnt-AI Description

Add direction-symmetry, MPI, restart roundtrip, and grid-stretching kernel tests

What Changed

  • Added 3D direction-symmetry tests that run the shock in X and Y as well as Z to exercise direction-specific reconstruction, Riemann, and gradient code paths.
  • Added MPI-consistency tests that run selected 3D cases with 2 MPI ranks to catch broadcast/reduction and decomposition-related failures in bubble, viscous, and hypoelastic physics.
  • Added restart roundtrip tests (1D and 3D): each test runs to a midpoint, restarts from that checkpoint, and compares the restarted output against the straight run to detect any drift or I/O fidelity issues.
  • Added a focused 3D kernel golden test for cosh-based grid stretching that ensures non-uniform stretching in all directions is covered and prevents uninitialized-cell / ICFL failures.
  • Test framework: TestCase and test runner now support an opt-in restart_check that performs the two-phase run/restart and compares packed outputs; new golden output files included for these cases.

Impact

✅ Fewer direction-specific reconstruction/gradient failures
✅ Fewer MPI broadcast/reduction regressions during multi-rank runs
✅ Clearer detection of restart I/O drift and restart regressions

💡 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.

Copilot AI review requested due to automatic review settings February 21, 2026 04:29
@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 21, 2026

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 21, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds optional per-case restart verification via a new restart_check flag, implements TestCase.run_restart for a two-phase run/restart workflow, threads the flag through builders and define helpers, and adds four new test-suite functions plus new golden data files.

Changes

Cohort / File(s) Summary
Restart infrastructure
toolchain/mfc/test/case.py
Add restart_check: bool to TestCase and TestCaseBuilder; update constructors, to_case(), and define_case_d to propagate the flag; add TestCase.run_restart(targets, gpus) implementing run-to-midpoint, prune, restart, and continue.
Post-run verification
toolchain/mfc/test/test.py
When case.restart_check is true, invoke run_restart (PRE_PROCESS → SIMULATION), capture restart stdout, re-pack restarted outputs, scan for NaNs, and compare restart pack to original using existing tolerances; preserves timeout handling.
Test suites
toolchain/mfc/test/cases.py
Add four new public test-suite functions: direction_symmetry_tests(), mpi_consistency_tests(), restart_roundtrip_tests(), and kernel_golden_tests(); each registers multiple cases (diff shows duplicated insertions).
Golden / test data
tests/1A379909/golden.txt
Add multiple new D/cons.* and D/prim.* golden data entries with large numeric arrays used as test fixtures.

Sequence Diagram(s)

sequenceDiagram
    participant Harness as "Test Harness"
    participant Case as "TestCase"
    participant Sim as "Simulation (PRE_PROCESS → SIMULATION)"
    participant FS as "Filesystem / Packer"
    participant Compare as "Comparator"

    rect rgba(200,200,255,0.5)
    Harness->>Case: construct with restart_check=True
    end

    rect rgba(200,255,200,0.5)
    Harness->>Sim: run case to midpoint
    Sim-->>FS: write restart checkpoint files
    FS-->>Harness: checkpoint available
    end

    rect rgba(255,200,200,0.5)
    Harness->>FS: prune non-essential outputs
    Harness->>Sim: restart from checkpoint and continue
    Sim-->>FS: write final outputs
    end

    rect rgba(200,255,255,0.5)
    FS->>Compare: pack restarted outputs
    FS->>Compare: pack original outputs
    Compare-->>Harness: run comparison (tolerance, NaN checks)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

Review effort 3/5

Poem

🐰 I hopped to midpoint, left a note so neat,
I restarted my run with a rhythmic beat,
I pruned and packed, then checked with care,
Symmetry, MPI, and golden kernels there,
A rabbit's roundtrip — precise and sweet. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the four main test families being added: directional, MPI, restart, and kernel regression tests, matching the changeset's core objective.
Description check ✅ Passed The description is comprehensive and well-structured, covering summary, implementation details, and test plan. It includes clear motivation (catching specific bug types), implementation approach across three files, and verification steps. Minor gaps exist in issue linking and type-of-change checkbox completion, but these are non-critical.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@codeant-ai codeant-ai bot added the size:L This PR changes 100-499 lines, ignoring generated files label Feb 21, 2026
@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 21, 2026

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • Restart boundary
    The restart roundtrip computes the midpoint using integer division of t_step_stop and proceeds even when t_step_stop is very small (e.g. 0 or 1). This can produce mid-step == 0 or zero-length phase runs and unexpected t_step_save values. The logic should validate and/or guard against too-small t_step_stop and ensure non-zero positive save/start steps.

  • Timeout handling
    The restart roundtrip path checks the per-test timeout flag before launching the restart run but does not check it immediately after the restart run completes. A long or hung restart run could exceed the intended timeout without being detected; additionally the code never attempts to interrupt or fail fast while a long restart is running.

  • File-copy robustness
    copy_input_lagrange uses shutil.copyfile without checking that the source exists and contains a small variable name typo (fite_path_dest). This can raise unexpected exceptions or hide the real problem when example files are missing; the destination variable name is also confusing/typo-prone.

  • Restart fidelity handling
    New tests set restart_check=True in define_case_d. Ensure the TestCase/TestCaseBuilder and the test runner correctly implement the two-phase run-and-restart comparison (including cleanup of previous D/ directories, deterministic save/load ordering, and tolerance handling). Confirm the added restart tests include sufficient trace information for diagnosing restart mismatches.

  • API compatibility
    define_case_d and TestCaseBuilder now accept a restart_check flag and propagate it to TestCase, but callers elsewhere in the codebase may not pass this flag. Verify other call sites (test generators) are updated to set restart_check where intended, otherwise behavior will be the default (False) and some tests won't run restart roundtrips.

@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 21, 2026

CodeAnt AI finished reviewing your PR.

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.

1 issue found across 3 files

Confidence score: 4/5

  • The only noted issue is a missing post-run timeout check in toolchain/mfc/test/test.py, which could allow a hung restart test to pass the 1-hour guard and mask test failures.
  • Overall risk seems limited to test reliability rather than production behavior, so this looks safe to merge with a small caveat.
  • Pay close attention to toolchain/mfc/test/test.py - add a timeout check after run_restart to catch long/hung runs.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="toolchain/mfc/test/test.py">

<violation number="1" location="toolchain/mfc/test/test.py:395">
P2: Timeouts triggered during the restart roundtrip won’t be detected because there’s no timeout check after `run_restart` completes. This can let long/hung restart runs pass the 1‑hour guard. Add the same post-run timeout check used elsewhere.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

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

Adds new regression coverage to the MFC test toolchain to catch direction-dependent, MPI-rank-dependent, restart I/O, and specific kernel indexing issues.

Changes:

  • Added new generated test cases for direction symmetry, MPI ppn=2 consistency, restart roundtrip, and a polydisperse bubbles kernel golden.
  • Extended TestCase / TestCaseBuilder to support a restart_check flag and implemented run_restart() to perform a two-phase run.
  • Updated the test runner to perform restart roundtrip verification after a successful golden comparison.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
toolchain/mfc/test/test.py Runs restart roundtrip verification and compares restarted outputs to the straight-run pack.
toolchain/mfc/test/cases.py Adds new generated test cases for direction symmetry, MPI consistency, restart roundtrip, and kernel golden coverage.
toolchain/mfc/test/case.py Introduces restart_check plumbing and implements run_restart() for two-phase restart verification.

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

🧹 Nitpick comments (2)
toolchain/mfc/test/cases.py (1)

1151-1237: LGTM! MPI consistency tests cover three distinct physics modules (bubbles, viscous, hypoelasticity) at ppn=2. The hypoelasticity variant correctly includes all 6 tau_e components for the 3D domain. Stack push/pop is balanced for all three sub-tests.

One minor observation: the base_3d dict construction (lines 1157–1180) is nearly identical to the one in restart_roundtrip_tests (lines 1263–1285). If you find yourself adding more 3D test suites, consider extracting a helper, but for now this is fine.

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

In `@toolchain/mfc/test/cases.py` around lines 1151 - 1237, The base_3d dictionary
in mpi_consistency_tests is nearly identical to the base_3d in
restart_roundtrip_tests; extract that common dictionary construction into a
single helper (e.g., new function build_base_3d()) and replace the inline
base_3d definitions in mpi_consistency_tests and restart_roundtrip_tests with
calls to build_base_3d(), keeping all subsequent per-test updates (patch entries
and stack.push calls) unchanged; locate the code by referencing the function
names mpi_consistency_tests, restart_roundtrip_tests and the symbol base_3d to
make the replacement.
toolchain/mfc/test/test.py (1)

389-389: Prefer direct attribute access over getattr for a declared field.

restart_check is a declared field on TestCase (with default False), so case.restart_check always exists. Using getattr(case, 'restart_check', False) suggests the attribute might be missing, which is misleading.

♻️ Suggested simplification
-        if getattr(case, 'restart_check', False) and not ARG("add_new_variables"):
+        if case.restart_check and not ARG("add_new_variables"):
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@toolchain/mfc/test/test.py` at line 389, The condition uses getattr(case,
'restart_check', False) even though restart_check is a declared TestCase field
with a default; replace the getattr call with direct attribute access
(case.restart_check) in the conditional that also checks
ARG("add_new_variables") so it becomes: if case.restart_check and not
ARG("add_new_variables"): — update the expression where the variable case and
field restart_check are used to improve clarity and avoid the misleading
fallback.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@toolchain/mfc/test/test.py`:
- Around line 387-413: After completing the restart roundtrip (the block that
calls case.run_restart and repacks), overwrite the on-disk case.py with the
restored in-memory params so subsequent calls to case.run() use the correct
Phase 1 params; specifically, after the restart block and before the subsequent
ARG("test_all") / case.run() logic, write the current in-memory case parameters
back to disk (e.g., regenerate/overwrite case.py under case.get_dirpath()) so
the stale Phase 2 params (old_ic, old_grid, t_step_start) are replaced.
- Line 395: run_restart is missing type annotations for its gpus parameter;
update its signature to match run by annotating gpus as typing.Set[int] (same as
run at line 120) so calls from _handle_case passing devices (typed as
typing.Set[int]) remain type-safe—locate the run_restart definition and add the
gpus: Set[int] annotation and import typing.Set if not already imported.

---

Nitpick comments:
In `@toolchain/mfc/test/cases.py`:
- Around line 1151-1237: The base_3d dictionary in mpi_consistency_tests is
nearly identical to the base_3d in restart_roundtrip_tests; extract that common
dictionary construction into a single helper (e.g., new function
build_base_3d()) and replace the inline base_3d definitions in
mpi_consistency_tests and restart_roundtrip_tests with calls to build_base_3d(),
keeping all subsequent per-test updates (patch entries and stack.push calls)
unchanged; locate the code by referencing the function names
mpi_consistency_tests, restart_roundtrip_tests and the symbol base_3d to make
the replacement.

In `@toolchain/mfc/test/test.py`:
- Line 389: The condition uses getattr(case, 'restart_check', False) even though
restart_check is a declared TestCase field with a default; replace the getattr
call with direct attribute access (case.restart_check) in the conditional that
also checks ARG("add_new_variables") so it becomes: if case.restart_check and
not ARG("add_new_variables"): — update the expression where the variable case
and field restart_check are used to improve clarity and avoid the misleading
fallback.

@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 21, 2026

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@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 21, 2026
@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 21, 2026

CodeAnt AI Incremental review completed.

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 (3)
toolchain/mfc/test/test.py (1)

389-389: Prefer direct attribute access over getattr with a default.

restart_check is a declared bool = False field on TestCase, so getattr(case, 'restart_check', False) is unnecessarily defensive.

♻️ Proposed simplification
-        if getattr(case, 'restart_check', False) and not ARG("add_new_variables"):
+        if case.restart_check and not ARG("add_new_variables"):
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@toolchain/mfc/test/test.py` at line 389, The getattr call is unnecessarily
defensive because TestCase declares restart_check: bool = False; replace
getattr(case, 'restart_check', False) with direct attribute access
case.restart_check in the conditional (the if using case.restart_check and not
ARG("add_new_variables")). Update any similar occurrences tied to the TestCase
instance to use the restart_check attribute directly to keep the intent clear
and avoid redundant defaults.
toolchain/mfc/test/case.py (1)

113-114: Use T | None union syntax for optional parameters (Ruff RUF013).

PEP 484 prohibits implicit Optional via = None defaults for non-Optional-typed params. With Python 3.10+ required, the union syntax should be used.

♻️ Proposed fix
-    def __init__(self, trace: str, mods: dict, ppn: int = None, override_tol: float = None, restart_check: bool = False) -> None:
+    def __init__(self, trace: str, mods: dict, ppn: int | None = None, override_tol: float | None = None, restart_check: bool = False) -> None:

Same applies to define_case_d at line 369:

-def define_case_d(stack: CaseGeneratorStack, newTrace: str, newMods: dict, ppn: int = None, functor: Callable = None, override_tol: float = None, restart_check: bool = False) -> TestCaseBuilder:
+def define_case_d(stack: CaseGeneratorStack, newTrace: str, newMods: dict, ppn: int | None = None, functor: Callable | None = None, override_tol: float | None = None, restart_check: bool = False) -> TestCaseBuilder:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@toolchain/mfc/test/case.py` around lines 113 - 114, Change the function
signatures to use explicit union types (PEP 604) for parameters that default to
None: update __init__ to annotate ppn as int | None and override_tol as float |
None (leave restart_check as bool), and apply the same pattern in define_case_d
(convert any parameters typed like X with default None to X | None). Locate the
signatures by the unique symbols __init__ and define_case_d and replace the
non-Optional typed params that use = None with the T | None union syntax to
satisfy Ruff RUF013.
toolchain/mfc/test/cases.py (1)

1157-1180: Duplicated 3D-base setup across mpi_consistency_tests, restart_roundtrip_tests, and kernel_golden_tests.

The domain/BC/patch-geometry block is copy-pasted verbatim three times. The only variation is the grid size (29×29×49 for MPI tests vs 24×24×24 for the others).

♻️ Suggested helper extraction

Add a helper inside list_cases:

def make_3d_shock_base(m=24, n=24, p=24):
    base = {
        'm': m, 'n': n, 'p': p,
        'x_domain%beg': 0.E+00, 'x_domain%end': 1.E+00,
        'y_domain%beg': 0.E+00, 'y_domain%end': 1.E+00,
        'z_domain%beg': 0.E+00, 'z_domain%end': 1.E+00,
        'bc_x%beg': -3, 'bc_x%end': -3,
        'bc_y%beg': -3, 'bc_y%end': -3,
        'bc_z%beg': -3, 'bc_z%end': -3,
    }
    for pid in range(1, 4):
        base[f'patch_icpp({pid})%geometry'] = 9
        base[f'patch_icpp({pid})%vel(1)'] = 0.0
        base[f'patch_icpp({pid})%vel(2)'] = 0.0
        base[f'patch_icpp({pid})%vel(3)'] = 0.0
        base[f'patch_icpp({pid})%x_centroid'] = 0.5
        base[f'patch_icpp({pid})%length_x'] = 1
        base[f'patch_icpp({pid})%y_centroid'] = 0.5
        base[f'patch_icpp({pid})%length_y'] = 1
    base.update({
        'patch_icpp(1)%z_centroid': 0.05, 'patch_icpp(1)%length_z': 0.1,
        'patch_icpp(2)%z_centroid': 0.45, 'patch_icpp(2)%length_z': 0.7,
        'patch_icpp(3)%z_centroid': 0.9,  'patch_icpp(3)%length_z': 0.2,
    })
    return base

Then replace each duplicated block with base_3d = make_3d_shock_base() (or make_3d_shock_base(m=29, n=29, p=49) for the MPI case).

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

In `@toolchain/mfc/test/cases.py` around lines 1157 - 1180, Extract the repeated
3D domain/BC/patch-geometry block into a helper function (e.g.,
make_3d_shock_base) inside list_cases that returns a dict and accepts parameters
m,n,p (default 24) and then replace the three copy-pasted constructions with
calls to that helper (use make_3d_shock_base(m=29,n=29,p=49) for the MPI case);
ensure the helper populates the same keys (base_3d, patch_icpp(<pid>)%geometry,
vel(1..3), x_centroid/length_x, y_centroid/length_y and the three
z_centroid/length_z entries) so existing code that references base_3d and
patch_icpp(...) continues to work.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@toolchain/mfc/test/case.py`:
- Around line 148-172: mid_step currently uses self.params['t_step_stop'] // 2
which can produce mid < orig['t_step_start'] and create invalid Phase 1 params;
change mid_step to bisect the actual interval, e.g. compute mid_step =
(orig['t_step_start'] + orig['t_step_stop']) // 2 (using the original params
dict), then use orig for Phase 1 so t_step_start stays orig['t_step_start'] and
t_step_stop becomes mid_step, and for Phase 2 set t_step_start = mid_step with
t_step_save = orig['t_step_stop'] - mid_step; update references to mid_step,
params, and the Phase 1/Phase 2 setups around create_directory() and run()
accordingly.

---

Duplicate comments:
In `@toolchain/mfc/test/case.py`:
- Line 146: The method run_restart lacks type annotations; update its signature
to include explicit parameter and return types (for example: change def
run_restart(self, targets, gpus) to def run_restart(self, targets:
Sequence[str], gpus: Sequence[int]) -> None) and add the necessary typing import
(from typing import Sequence) at the top of the module, or adjust the concrete
types to match actual usage (List[str], int, Optional[...] or bool) if the
function semantics require different types; ensure the annotation matches usages
of run_restart elsewhere in the codebase.

In `@toolchain/mfc/test/test.py`:
- Line 395: The call to case.run_restart has previously flagged incorrect or
missing type annotations; update the run_restart function signature (the
run_restart method on the Case/CaseRunner class) to have precise parameter and
return types (e.g., devices: Sequence[Device] or List[Device], stages:
Sequence[Stage] or List[str] as appropriate) and a concrete return type (not
Any) so the assignment restart_result has a correct inferred type; then adjust
any usages (including this call site) to pass matching typed values and import
the Device/Stage types or use typing.Protocol/TypeAlias if needed.

---

Nitpick comments:
In `@toolchain/mfc/test/case.py`:
- Around line 113-114: Change the function signatures to use explicit union
types (PEP 604) for parameters that default to None: update __init__ to annotate
ppn as int | None and override_tol as float | None (leave restart_check as
bool), and apply the same pattern in define_case_d (convert any parameters typed
like X with default None to X | None). Locate the signatures by the unique
symbols __init__ and define_case_d and replace the non-Optional typed params
that use = None with the T | None union syntax to satisfy Ruff RUF013.

In `@toolchain/mfc/test/cases.py`:
- Around line 1157-1180: Extract the repeated 3D domain/BC/patch-geometry block
into a helper function (e.g., make_3d_shock_base) inside list_cases that returns
a dict and accepts parameters m,n,p (default 24) and then replace the three
copy-pasted constructions with calls to that helper (use
make_3d_shock_base(m=29,n=29,p=49) for the MPI case); ensure the helper
populates the same keys (base_3d, patch_icpp(<pid>)%geometry, vel(1..3),
x_centroid/length_x, y_centroid/length_y and the three z_centroid/length_z
entries) so existing code that references base_3d and patch_icpp(...) continues
to work.

In `@toolchain/mfc/test/test.py`:
- Line 389: The getattr call is unnecessarily defensive because TestCase
declares restart_check: bool = False; replace getattr(case, 'restart_check',
False) with direct attribute access case.restart_check in the conditional (the
if using case.restart_check and not ARG("add_new_variables")). Update any
similar occurrences tied to the TestCase instance to use the restart_check
attribute directly to keep the intent clear and avoid redundant defaults.

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 (3)
toolchain/mfc/test/case.py (3)

113-114: Use explicit T | None union syntax to satisfy PEP 484 (Ruff RUF013)

ppn: int = None and override_tol: float = None are implicit Optional — prohibited by PEP 484. With Python 3.10+ already required by this toolchain, prefer the union syntax.

♻️ Proposed fix
-    def __init__(self, trace: str, mods: dict, ppn: int = None, override_tol: float = None, restart_check: bool = False) -> None:
+    def __init__(self, trace: str, mods: dict, ppn: int | None = None, override_tol: float | None = None, restart_check: bool = False) -> None:

As per coding guidelines: "Python toolchain code. Follow PEP 8. Requires Python 3.10+."

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

In `@toolchain/mfc/test/case.py` around lines 113 - 114, The __init__ signature in
class Case (function __init__) uses implicit Optional defaults (ppn: int = None,
override_tol: float = None); update the annotations to explicit union types
using Python 3.10+ syntax (ppn: int | None, override_tol: float | None) so they
satisfy PEP 484/Ruff RUF013 and leave the default values as None; no additional
imports are necessary.

369-369: Implicit Optional in define_case_d signature (Ruff RUF013)

ppn: int = None, functor: Callable = None, and override_tol: float = None are all implicit Optional. Same PEP 484 concern as the __init__ signature.

♻️ Proposed fix
-def define_case_d(stack: CaseGeneratorStack, newTrace: str, newMods: dict, ppn: int = None, functor: Callable = None, override_tol: float = None, restart_check: bool = False) -> TestCaseBuilder:
+def define_case_d(stack: CaseGeneratorStack, newTrace: str, newMods: dict, ppn: int | None = None, functor: Callable | None = None, override_tol: float | None = None, restart_check: bool = False) -> TestCaseBuilder:

As per coding guidelines: "Python toolchain code. Follow PEP 8. Requires Python 3.10+."

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

In `@toolchain/mfc/test/case.py` at line 369, The function signature for
define_case_d uses implicit Optional types (ppn: int = None, functor: Callable =
None, override_tol: float = None); update the annotations to explicit Optional
types (ppn: Optional[int], functor: Optional[Callable[..., Any]] or
Optional[Callable] per project conventions, override_tol: Optional[float]) and
ensure Optional (and Any if used) are imported from typing at the top of the
module so the signature matches PEP 484/PEP 8 requirements.

146-147: Add type annotations to run_restart for consistency with run

run(self, targets: List[Union[str, MFCTarget]], gpus: Set[int]) is fully annotated; run_restart leaves targets and gpus untyped.

♻️ Proposed fix
-    def run_restart(self, targets, gpus):
+    def run_restart(self, targets: List[Union[str, MFCTarget]], gpus: Set[int]) -> subprocess.CompletedProcess:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@toolchain/mfc/test/case.py` around lines 146 - 147, The run_restart method
lacks type annotations; update its signature to match run by annotating targets
and gpus as: def run_restart(self, targets: List[Union[str, MFCTarget]], gpus:
Set[int]) (and add the same return type as run if present). Also ensure the
module imports the typing symbols (List, Union, Set) and MFCTarget is in scope
so the annotations resolve correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@toolchain/mfc/test/case.py`:
- Line 155: The current assignment self.params = {**orig, 't_step_stop':
mid_step, 't_step_save': mid_step} incorrectly treats t_step_save as an absolute
step (assuming t_step_start == 0); change it to compute t_step_save relative to
the start offset by using t_step_save = mid_step - orig.get('t_step_start', 0)
so Phase 1 will produce a checkpoint exactly at mid_step even when orig contains
a nonzero 't_step_start'; update the dict construction using
orig.get('t_step_start', 0) and keep 't_step_stop': mid_step unchanged.

---

Nitpick comments:
In `@toolchain/mfc/test/case.py`:
- Around line 113-114: The __init__ signature in class Case (function __init__)
uses implicit Optional defaults (ppn: int = None, override_tol: float = None);
update the annotations to explicit union types using Python 3.10+ syntax (ppn:
int | None, override_tol: float | None) so they satisfy PEP 484/Ruff RUF013 and
leave the default values as None; no additional imports are necessary.
- Line 369: The function signature for define_case_d uses implicit Optional
types (ppn: int = None, functor: Callable = None, override_tol: float = None);
update the annotations to explicit Optional types (ppn: Optional[int], functor:
Optional[Callable[..., Any]] or Optional[Callable] per project conventions,
override_tol: Optional[float]) and ensure Optional (and Any if used) are
imported from typing at the top of the module so the signature matches PEP
484/PEP 8 requirements.
- Around line 146-147: The run_restart method lacks type annotations; update its
signature to match run by annotating targets and gpus as: def run_restart(self,
targets: List[Union[str, MFCTarget]], gpus: Set[int]) (and add the same return
type as run if present). Also ensure the module imports the typing symbols
(List, Union, Set) and MFCTarget is in scope so the annotations resolve
correctly.

@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 22, 2026

CodeAnt AI is running Incremental review


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@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
@codeant-ai
Copy link
Contributor

codeant-ai bot commented Feb 22, 2026

CodeAnt AI Incremental review completed.

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 (3)
toolchain/mfc/test/case.py (2)

114-114: Use explicit | None type hints instead of implicit Optional.

Ruff (RUF013) flags ppn: int = None and override_tol: float = None — PEP 484 prohibits implicit Optional. Since the project requires Python 3.10+, the union syntax is available.

♻️ Suggested fix
-    def __init__(self, trace: str, mods: dict, ppn: int = None, override_tol: float = None, restart_check: bool = False) -> None:
+    def __init__(self, trace: str, mods: dict, ppn: int | None = None, override_tol: float | None = None, restart_check: bool = False) -> None:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@toolchain/mfc/test/case.py` at line 114, The constructor signature for class
__init__ uses implicit Optional via default None for parameters ppn and
override_tol (ppn: int = None, override_tol: float = None); update the type
hints to explicit union types using Python 3.10+ syntax (ppn: int | None and
override_tol: float | None) in the __init__ definition so the annotations match
PEP 484 and satisfy Ruff (RUF013) while leaving default values as None.

377-377: Same implicit Optional issue on define_case_d parameters.

Ruff (RUF013) flags the same pattern here. Apply the same | None fix for ppn, functor, and override_tol.

♻️ Suggested fix
-def define_case_d(stack: CaseGeneratorStack, newTrace: str, newMods: dict, ppn: int = None, functor: Callable = None, override_tol: float = None, restart_check: bool = False) -> TestCaseBuilder:
+def define_case_d(stack: CaseGeneratorStack, newTrace: str, newMods: dict, ppn: int | None = None, functor: Callable | None = None, override_tol: float | None = None, restart_check: bool = False) -> TestCaseBuilder:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@toolchain/mfc/test/case.py` at line 377, The function define_case_d has
implicit Optional types for ppn, functor, and override_tol; update the signature
to make the optionality explicit by annotating ppn as int | None, functor as
Callable | None, and override_tol as float | None (keeping the default = None),
so the type hints match RUF013 expectations and align with the other fixes
applied in this module.
toolchain/mfc/test/cases.py (1)

1264-1286: Repeated 3D base setup could be extracted into a helper.

The base-3D shock-tube construction (grid, BCs, geometry=9, patch centroids/lengths) is nearly identical in restart_roundtrip_tests (Lines 1264–1286) and kernel_golden_tests (Lines 1301–1323), and similar in mpi_consistency_tests (Lines 1157–1180). A shared helper would reduce duplication.

♻️ Sketch
def _make_base_3d(m=24, n=24, p=24):
    base = {
        'm': m, 'n': n, 'p': p,
        'x_domain%beg': 0.E+00, 'x_domain%end': 1.E+00,
        'y_domain%beg': 0.E+00, 'y_domain%end': 1.E+00,
        'z_domain%beg': 0.E+00, 'z_domain%end': 1.E+00,
        'bc_x%beg': -3, 'bc_x%end': -3,
        'bc_y%beg': -3, 'bc_y%end': -3,
        'bc_z%beg': -3, 'bc_z%end': -3,
    }
    for pid in range(1, 4):
        base[f'patch_icpp({pid})%geometry'] = 9
        for v in range(1, 4):
            base[f'patch_icpp({pid})%vel({v})'] = 0.0
        base[f'patch_icpp({pid})%x_centroid'] = 0.5
        base[f'patch_icpp({pid})%length_x']   = 1
        base[f'patch_icpp({pid})%y_centroid'] = 0.5
        base[f'patch_icpp({pid})%length_y']   = 1
    base.update({
        'patch_icpp(1)%z_centroid': 0.05, 'patch_icpp(1)%length_z': 0.1,
        'patch_icpp(2)%z_centroid': 0.45, 'patch_icpp(2)%length_z': 0.7,
        'patch_icpp(3)%z_centroid': 0.9,  'patch_icpp(3)%length_z': 0.2,
    })
    return base

Also applies to: 1301-1323

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

In `@toolchain/mfc/test/cases.py` around lines 1264 - 1286, Extract the duplicated
3D base setup into a helper function (e.g., _make_base_3d) and replace the
repeated dict construction in restart_roundtrip_tests, kernel_golden_tests, and
mpi_consistency_tests with calls to that helper; the helper should build the
base dict (m,n,p, domain bounds, bc_*), loop patchID 1..3 to set
'patch_icpp({pid})%geometry'=9, vel(1..3)=0.0, x_centroid/length_x and
y_centroid/length_y, and then update the three z_centroid/length_z entries
before returning the dict so callers can further update or override values as
needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@toolchain/mfc/test/case.py`:
- Around line 146-183: The test omits POST_PROCESS when creating the straight
and restart outputs so D/ is empty and packer.pack() compares nothing; update
the test flow to ensure POST_PROCESS runs for both the initial straight run and
the restart execution: when invoking run() in the straight-path (calls at
test.py ~341) and inside run_restart (calls to self.run(...) and later result2 =
self.run([SIMULATION], gpus) in run_restart), include POST_PROCESS in the target
list (e.g., [PRE_PROCESS, SIMULATION, POST_PROCESS]) or call POST_PROCESS
separately after the restart completes so that D/ is populated before calling
packer.pack() and the tolerance comparison validates real output differences.

---

Duplicate comments:
In `@toolchain/mfc/test/case.py`:
- Line 155: The bug is that t_step_save is set to the absolute mid_step instead
of a save interval relative to t_step_start, so the MFC save condition
mod(t_step - t_step_start, t_step_save) == 0 won't fire when t_step_start>0; fix
by computing a relative interval (e.g. rel_save = mid_step -
orig.get('t_step_start', 0)), ensure rel_save is >=1 (fallback to 1), and set
self.params = {**orig, 't_step_stop': mid_step, 't_step_save': rel_save};
reference symbols: self.params, orig, mid_step, 't_step_start', 't_step_save',
't_step_stop'.

---

Nitpick comments:
In `@toolchain/mfc/test/case.py`:
- Line 114: The constructor signature for class __init__ uses implicit Optional
via default None for parameters ppn and override_tol (ppn: int = None,
override_tol: float = None); update the type hints to explicit union types using
Python 3.10+ syntax (ppn: int | None and override_tol: float | None) in the
__init__ definition so the annotations match PEP 484 and satisfy Ruff (RUF013)
while leaving default values as None.
- Line 377: The function define_case_d has implicit Optional types for ppn,
functor, and override_tol; update the signature to make the optionality explicit
by annotating ppn as int | None, functor as Callable | None, and override_tol as
float | None (keeping the default = None), so the type hints match RUF013
expectations and align with the other fixes applied in this module.

In `@toolchain/mfc/test/cases.py`:
- Around line 1264-1286: Extract the duplicated 3D base setup into a helper
function (e.g., _make_base_3d) and replace the repeated dict construction in
restart_roundtrip_tests, kernel_golden_tests, and mpi_consistency_tests with
calls to that helper; the helper should build the base dict (m,n,p, domain
bounds, bc_*), loop patchID 1..3 to set 'patch_icpp({pid})%geometry'=9,
vel(1..3)=0.0, x_centroid/length_x and y_centroid/length_y, and then update the
three z_centroid/length_z entries before returning the dict so callers can
further update or override values as needed.

@qodo-code-review
Copy link
Contributor

ⓘ Your monthly quota for Qodo has expired. Upgrade your plan
ⓘ Paying users. Check that your Qodo account is linked with this Git user account

2 similar comments
@qodo-code-review
Copy link
Contributor

ⓘ Your monthly quota for Qodo has expired. Upgrade your plan
ⓘ Paying users. Check that your Qodo account is linked with this Git user account

@qodo-code-review
Copy link
Contributor

ⓘ Your monthly quota for Qodo has expired. Upgrade your plan
ⓘ Paying users. Check that your Qodo account is linked with this Git user account

@codecov
Copy link

codecov bot commented Feb 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 44.08%. Comparing base (df28255) to head (0108e49).
⚠️ Report is 9 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1213      +/-   ##
==========================================
+ Coverage   44.05%   44.08%   +0.02%     
==========================================
  Files          70       70              
  Lines       20496    20496              
  Branches     1989     1989              
==========================================
+ Hits         9030     9035       +5     
+ Misses      10328    10323       -5     
  Partials     1138     1138              

☔ 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.

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.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="toolchain/mfc/test/case.py">

<violation number="1" location="toolchain/mfc/test/case.py:184">
P2: Avoid swallowing all exceptions when recreating the test directory; it can mask filesystem failures and leave the test state inconsistent. Let the exception surface (or handle a specific expected error) so failures are visible.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

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.

🧹 Nitpick comments (3)
toolchain/mfc/test/case.py (3)

182-187: Silent except Exception: pass in cleanup may hide disk-level failures.

The intent (restore case.py on disk) is sound, but swallowing all exceptions makes it hard to diagnose failures in CI. Consider at least logging a warning so maintainers know the cleanup didn't succeed.

Log the failure instead of silencing it
         finally:
             self.params = orig
             try:
                 self.create_directory()
-            except Exception:
-                pass
+            except Exception as exc:        # noqa: BLE001
+                cons.print(f"[yellow]Warning:[/yellow] Failed to restore case.py after restart: {exc}")

(Requires importing cons from ..printer.)

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

In `@toolchain/mfc/test/case.py` around lines 182 - 187, The finally block that
restores self.params = orig and calls self.create_directory() currently swallows
all exceptions with "except Exception: pass"; instead catch Exception as e and
log a warning via the project's printer (import cons from ..printer) so
disk-level failures are visible in CI; update the except on the create_directory
call in case.py to use except Exception as e: cons.warn(...) (providing context
like "failed to recreate case directory" and include e) rather than silently
passing.

146-160: Phase 1 passes full targets list including PRE_PROCESS, while Phase 2 hardcodes [SIMULATION] — document the asymmetry.

The design is intentional (Phase 1 needs grid generation; Phase 2 reuses the grid), but a reader unfamiliar with MFC's restart workflow may wonder why Phase 2 drops PRE_PROCESS. A brief inline comment on line 171 would help.

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

In `@toolchain/mfc/test/case.py` around lines 146 - 160, In run_restart, add a
brief inline comment explaining why Phase 1 calls run with the full targets list
(including PRE_PROCESS) while Phase 2 calls run with only [SIMULATION]: Phase 1
must generate the grid and restart data (hence PRE_PROCESS), and Phase 2 reuses
that grid so only SIMULATION is required; place the comment near the two
run(...) calls (referencing run_restart, run(targets, gpus), PRE_PROCESS and
SIMULATION) so readers understand the intentional asymmetry.

114-114: PEP 484 prohibits implicit Optional; use T | None (Python 3.10+).

Ruff flags ppn: int = None and override_tol: float = None as implicit optionals. Since the toolchain targets Python 3.10+, the union syntax is available.

Suggested fix
-    def __init__(self, trace: str, mods: dict, ppn: int = None, override_tol: float = None, restart_check: bool = False) -> None:
+    def __init__(self, trace: str, mods: dict, ppn: int | None = None, override_tol: float | None = None, restart_check: bool = False) -> None:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@toolchain/mfc/test/case.py` at line 114, The __init__ signature uses implicit
Optional by assigning None to typed parameters (ppn: int = None, override_tol:
float = None); update the annotations to explicit union types supported in
Python 3.10+ (use ppn: int | None and override_tol: float | None) in the
__init__ method to satisfy PEP 484/ruff; keep the default values as None and
leave restart_check: bool unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@toolchain/mfc/test/test.py`:
- Line 395: The run_restart function currently accepts a targets parameter but
only uses it for Phase 1 while Phase 2 always uses [SIMULATION]; update the code
to avoid confusion by either (A) clarifying the behavior in run_restart's
docstring (explicitly state that the targets argument applies only to Phase 1
and Phase 2 is always [SIMULATION]) or (B) simplify the API by removing the
targets parameter from run_restart and hardcoding the intended phases (e.g.,
PRE_PROCESS then SIMULATION) inside the function; locate references to
run_restart and the Phase 2 hardcode to make the change and update any
callers/tests accordingly.

---

Nitpick comments:
In `@toolchain/mfc/test/case.py`:
- Around line 182-187: The finally block that restores self.params = orig and
calls self.create_directory() currently swallows all exceptions with "except
Exception: pass"; instead catch Exception as e and log a warning via the
project's printer (import cons from ..printer) so disk-level failures are
visible in CI; update the except on the create_directory call in case.py to use
except Exception as e: cons.warn(...) (providing context like "failed to
recreate case directory" and include e) rather than silently passing.
- Around line 146-160: In run_restart, add a brief inline comment explaining why
Phase 1 calls run with the full targets list (including PRE_PROCESS) while Phase
2 calls run with only [SIMULATION]: Phase 1 must generate the grid and restart
data (hence PRE_PROCESS), and Phase 2 reuses that grid so only SIMULATION is
required; place the comment near the two run(...) calls (referencing
run_restart, run(targets, gpus), PRE_PROCESS and SIMULATION) so readers
understand the intentional asymmetry.
- Line 114: The __init__ signature uses implicit Optional by assigning None to
typed parameters (ppn: int = None, override_tol: float = None); update the
annotations to explicit union types supported in Python 3.10+ (use ppn: int |
None and override_tol: float | None) in the __init__ method to satisfy PEP
484/ruff; keep the default values as None and leave restart_check: bool
unchanged.

@sbryngelson sbryngelson marked this pull request as draft February 22, 2026 14:53
sbryngelson and others added 7 commits February 23, 2026 09:48
…l tests

Four new test categories to catch edge-case bugs:

1. Direction symmetry: 3D shock tube tests with shock propagating in x
   and y directions (default 3D tests use z), catching direction-specific
   bugs in reconstruction and gradient calculations.

2. MPI consistency: ppn=2 tests for bubbles, viscous flows, and
   hypoelasticity, catching broadcast/reduction bugs in MPI-sensitive
   physics modules.

3. Restart roundtrip: 1D and 3D tests that run a straight simulation,
   then restart from the midpoint and compare the restarted output
   against the straight run output to verify restart I/O fidelity.

4. Kernel golden values: 3D grid stretching test exercising non-uniform
   grid spacing in all three directions, which interacts with WENO
   reconstruction and gradient calculations direction-specifically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…oat consistency

- Add timeout check after run_restart completes to catch hung restarts
- Restore case.py on disk in finally block so test_all mode uses correct params
- Use 1.0 instead of 1 for float consistency in direction symmetry tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add pylint disable comments for too-many-arguments/too-many-positional-arguments
on TestCase.__init__ and too-many-instance-attributes on TestCaseBuilder,
following the existing pattern already used in define_case_d/define_case_f.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
mid_step = t_step_stop // 2 produced an invalid Phase 1 run when
t_step_start > 0, since the midpoint could fall before the start step.
Use (t_step_start + t_step_stop) // 2 so Phase 1 always has a valid range.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Restart roundtrip: Phase 2 now runs only SIMULATION (skips pre_process)
since it reads grid+IC directly from p_all/p0/<mid_step>/. D/ is
preserved across phases and intermediate step files are cleaned up so
the final output matches a straight run.

Grid stretching: Enlarge patches to cover the cosh-stretched domain
(which expands beyond [0,1] to ~[0,1.39] with a=2, x_a=0.3, x_b=0.7).
Without this, cells beyond the original bounds are uninitialized.

Hypoelasticity MPI: Add dt=1e-06 matching other 3D hypoelasticity tests
(default dt=0.0005 exceeds CFL for the high speed of sound ~88).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use mid_step - t_step_start instead of bare mid_step so the save
interval aligns correctly when t_step_start > 0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…oat consistency

- Use common.delete_file instead of raw os.remove for intermediate
  step cleanup (prevents filesystem errors from crashing a passing test)
- Guard finally block's create_directory so it cannot mask the original
  exception on failure
- Use direct case.restart_check instead of getattr with default (fail
  loudly if attribute is removed rather than silently skipping tests)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

1 participant