Skip to content

Fix MIRK extrema boundary conditions under AD - #542

Draft
ChrisRackauckas-Claude wants to merge 5 commits into
SciML:masterfrom
ChrisRackauckas-Claude:fix-mirk-dual-interpolation
Draft

Fix MIRK extrema boundary conditions under AD#542
ChrisRackauckas-Claude wants to merge 5 commits into
SciML:masterfrom
ChrisRackauckas-Claude:fix-mirk-dual-interpolation

Conversation

@ChrisRackauckas-Claude

@ChrisRackauckas-Claude ChrisRackauckas-Claude commented Jul 10, 2026

Copy link
Copy Markdown
Member

Ignore this PR until reviewed by @ChrisRackauckas.

Summary

  • Make MIRK dense interpolation evaluate against dual-compatible stage caches during boundary-condition AD.
  • Use the dense AD mode for MIRK boundary residual construction.
  • Strip nested dual values before solving the auxiliary extrema root problems used by maxsol/minsol, via BoundaryValueDiffEqCore.nodual_value rather than direct MIRK access to ForwardDiff internals.
  • Add a regression test for MIRK4 with maxsol/minsol boundary conditions.
  • Keep direct interpolation reads on primal DiffCache stages so sparse constraint tracing does not read uninitialized AD temporaries.

Local Verification

  • Exact pendulum maxsol/minsol MIRK4 reproducer under Julia 1.10 -> SciMLBase.successful_retcode(extrema_sol) = true
  • Exact pendulum maxsol/minsol MIRK4 reproducer under Julia 1.12 -> SciMLBase.successful_retcode(extrema_sol) = true
  • Targeted Julia 1.12 optimizer reproducer with local Core/MIRK and OptimizationIpopt: bounded constraint path -> SciMLBase.successful_retcode(sol1) = true; no-user-bounds optimization path -> SciMLBase.successful_retcode(sol2) = true
  • BOUNDARYVALUEDIFFEQ_TEST_GROUP=QA timeout 3600 julia +1.10 --project=lib/BoundaryValueDiffEqMIRK -e 'using Pkg; Pkg.test()' -> Quality Assurance 15/15 passed
  • git diff --check
  • Runic formatter check with Runic.main(["-c", "-d", "."]) passed under Julia 1.12

CI Status on 6614a935

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results (Julia v1.11)

