SolvSRK 2.5.0
Date: 2026-08-27
The headline of 2.5.0 is that run() behaves like scipy.integrate.solve_ivp —
t_eval, dense_output, events, and a result object that subclasses SciPy's
— and that the solver now reports honest step statistics. Licensing moved to
Ed25519, which means existing .lic files must be reissued.
Breaking changes
- Reissue your license file. Licensing moved from HMAC-SHA256 to Ed25519
signatures and the payload format is now
solvsrk-license-v3. Previously issued.licfiles no longer validate. Download a replacement from resonix.io/account (opens in a new tab) — your seat is unaffected. The product now embeds only a public key, so a shipped binary cannot be used to forge a license. - Uncertainty quantification is a separate SKU. A base subscription no
longer enables
emit_uq; the seat must carryfeatures: uq(SolvSRK-UQ) orfeatures: edge(SolvSRK-Edge). 30-day trials include UQ so you can evaluate it. Check at runtime withsolvsrk.license_has_uq()(solvsrk_license_has_uq()in C).
SciPy-compatible solving
run(..., t_eval=..., dense_output=True, events=g)mirrors thesolve_ivpknobs:t/yon a caller-supplied grid,sol(t)for continuous output, andt_events/y_eventsfrom zero crossings.run()andrun_profile()returnSolveResult, which subclasses SciPy'sOdeResultwhen SciPy is installed (pip install solvsrk[scipy]) and behaves like a dict otherwise.- Interpolation is the method interpolant (cubic Hermite from CVODE) on continuation spans; EK and explicit-RK spans stay piecewise linear.
- A terminal event — or a truthy
status_fnreturn — stops the native integrator at the first accepted sample after the request and reportsuser_stoppedwith SciPy'sstatus=1andsuccess=True. - Endpoint
t/yare always populated;solisNoneunless you ask fordense_output=True.
Trajectory telemetry
run(..., emit_history=True)records every accepted step into caller-owned buffers with phase labels, interval subsampling, explicit truncation reporting, and aggregatenfev/njev/nlu/nsteps/nfailedcounters. Python returns SciPy-shapedtandy.- Real rejected-step and factorization counts. Every continuation backend
now reports
n_failed(error-test rejections, plus Newton stalls and singular-LU retries where they apply) andn_lu(Newton/stage-matrix factorizations —0for the matrix-free explicit-RK backend). These surface ascvode_n_failed/cvode_n_luand aggregate intonfailed/nlu, so MATLAB-stylesol.statsreports realnfailedandndecompsinstead of placeholders.
Choosing a solver path
-
Three continuation backends are selectable: CVODE (default), a matrix-free explicit RK45 path for non-stiff spans, and an accuracy mode for tight-tolerance work.
-
solvsrk.config()takes SolvTune's output directly, so a recommendation becomes a run without hand-translating fields:cfg = solvsrk.config(mode="acmode", rtol=1e-12, atol=1e-12, ek_max_steps=0) solvsrk.run(cfg, dim, t0, t_end, y0, rhs)modeis one ofacmode,rk,stiff,switch. -
The Python RHS callback marshals state vectors in one vectorised conversion per step instead of element by element, which cuts per-step overhead on higher-dimensional systems.
-
SolvTune's linear path (profile mode 1) ships in every wheel and is covered by your SolvSRK seat — no separate SolvLRDE license.
Java / Jython (Cameo)
- The JNA binding tracks the native struct layout, allocates caller-owned
history buffers when
emit_history=1, and returns SciPy-shapedgetT()/getY()with phase labels and truncation status. emit_dense=1copies the same interpolant pieces before the native session is freed, andRunResult.evalAt(tEval)uses them (linear fallback on EK/RK spans).StatusCallback.onStatusreturnsint;RunResult.isUserStopped()reports a live abort.RunResultexposesnfev/njev/nlu/nsteps/nfailed/nlinsolsso Jython callers can fill MATLAB-stylesol.statswithout reading the raw struct.scripts/stage_cameo_bundle.pybuilds a turnkey Cameo pilot bundle;scripts/verify_cameo_bundle.pyvalidates its layout and runs a Jython smoke test.
Fixed
- Import failures on Linux and macOS. The shared library was emitted as
liblibsolvsrk.so/.dylib, which nothing looks for, so any Linux or macOS wheel failed at import with "libsolvsrk could not be located". The name is correct again and the Python loader now accepts the shipped ABI soversion rather than only resolving through the unversioned symlink. - Struct layout drift. The Python and Java config/result structs were
missing
continuation_backend, the CVODE policy fields, andcvode_method_active/cvode_n_switches, so they mis-sized against a rebuilt library. They match the C header again, and a runtime ABI test compares JNA field offsets to the native layout. - Windows library discovery tries each candidate directory and registers its parent for dependent DLLs, so a local build tree with copied SUNDIALS dependencies loads.
- Profile mode 1 returns
SOLVSRK_FAIL_BAD_ARGinstead of segfaulting whenresult->y_finalis NULL, and its sub-window diagnostics (cvode_steps,cvode_n_rhs,cvode_wall_s) are now totals across sub-windows instead of the last window only.
Packaging
- One wheel per platform instead of one per interpreter. The Python binding
is ctypes and links against no CPython ABI, so 2.5.0 ships five
py3-none-<platform>wheels — Linux x86_64 and aarch64 (manylinux_2_28), macOS arm64 and x86_64, Windows AMD64 — each valid for every supported Python 3 release. - SUNDIALS is bundled inside the wheel on all five platforms; no system install is required.
- For C consumers:
solvsrk::solvsrk_staticis now an exported CMake target carrying the required define, andfind_package(solvsrk)no longer requires a SUNDIALS CMake config when the SUNDIALS paths were baked into the build. In that mode the package is not relocatable and reports missing libraries by name instead of deferring to a link error.
Upgrading
pip install --force-reinstall path/to/solvsrk-2.5.0-py3-none-<platform>.whl
python -m solvsrk # prints machine code and license state
python -m solvsrk activate ~/Downloads/solvsrk.lic # v3 file, reissuedSee the version list.