Solver

class cubie.batchsolving.solver.Solver(system: BaseODE, algorithm: str | None = None, lineinfo: bool | None = None, step_control_settings: Dict[str, object] | None = None, algorithm_settings: Dict[str, object] | None = None, system_settings: Dict[str, object] | None = None, output_settings: Dict[str, object] | None = None, memory_settings: Dict[str, object] | None = None, loop_settings: Dict[str, object] | None = None, time_logging_level: str | None = None, auto_performance: bool | None = None, **kwargs: Any)[source]

Bases: DerivedValues

User-facing interface for solving batches of ODE systems.

Parameters:
  • system – System model containing the ODEs to integrate.

  • algorithm – Integration algorithm to use. Defaults to "euler".

  • lineinfo – Compile all kernels and device functions with source-line correlation data for profilers such as Nsight Compute. None defers to the CUBIE_LINEINFO environment variable (default off). Changing it later via update() triggers a rebuild.

  • step_control_settings – Explicit controller configuration that overrides solver defaults.

  • algorithm_settings – Explicit algorithm configuration overriding solver defaults.

  • system_settings – Explicit system configuration; each key may also be a keyword argument.

  • output_settings – Explicit output configuration overriding solver defaults. Individual selectors such as save_variables or index-based parameters may also be supplied as keyword arguments.

  • memory_settings – Memory configuration; each key may also be a keyword argument. Host result arrays above 80% of system RAM are disk-backed in the cache root. An idle solver’s completed device buffers are freed when another solver faces a genuine VRAM shortage; the evicted solver reallocates on its next solve.

  • loop_settings – Explicit loop configuration overriding solver defaults. Keys such as save_every and summarise_every may also be supplied as loose keyword arguments.

  • time_logging_level (str or None, default='default') – Time logging verbosity level. Options are ‘silent’, ‘default’, ‘verbose’, ‘debug’, None, or ‘None’ to disable timing.

  • auto_performance (bool, default=True) – Set buffer locations, loop unrolling and launch residency from your hardware and CuBIE’s best guess. Never overrides explicit unroll_* or *_location arguments. Turning it off returns the derived values to their defaults.

  • **kwargs – Any setting named in SolverSettings.

given

Settings that the user explicitly set, a SolverSettings.

effective

Settings that the solver is using, including given and the ones resolved from it, an EffectiveSettings.

Notes

Instances coordinate batch grid construction, kernel configuration, and driver interpolation so that solve() orchestrates a complete GPU integration run.

When specifying variables:

  • None means “use all” (default behavior for both states and observables)

  • [] (empty list) means “explicitly no variables”

  • When both labels and indices are provided, their union is used

_check_duration(duration: float) → None[source]

Raise ValueError if the solver would save nothing in duration.

Parameters:

duration – Integration time of the solve.

_host_result(nan_error_trajectories: bool) → SolveResult[source]

Wait for the launched host solve and return its result.

Parameters:

nan_error_trajectories – Overwrite the runs with nonzero status codes with NaN.

Returns:

Result owning the solve’s host buffers.

Return type:

SolveResult

_solve_spec() → SolveSpec[source]

Return a SolveSpec built from the current settings.

property active_outputs: ActiveOutputs

Expose active outputs from the kernel.

property algorithm

Return the configured algorithm name.

property atol: float | None

Return the absolute tolerance for adaptive controllers.

property cache_dir: Path | None

Custom cache directory, or None for default location.

property cache_enabled: bool

Whether file-based caching is enabled.

calibrate(initial_values: None | ndarray | Dict[str, Any] = None, parameters: None | ndarray | Dict[str, Any] = None, drivers: DriverSamples | None = None, duration: float = 1.0, settling_time: float = 0.0, t0: float = 0.0, grid_type: str = 'verbatim', apply: bool = True, verbose: bool = True, auto_size: bool = True, waves: int = 5, target_ms: float = 20.0, max_parallel: int = 4, fix_constant_parameters: bool = True) → CalibrationResult[source]

Race solver configurations and pick the fastest.

Compare a range of integration algorithms and settings (preconditioners, solver types, smoothed error and prediction), returning a winner and a ranked list based on solve time and solver-failure count. Can run for up to an hour on large systems, but takes care of a lot of trial/error. Candidates inherit this solver’s tolerances and output configuration.