Time benchmarks
master 4ef52d1... master / 4ef52d1...
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK2() 0.584 ± 0.012 s 0.573 ± 0.009 s 1.02 ± 0.026
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK3() 12.3 ± 0.21 ms 12.1 ± 0.24 ms 1.02 ± 0.027
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK4() 2.7 ± 0.1 ms 2.65 ± 0.091 ms 1.02 ± 0.052
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK5() 3.29 ± 0.11 ms 3.18 ± 0.13 ms 1.03 ± 0.056
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK6() 1.58 ± 0.063 ms 1.54 ± 0.051 ms 1.02 ± 0.053
Simple Pendulum/IIP/MultipleShooting(10, Tsit5; grid_coarsening = false) 1.55 ± 0.098 ms 1.52 ± 0.072 ms 1.02 ± 0.081
Simple Pendulum/IIP/MultipleShooting(10, Tsit5; grid_coarsening = true) 3.29 ± 0.19 ms 3.17 ± 0.15 ms 1.04 ± 0.077
Simple Pendulum/IIP/MultipleShooting(100, Tsit5; grid_coarsening = false) 0.0406 ± 0.0038 s 0.0397 ± 0.0033 s 1.02 ± 0.13
Simple Pendulum/IIP/MultipleShooting(100, Tsit5; grid_coarsening = true) 0.0641 ± 0.0022 s 0.0629 ± 0.0027 s 1.02 ± 0.057
Simple Pendulum/IIP/Shooting(Tsit5()) 0.177 ± 0.076 ms 0.174 ± 0.073 ms 1.02 ± 0.61
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK2() 0.74 ± 0.0075 s 0.72 ± 0.0057 s 1.03 ± 0.013
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK3() 15.9 ± 5.5 ms 15.3 ± 4.6 ms 1.04 ± 0.48
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK4() 3.23 ± 0.16 ms 3.16 ± 0.15 ms 1.02 ± 0.07
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK5() 3.97 ± 0.21 ms 3.84 ± 0.26 ms 1.03 ± 0.09
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK6() 1.86 ± 0.11 ms 1.85 ± 0.12 ms 1 ± 0.086
Simple Pendulum/OOP/MultipleShooting(10, Tsit5; grid_coarsening = false) 3.4 ± 0.68 ms 3.37 ± 0.85 ms 1.01 ± 0.32
Simple Pendulum/OOP/MultipleShooting(10, Tsit5; grid_coarsening = true) 6.56 ± 6 ms 6.5 ± 5.5 ms 1.01 ± 1.3
Simple Pendulum/OOP/MultipleShooting(100, Tsit5; grid_coarsening = false) 0.0856 ± 0.003 s 0.0833 ± 0.0022 s 1.03 ± 0.045
Simple Pendulum/OOP/MultipleShooting(100, Tsit5; grid_coarsening = true) 0.135 ± 0.0032 s 0.128 ± 0.0032 s 1.05 ± 0.036
Simple Pendulum/OOP/Shooting(Tsit5()) 0.607 ± 0.047 ms 0.595 ± 0.048 ms 1.02 ± 0.11
time_to_load 7.21 ± 0.018 s 7.06 ± 0.019 s 1.02 ± 0.0038
Memory benchmarks
master 4ef52d1... master / 4ef52d1...
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK2() 0.389 M allocs: 0.0443 GB 0.389 M allocs: 0.0443 GB 1
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK3() 0.0436 M allocs: 4.88 MB 0.0436 M allocs: 4.88 MB 1
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK4() 15.7 k allocs: 1.65 MB 15.7 k allocs: 1.65 MB 1
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK5() 22.1 k allocs: 2.03 MB 22.1 k allocs: 2.03 MB 1
Simple Pendulum/IIP/BoundaryValueDiffEqMIRK.MIRK6() 12.8 k allocs: 1.05 MB 12.8 k allocs: 1.05 MB 1
Simple Pendulum/IIP/MultipleShooting(10, Tsit5; grid_coarsening = false) 25.5 k allocs: 1.82 MB 25.5 k allocs: 1.82 MB 1
Simple Pendulum/IIP/MultipleShooting(10, Tsit5; grid_coarsening = true) 0.0491 M allocs: 3.39 MB 0.0491 M allocs: 3.39 MB 1
Simple Pendulum/IIP/MultipleShooting(100, Tsit5; grid_coarsening = false) 0.553 M allocs: 0.0535 GB 0.553 M allocs: 0.0535 GB 1
Simple Pendulum/IIP/MultipleShooting(100, Tsit5; grid_coarsening = true) 0.833 M allocs: 0.0778 GB 0.833 M allocs: 0.0778 GB 1
Simple Pendulum/IIP/Shooting(Tsit5()) 4.63 k allocs: 0.224 MB 4.63 k allocs: 0.224 MB 1
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK2() 0.89 M allocs: 0.984 GB 0.89 M allocs: 0.984 GB 1
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK3() 0.0932 M allocs: 24.8 MB 0.0932 M allocs: 24.8 MB 1
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK4() 0.0324 M allocs: 3.96 MB 0.0324 M allocs: 3.96 MB 1
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK5() 0.045 M allocs: 4.99 MB 0.045 M allocs: 4.99 MB 1
Simple Pendulum/OOP/BoundaryValueDiffEqMIRK.MIRK6() 25.3 k allocs: 2.17 MB 25.3 k allocs: 2.17 MB 1
Simple Pendulum/OOP/MultipleShooting(10, Tsit5; grid_coarsening = false) 0.142 M allocs: 10.2 MB 0.142 M allocs: 10.2 MB 1
Simple Pendulum/OOP/MultipleShooting(10, Tsit5; grid_coarsening = true) 0.266 M allocs: 18.7 MB 0.266 M allocs: 18.7 MB 1
Simple Pendulum/OOP/MultipleShooting(100, Tsit5; grid_coarsening = false) 2.52 M allocs: 0.279 GB 2.52 M allocs: 0.279 GB 1
Simple Pendulum/OOP/MultipleShooting(100, Tsit5; grid_coarsening = true) 3.82 M allocs: 0.404 GB 3.82 M allocs: 0.404 GB 1
Simple Pendulum/OOP/Shooting(Tsit5()) 0.0373 M allocs: 1.69 MB 0.0373 M allocs: 1.69 MB 1
time_to_load 0.159 k allocs: 11.2 kB 0.159 k allocs: 11.2 kB 1

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member Author

Update pushed in c306f64.

Additional local verification for the Mooncake Julia-pre failure:

