Architecture Overview
This page describes CuBIE’s internal design patterns. Understanding these is essential for contributing new algorithms, metrics, or other components.
Component Ownership Tree
A typical solve involves the following hierarchy:
Solver
└── BatchSolverKernel
└── SingleIntegratorRun
├── IVPLoop
├── OutputFunctions
├── Algorithm step (e.g. ERKStep, FIRKStep)
└── Controller (PI, PID, Gustafsson)
Each component is a CUDAFactory subclass that
generates CUDA device functions.
The CUDAFactory Lifecycle
Every CUDA-generating component follows the same pattern:
Configuration. An
attrs-based config class (subclass ofCUDAFactoryConfig) holds compile-time settings. The config is set viasetup_compile_settings().Build. The
build()method generates and returns compiled device functions. Subclasses override this method.Cache. The result of
build()is cached. Subsequent accesses via thedevice_functionproperty return the cached result without rebuilding.Invalidation. When
update_compile_settings()is called with changed values, the cache is invalidated and the next property access triggers a rebuild.
Important
Never call build() directly. Always access compiled functions
through properties (e.g. device_function), which handle caching.
Config Hashing and Change Detection
_CubieConfigBase provides values_hash (a hex digest of the frozen
config) and values_tuple for comparison. update() returns two
sets: the names of fields that were requested to change and those that
actually changed. Only actual changes invalidate the cache.
MultipleInstanceCUDAFactory
Some components appear multiple times in the tree (e.g. one algorithm
step per stage in a multi-stage method). MultipleInstanceCUDAFactory
manages a collection of identically-typed factories distinguished by a
prefix string, so their buffers and settings don’t collide.
Attrs Conventions
Float attributes are stored with an underscore prefix (e.g.
_atol) and exposed via a property that casts throughself.precision.__init__signatures use the public name (no underscore).Validators from
cubie._utilsaccept both Python floats and NumPy scalar dtypes.Never add
aliasto underscored fields.