Parameters:
  • initial_values – A typical initial-values grid that you’ll solve over; aim for at least 32768 combined initial-value/parameter sets to test the solver at full capacity. Accepts dictionaries mapping state names to values for grid construction, or pre-built arrays in (n_states, n_runs) format. None starts every run from the system’s default initial values.

  • parameters – Parameter values for each run, as in solve().

  • drivers – DriverSamples replacing the solver’s configured samples.

  • duration – Total integration time. Default is 1.0.

  • settling_time – Warm-up period before recording outputs. Default 0.0.

  • t0 – Initial integration time. Default 0.0.

  • grid_type – Strategy for constructing the integration grid from inputs. Only used when dict inputs trigger grid construction.

  • apply – Apply the winner’s configuration to this solver when True (default). Pass False to only report.

  • verbose – Print per-candidate progress lines. Default True.

  • auto_size – Race a batch sized for target_ms solves at your duration; False races your batch. Default True.

  • waves – Waves of the most concurrent candidate the batch starts at. Default 5.

  • target_ms – Kernel milliseconds per timed solve the batch is sized for. Default 20.0.

  • max_parallel – Maximum compilations to run in parallel.

  • fix_constant_parameters – Compile in every dict entry and every row of a full-height parameter array that holds one value, as solve() does, so the candidates race the kernel your solves use. Default True.

Returns:

Winner, ranking, and every candidate measurement. A candidate that fails to build or integrate is reported as dropped with its error message.

Return type:

CalibrationResult

Raises:

ValueError – No driver samples for a driven system; waves under 1; target_ms under 10 or not finite.

property chunks

Return the number of chunks used in the last run.

close(shutdown_timeout: float | None = None) → None[source]

Release GPU resources after pending transfers finish.

Parameters:

shutdown_timeout – Maximum seconds to wait. None waits until transfers finish.

compile(parameters: None | ndarray | Dict[str, float | ndarray] = None, fix_constant_parameters: bool = True, optimize_candidates: bool = False, max_parallel: int = 4, **kwargs: Any) → None[source]

Apply settings and compile the kernel for these parameters.

Parameters:
  • parameters – Parameter values as in solve(). Compile the kernel that a solve with the same parameters would use.

  • fix_constant_parameters – If False, leave any parameters that have been given the same value for all runs in the parameters array that the GPU sees. Defaults to True, so that constant parameters are compiled into the code and the whole thing runs faster. Set it False if you are changing a single value per batch frequently, and the compile time is long enough to make it annoying.

  • optimize_candidates – Also compile the candidate kernels for optimize().

  • max_parallel – Maximum compilations to run in parallel.

  • **kwargs – Options forwarded to update().

property compile_flags: OutputCompileFlags

Expose output compile flags from the kernel.

convert_output_labels(output_settings: Dict[str, Any]) → None[source]

Convert variable labels to indices.

Parameters:

output_settings – Output configuration kwargs. Entries used are save_variables, summarise_variables, saved_state_indices, saved_observable_indices, summarised_state_indices, and summarised_observable_indices.

Raises:

ValueError – If variable labels are not recognized by the system.

copy() → Solver[source]

Return a copy: same given settings, current log level.

property device_initial_values

Device initial values of the last run; raise if chunked.

property device_iteration_counters

Expose the device buffer of iteration counters.

property device_observable_summaries

Expose the device buffer of observable summaries.

property device_observables

Expose the device buffer of observable outputs.

property device_parameters

Device parameters of the last run; raise if chunked.

property device_state

Expose the device buffer of state outputs.

property device_state_summaries

Expose the device buffer of state summaries.

property device_status_codes

Expose the device buffer of status codes.

property driver_coefficients

Expose driver interpolation coefficients.

property driver_interpolator: ArrayInterpolator

The kernel-owned driver interpolator.

property dt: float | None

Return the fixed-step size or None for adaptive controllers.

property dt_max: float | None

Return the maximum step size for adaptive controllers.

property dt_min: float | None

Return the minimum step size for adaptive controllers.

property duration

Return the requested integration duration.

property fixed_parameter_values: Dict[str, float]