timeout 3600 env JULIA_DEPOT_PATH=/home/crackauc/sandbox/tmp_20260708_121627_10236/julia_depot_mirk_mooncake_matvec /home/crackauc/.juliaup/bin/julia +1.13 --startup-file=no --project=lib/BoundaryValueDiffEqMIRK/test/AD -e 'import Pkg; Pkg.instantiate(); include("lib/BoundaryValueDiffEqMIRK/test/AD/ad_tests.jl")'\n```\n\nObserved result:\n\n```\nTest Summary:              | Pass  Total      Time\nDifferent AD compatibility |    9      9  15m01.1s\n```\n\nAlso ran:\n\n```\ntimeout 3600 julia +1 --startup-file=no --project=.runic_env -m Runic --check lib/BoundaryValueDiffEqMIRK/src/interpolation.jl lib/BoundaryValueDiffEqMIRK/src/collocation.jl\n```\n\nRunic exited successfully.

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member Author

Final-state verification after the variable rename commit 4ef52d14:

timeout 3600 env JULIA_DEPOT_PATH=/home/crackauc/sandbox/tmp_20260708_121627_10236/julia_depot_mirk_mooncake_matvec /home/crackauc/.juliaup/bin/julia +1.13 --startup-file=no --project=lib/BoundaryValueDiffEqMIRK/test/AD -e 'import Pkg; Pkg.instantiate(); include("lib/BoundaryValueDiffEqMIRK/test/AD/ad_tests.jl")'\n```\n\nObserved result:\n\n```\nTest Summary:              | Pass  Total      Time\nDifferent AD compatibility |    9      9  14m57.5s\n```\n\nLocal checks after `4ef52d14`:\n\n```\ntimeout 3600 julia +1 --startup-file=no --project=.runic_env -m Runic --check lib/BoundaryValueDiffEqMIRK/src/interpolation.jl lib/BoundaryValueDiffEqMIRK/src/collocation.jl\n/home/crackauc/.local/bin/typos lib/BoundaryValueDiffEqMIRK/src/interpolation.jl lib/BoundaryValueDiffEqMIRK/src/collocation.jl\ngit diff --check\n```\n\nAll exited successfully.

Copy link
Copy Markdown
Member Author

Downstream audit replay for head 4ef52d1443062cf0e6877fa3338752c35af5939f:

I ran the exact current ModelingToolkitBase BVPOnly target under Julia 1.12 with this PR's local BoundaryValueDiffEq source projects. The test group genuinely executed; it did not silently select zero tests.

Observed terminal summary:

Optimal Control + Constraints Tests | 20 pass, 2 fail, 1 error, 5 broken

The two failures are the cost-function compilation checks evaluating NaN ≈ NaN; the error is the parameter-estimation optimization path. The testset reported 51m36s before exiting 1. I therefore cannot claim the complete MTKBase BVP target passes against this head.

This result is relevant to the caller-workflow correction in #563: that PR points CI at the right moved test group, and the remaining red result is genuine source/integration behavior rather than a workflow startup failure or no-op.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas-Claude
ChrisRackauckas-Claude force-pushed the fix-mirk-dual-interpolation branch from 4ef52d1 to 3ed990d Compare July 20, 2026 18:02
@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member Author

Rebased this branch onto current master (5e9eb4e) and reran the affected lanes locally.

PR-specific validation:

  • Julia 1.12 MIRK AD group: 9/9 passed (MIRK AD Tests, 18m03.1s).
  • Julia 1.12 MIRK Core reached the changed interpolation block: 80/80 passed.
  • repository-wide Runic check passed; git diff --check passed.

The broader current-dependency Core run ended at 195 passed, 2 failed, and 1 errored. All three outcomes are independently reproduced on untouched current master and are unrelated to this interpolation patch:

  • The error is the OptimizationBase 5.2.1 / OptimizationIpopt 1.3.0 generic-cache regression introduced by Optimization PR #1257; Optimization PR #1270 passes the exact BVP reproduction.
  • The two failures are successful Ipopt solves rejected only by existing @test_nowarn assertions after OptimizationBase began emitting missing_second_order_ad. Both focused testsets reproduce identically on clean BVP master with OptimizationIpopt 1.3.0 and pass with 1.2.3. Optimization PR #1269 covers the explicit sparse-second-order handling.

No test was skipped, disabled, silenced, or loosened. The branch changes themselves remain the original five focused commits.

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member Author

CI classification for rebased head 3ed990db:

  • MIRK AD passed on Julia lts and pre. The Julia 1 AD job lost communication with its self-hosted runner while the test step was active, so it produced no test failure.
  • MIRK Core on Julia lts/1/pre and the MIRK downgrade job reach the same current-dependency result reproduced on clean master: 195 passed, 2 failed, 1 errored. The changed interpolation testset is 80/80 and the maxsol/minsol regression is 3/3. The residuals are the OptimizationBase/OptimizationIpopt issues covered by Optimization.jl #1269 and #1270.
  • FIRK downgrade also lost communication with its self-hosted runner and produced no test failure.
  • Shooting downgrade reproduces the dual ODE-cache error already split into Fix MultipleShooting caches for tagged AD states #541.
  • ModelingToolkit downstream genuinely ran to 7242 passed, 2 failed, 1 errored, 5 broken. Its BVP residuals match the same Optimization integration failures reproduced locally on clean BVP master; this is not an interpolation regression.
  • The benchmark check failed before checkout because the trusted pull_request_target workflow refused to execute fork PR code. No benchmark code ran in that check.
  • Repository Misc/QA/Wrappers, docs, Runic, spell check, MIRK QA, MIRK AD lts/pre, and the remaining downgrade sublibraries are green.

No additional PR-specific failure is exposed by this run.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants