Speed up propagation step time by 3x - #175
Merged
Merged
Conversation
scottshambaugh
force-pushed
the
perf
branch
from
September 11, 2026 16:29
bfb88eb to
fdc5b20
Compare
Contributor
Author
|
Space weather timing bug broken out to #176 instead of being lumped in with this. |
Owner
|
This is a very impressive speedup. I'll take a closer look over the weekend, and merge if performance/accuracy is expected. Thank you. |
Owner
|
For your comment about the initial timestep PID convergence: I'll have to think about this one. If I remember correctly, I had a tough time figuring this out and ended up copying the algorithm for initial step size from the ODE module in the Julia programming language. I could:
I'll look at this over the weekend as well, and thanks again for your contributions. |
Owner
|
All looks good. Merged. Thank you! |
ssmichael1
added a commit
that referenced
this pull request
Sep 12, 2026
Claude-Session: https://claude.ai/code/session_01XX7RJzhJFFjTyNpRhgCsqF Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
3 tasks
ssmichael1
added a commit
that referenced
this pull request
Sep 12, 2026
… (numeris 0.6) The adaptive integrators no longer start from numeris' Hairer starting-step heuristic, which is scale sensitive: for an orbit in metres and seconds at 1e-9 tolerance it started RKV98 at a fraction of a millisecond against a ~270 s working step and spent about half the force evaluations of a one-hour arc growing into it (satkit #175 discussion). - `PropSettings::initial_step_secs: Option<f64>` — first step to attempt. `None` (default) derives `1.5 · |r|/|v| · tol^(1/(p+1))` from the initial state, the tolerances (`tol = rel_error + abs_error/|r|`) and the integrator order `p`: the settled stride of an order-p method scales as tol^(1/(p+1)), and the constant is fit to LEO strides. Across RKTS54..RKV98 and 1e-6..1e-12 the hint lands within 0.64–2.6× of the settled stride, so the controller is on stride in a step or two. Ignored by Gauss-Jackson 8. Zero / non-finite → error. - `PropagationResult::next_step_secs` — the integrator's working stride at the end of the arc (numeris `Solution::next_step`; GJ8's fixed step; 0 for a zero-duration arc), signed like the propagation direction, so a follow-on arc can warm-start by passing it back. - Python: `propsettings.initial_step_secs` (kwarg + property, pickled) and `propresult.next_step_secs`; stubs and docstrings; integrators guide section; CHANGELOG. - numeris requirement 0.5.18 → 0.6.0. One-hour 550 km arc, RKV98 at 1e-9, 8x8 gravity: 525 evals with the old-heuristic-sized start → 315 with the default hint → 294 warm-started from the previous hour; every RK integrator at every tolerance from 1e-6 to 1e-12 is now within one step of the warm-start cost. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017VHexyxYasfatXebfxtphw
ssmichael1
added a commit
that referenced
this pull request
Sep 12, 2026
…ris 0.6) (#178) * feat(orbitprop): initial_step_secs hint and next_step_secs warm start (numeris 0.6) The adaptive integrators no longer start from numeris' Hairer starting-step heuristic, which is scale sensitive: for an orbit in metres and seconds at 1e-9 tolerance it started RKV98 at a fraction of a millisecond against a ~270 s working step and spent about half the force evaluations of a one-hour arc growing into it (satkit #175 discussion). - `PropSettings::initial_step_secs: Option<f64>` — first step to attempt. `None` (default) derives `1.5 · |r|/|v| · tol^(1/(p+1))` from the initial state, the tolerances (`tol = rel_error + abs_error/|r|`) and the integrator order `p`: the settled stride of an order-p method scales as tol^(1/(p+1)), and the constant is fit to LEO strides. Across RKTS54..RKV98 and 1e-6..1e-12 the hint lands within 0.64–2.6× of the settled stride, so the controller is on stride in a step or two. Ignored by Gauss-Jackson 8. Zero / non-finite → error. - `PropagationResult::next_step_secs` — the integrator's working stride at the end of the arc (numeris `Solution::next_step`; GJ8's fixed step; 0 for a zero-duration arc), signed like the propagation direction, so a follow-on arc can warm-start by passing it back. - Python: `propsettings.initial_step_secs` (kwarg + property, pickled) and `propresult.next_step_secs`; stubs and docstrings; integrators guide section; CHANGELOG. - numeris requirement 0.5.18 → 0.6.0. One-hour 550 km arc, RKV98 at 1e-9, 8x8 gravity: 525 evals with the old-heuristic-sized start → 315 with the default hint → 294 warm-started from the previous hour; every RK integrator at every tolerance from 1e-6 to 1e-12 is now within one step of the warm-start cost. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017VHexyxYasfatXebfxtphw * orbitprop: run rkv98 as the 16-stage tableau when interpolation is off The five extra stages of the 21-stage Verner 9(8) tableau exist only to build the interpolant. With `enable_interp = false` nothing is stored to interpolate, so `Integrator::RKV98` now dispatches to `RKV98NoInterp`: same order and error control, 24% fewer force evaluations per step. The result still reports `Integrator::RKV98`; `interp` fails with "no dense output" exactly as before. Results for that combination change at the tolerance level (a different tableau takes different steps). Tests pin evals == 16 × steps without interpolation and 21 × steps with, and agreement of the two final positions to 1 cm over an hour. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017VHexyxYasfatXebfxtphw --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I've been trying out different numerical propagators, and this is the fastest so far, with results aligning with both Orekit and Tudat. Nice project!
This PR rolls in the following performance improvements:
fma(fused multiply add) compiler support, and use fma at runtime if the machine supports it. Cuts the gravity evaluation by ~5xOne more performance issue to flag: the initial timestep PID convergence is slow, and is the dominant time on short-duration propagation - about half the evaluations for a one-hour horizon. A warm start or forced initial step would drastically reduce the needed calls there. I believe this would require a coordinated
numerischange.earthgravity/accel40x40nrlmsise/density_400km