Values compiled into the kernel, keyed by parameter name.

get_observable_indices(observable_labels: List[str] | None = None) → ndarray[source]

Return indices for the specified observables.

Parameters:

observable_labels – Labels of observables to query. None returns indices for all observables.

Returns:

Integer indices corresponding to the requested observables.

Return type:

ndarray

get_state_indices(state_labels: List[str] | None = None) → ndarray[source]

Return indices for the specified state variables.

Parameters:

state_labels – Labels of states to query. None returns indices for all states.

Returns:

Integer indices corresponding to the requested states.

Return type:

ndarray

property initial_values

Expose initial values array used in the last run.

property input_variables: List[str]

List all input variable labels.

is_given(name: str) → bool[source]

Return whether the setting name was given.

property iteration_counters

Expose iteration counters at each save point.

property mem_proportion

Return the proportion of global memory allocated.

property memory_manager

Return the associated memory manager instance.

property num_runs

Expose the number of runs in the last solve.

property observable_summaries

Expose observable summary outputs.

property observables

Expose latest observable outputs.

optimisation_candidates(force: bool = False) → Tuple[Dict[str, Any], ...][source]

Return optimisation candidates; force frees the given keys.

optimize(initial_values: None | ndarray | Dict[str, Any] = None, parameters: None | ndarray | Dict[str, Any] = None, drivers: DriverSamples | None = None, duration: float = 1.0, settling_time: float = 0.0, t0: float = 0.0, grid_type: str = 'verbatim', apply: bool = True, verbose: bool = True, force: bool = False, auto_size: bool = True, waves: int = 5, target_ms: float = 20.0, max_parallel: int = 4, fix_constant_parameters: bool = True) → OptimizeResult[source]

Time placement, unrolling and launch options; keep the fastest.

Settings you gave, or an earlier optimize applied, stay fixed unless force=True.

Parameters:
  • initial_values – Dict of state names to values, or an (n_states, n_runs) array. None starts every run from the system’s default initial values.

  • parameters – Parameter values for each run, as in solve().

  • drivers – DriverSamples replacing the solver’s configured samples.

  • duration – Integration time of your solves. Default 1.0.

  • settling_time – Warm-up period before outputs are recorded. Default 0.0.

  • t0 – Initial integration time. Default 0.0.

  • grid_type – Grid strategy when dict inputs build a grid.

  • apply – Apply the fastest settings to this solver. Default True.

  • verbose – Print per-launch progress lines. Default True.

  • force – Vary the settings you gave or applied earlier too.

  • auto_size – True optimizes at an automatically selected batch size and duration to reduce runtime; False optimizes at your given batch size and duration. Default True.

  • waves – Waves of the launch with the most concurrent runs the auto_size batch starts at. Default 5.

  • target_ms – Kernel milliseconds per timed solve auto_size aims for. Default 20.0.

  • max_parallel – Maximum compilations to run in parallel.

  • fix_constant_parameters – Compile in every dict entry and every row of a full-height parameter array that holds one value, as solve() does, so the candidates race the kernel your solves use. Default True.

Returns:

Every launch, the best one, and the applied settings.

Return type:

OptimizeResult

Raises:

ValueError – waves under 1, or target_ms under 10 or not finite.

property output_array_heights

Expose output array heights from the kernel.

property output_length

Expose the flattened output length.

property output_types: List[str]

List active output types.

property output_variables: List[str]

List all output variable labels.

property parameter_legend: Dict[int, str]

Label of each row of the parameters array.

property parameters

Expose parameter array used in the last run.

property precision: type[float16] | type[float32] | type[float64] | dtype[float16] | dtype[float32] | dtype[float64]

Expose the kernel precision.

prepare_grid_arrays(initial_values: None | ndarray | Dict[str, float | ndarray] = None, parameters: None | ndarray | Dict[str, float | ndarray] = None, grid_type: str = 'verbatim') → Tuple[ndarray, ndarray][source]

Build state and parameter arrays to pass to solve().

Parameters:
  • initial_values – Initial state values as dictionaries mapping state names to value sequences, or arrays in (n_states, n_runs) format.

  • parameters – Parameter values for each run, as a dict mapping parameter names to values, or as an array. Every parameter you name gets a row, and a parameter given a single number gets a row with that number in every run. Every parameter you leave out uses its default value, so set a value as the default to compile it in.

  • grid_type – Strategy for constructing the grid. "combinatorial" produces all combinations while "verbatim" preserves column-wise pairings. Default is "verbatim".

Returns:

The (n_states, n_runs) initial values and the (n_given, n_runs) parameter values, one row per parameter given, in parameter name order.

Return type:

Tuple[ndarray, ndarray]

Examples

>>> inits, params = solver.prepare_grid_arrays(
...     {"x": [1, 2, 3]}, {"p": [0.1, 0.2]}, grid_type="combinatorial"
... )
>>> result = solver.solve(inits, params)  # Uses fast path
property rtol: float | None

Return the relative tolerance for adaptive controllers.

property sample_summaries_every: float | None

Return the interval between summary metric samples.

property save_counters: bool

Return whether iteration counters are saved.

property save_every: float | None

Return the interval between saved time-domain outputs.

property save_time: bool

Return whether time points are saved.

property saved_observable_indices

Expose saved observable indices.

property saved_observables

List saved observable labels.

property saved_state_indices

Expose saved state indices.

property saved_states

List saved state labels.

set_cache_dir(path: str | Path) → None[source]

Set a custom cache directory for compiled kernels.

Parameters:

path – New cache directory path. Can be absolute or relative.

Notes

Invalidates the current cache, causing a rebuild on next access.

set_swept_parameters(names: Sequence[str]) → None[source]

Set which parameters will change over the runs of a batch.

Call this before you pass solve() an array that holds only the varying parameters; a dict or a full-height array sets the swept parameters itself. Names can be in any order, but the array you pass must have its rows in parameter-name order. The solver compiles every other parameter in at its default.

Parameters:

names – Names of the parameters that vary over the runs of a batch.

Raises:
  • KeyError – If a name is not a parameter of the system.

  • ValueError – If a name repeats.

set_verbosity(verbosity: str | None) → None[source]

Set the time logging verbosity level.

Parameters:

verbosity (str or None) – New verbosity level. Options are ‘default’, ‘verbose’, ‘debug’, None, or ‘None’.

Notes

Updates the global time logger verbosity. This affects all timing events across the entire CuBIE package.

settings_dict(for_new_process: bool = False) → Dict[str, Any][source]

Return the given settings with the logger’s current level.

Parameters:

for_new_process – Leave out this process’s memory manager.

solve(initial_values: None | ndarray | Dict[str, float | ndarray] = None, parameters: None | ndarray | Dict[str, float | ndarray] = None, drivers: DriverSamples | None = None, duration: float = 1.0, settling_time: float = 0.0, t0: float = 0.0, blocksize: int | None = None, grid_type: str = 'verbatim', nan_error_trajectories: bool = True, on_device: bool = False, fix_constant_parameters: bool = True, **kwargs: Any) → SolveResult | DeviceSolveResult[source]

Solve a batch initial value problem.

Parameters:
  • initial_values – Initial state values for each integration run. Accepts dictionaries mapping state names to values for grid construction, or pre-built arrays in (n_states, n_runs) format for fast-path execution. Device arrays (CuPy or Numba) are used in place with no host-to-device transfer; they must already match the system precision. None starts every run from the system’s default initial values.

  • parameters – Parameter values for each run, as a dict mapping parameter names to values, or as an array. The solver uses the default value of every parameter you leave out of a dict. Give an array either one row per parameter in the system, or one row per swept parameter in parameter name order, in which case the solver uses the default value of every other parameter. For a dict or an array with one row per parameter, any parameters given as a single value will be removed from the array and compiled into the code; see fix_constant_parameters. Pass None, an empty dict, or an empty 1D array to use the default parameters for all runs.

  • drivers – DriverSamples replacing the solver’s configured samples.

  • duration – Total integration time. Default is 1.0.

  • settling_time – Warm-up period before recording outputs. Default 0.0.

  • t0 – Initial integration time. Default 0.0.

  • blocksize – CUDA block size for this launch; None lets the solver pick.

  • grid_type – Strategy for constructing the integration grid from inputs. Only used when dict inputs trigger grid construction.

  • nan_error_trajectories – When True (default), trajectories with nonzero status codes are automatically set to NaN, making failed runs easy to identify and exclude from analysis. When False, all trajectories are returned unchanged. Ignored when on_device is True.

  • on_device – When True, skip the device-to-host copy of the output arrays and return a DeviceSolveResult holding the solver’s device output buffers plus the CUDA stream the solve ran on; see Notes. Default False.

  • fix_constant_parameters – If False, leave any parameters that have been given the same value for all runs in the parameters array that the GPU sees. Defaults to True, so that constant parameters are compiled into the code and the whole thing runs faster. Set it False if you are changing a single value per batch frequently, and the compile time is long enough to make it annoying.

  • **kwargs – Additional options forwarded to update(). See “Optional Arguments” in the docs for possibilities. Any system parameters passed as kwargs are rejected, as they should be in the parameters argument.

Returns:

SolveResult owning the solve’s host output buffers — nothing is copied. Keep it alive while its data is needed: once it is garbage collected the solver reuses the buffers on its next run. as_numpy, as_numpy_per_summary, and as_pandas build RAM representations on demand; disk-backed results release their spill files on close() or context exit. DeviceSolveResult when on_device is True.

Return type:

SolveResult or DeviceSolveResult

Notes

Input type detection determines the processing path:

  • Dictionary inputs trigger grid construction via BatchInputHandler

  • Pre-built numpy arrays with correct shapes skip grid construction for improved performance

  • Device arrays are used in place: no grid construction and no host-to-device transfer

  • device_initial_values/device_parameters re-run the previous solve’s inputs with nothing uploaded

When GPU memory is insufficient for the full batch, arrays are automatically chunked along the run axis.

on_device=True returns without synchronizing: buffer contents are valid once the returned stream is synchronized, and the next solve() on this solver overwrites them. A chunked run raises ValueError.

property solve_info: SolveSpec

SolveSpec for the current settings.

property state

Expose latest state outputs.

property state_summaries

Expose state summary outputs.

property status_codes

Expose integration status codes.

property status_messages

Decode nonzero run status codes into named result flags.

Returns:

Mapping from run index to the CUBIE_RESULT_CODES member names set in that run’s status word; successful runs are omitted.

Return type:

dict[int, list[str]]

property stream

Return the CUDA stream used by this solver.

property stream_group

Return the CUDA stream group assigned to this solver.

property summaries_length

Expose the flattened summary length.

property summarise_every: float | None

Return the summary window; None summarises once at the end.

property summarised_observable_indices

Expose summarised observable indices.

property summarised_observables

List summarised observable labels.

property summarised_state_indices

Expose summarised state indices.

property summarised_states

List summarised state labels.

property summary_legend_per_variable: dict[int, str]

Expose summary legends keyed by variable index.

property summary_unit_modifications: dict[int, str]

Expose summary unit modifications keyed by variable index.

property swept_parameters: Tuple[str, ...]

Names of the swept parameters, sorted by name.

Pass a parameters array with one row per name, in this order.

property system: BaseODE

Return the underlying ODE system instance.

property system_sizes

Expose cached system size metadata.

property t0: float

Return the starting integration time.

update(updates_dict: Dict[str, Any] | None = None, silent: bool = False, **kwargs: Any) → Set[str][source]

Record the given settings, resolve them and update the kernel.

None makes a setting not given and returns it to its default.

Parameters:
  • updates_dict – Setting names to new values; a dict value is a settings group.

  • silent – Ignore unknown names instead of raising.

  • **kwargs – Further updates.

Returns:

The recognised names.

Return type:

Set[str]

Raises:

KeyError – Unknown names when not silent.

update_memory_settings(updates_dict: Dict[str, Any] | None = None, silent: bool = False, **kwargs: Any) → Set[str][source]

Update the memory settings.

Parameters:
  • updates_dict – Memory setting names to new values; mem_proportion=None selects the automatic limit.

  • silent – Ignore unknown names instead of raising.

  • **kwargs – Further updates.

Returns:

The recognised names.

Return type:

Set[str]

Raises:

KeyError – Unknown names when not silent.

property warmup

Return the warm-up period length.