cubie.systemmodels

System models package for ODE systems with CUDA support.

This package provides classes and utilities for defining and solving ordinary differential equation systems on CUDA devices.

class cubie.systemmodels.Decays(precision=<class 'numpy.float64'>, **kwargs)[source]

Bases: GenericODE

Exponential decay system for testing purposes.

A system where each state variable decays exponentially at a rate proportional to its position. Observables are the same as state variables * parameters (coefficients) + index.

Parameters:
  • precision (numpy.dtype, optional) – Data type for calculations, by default np.float64.

  • **kwargs (dict) – Must contain ‘coefficients’ key with list of decay coefficients.

Notes

If coefficients = [c1, c2, c3], then the system will have three state variables x0, x1, x2, and:

dx[0] = -x[0]/1, dx[1] = x[1]/2, dx[2] = x[2]/3

obs[0] = dx[0]*c1 + 1 + step_count, obs[1] = dx[1]*c2 + 2 + step_count, obs[2] = dx[2]*c3 + 3 + step_count.

Really just exists for testing.

__init__(precision=<class 'numpy.float64'>, **kwargs)[source]

Initialize the decay system.

Parameters:
  • precision (numpy.dtype, optional) – Data type for calculations, by default np.float64.

  • **kwargs (dict) – Must contain ‘coefficients’ key with list of decay coefficients.

build()[source]

Build the CUDA device function for the decay system.

Returns:

Compiled CUDA device function implementing the decay dynamics.

Return type:

function

correct_answer_python(states, parameters, drivers)[source]

Python testing function.

Do it in python and compare results with CUDA implementation.

Parameters:
Returns:

A tuple containing (dxdt, observables) arrays.

Return type:

tuple of numpy.ndarray

class cubie.systemmodels.GenericODE(initial_values=None, parameters=None, constants=None, observables=None, default_initial_values=None, default_parameters=None, default_constants=None, default_observable_names=None, precision=<class 'numpy.float64'>, num_drivers=1, **kwargs)[source]

Bases: CUDAFactory

Template class for a system of ODEs.

This class is designed to be subclassed for specific systems so that the shared machinery used to interface with CUDA can be reused. When subclassing, you should overload the build() and correct_answer_python() methods to provide the specific ODE system you want to simulate.

Parameters:
  • initial_values (dict, optional) – Initial values for state variables.

  • parameters (dict, optional) – Parameter values for the system.

  • constants (dict, optional) – Constants that are not expected to change between simulations.

  • observables (dict, optional) – Observable values to track.

  • default_initial_values (dict, optional) – Default initial values if not provided in initial_values.

  • default_parameters (dict, optional) – Default parameter values if not provided in parameters.

  • default_constants (dict, optional) – Default constant values if not provided in constants.

  • default_observable_names (dict, optional) – Default observable names if not provided in observables.

  • precision (numpy.dtype, optional) – Precision to use for calculations, by default np.float64.

  • num_drivers (int, optional) – Number of driver/forcing functions, by default 1.

  • **kwargs (dict) – Additional arguments.

Notes

If you do implement a correct_answer_python() method, then you can subclass the SystemTester class in tests/systemmodels/SystemTester.py and overload system_class with your ODE class name. The generate_system_tests function can then generate a set of floating-point and missing-input tests to see if your system behaves as expected.

Most systems will contain a default set of initial values, parameters, constants, and observables. This parent class does not contain them, but instead can be instantiated with a set of values of any size, for testing purposes. The default values provide a way to both set a default state and to provide the set of modifiable entries. This means that a user can’t add in a state or parameter when solving the system that ends up having no effect on the system.

__init__(initial_values=None, parameters=None, constants=None, observables=None, default_initial_values=None, default_parameters=None, default_constants=None, default_observable_names=None, precision=<class 'numpy.float64'>, num_drivers=1, **kwargs)[source]

Initialize the ODE system.

Parameters:
  • initial_values (dict, optional) – Initial values for state variables.

  • parameters (dict, optional) – Parameter values for the system.

  • constants (dict, optional) – Constants that are not expected to change between simulations.

  • observables (dict, optional) – Observable values to track.

  • default_initial_values (dict, optional) – Default initial values if not provided in initial_values.

  • default_parameters (dict, optional) – Default parameter values if not provided in parameters.

  • default_constants (dict, optional) – Default constant values if not provided in constants.

  • default_observable_names (dict, optional) – Default observable names if not provided in observables.

  • precision (numpy.dtype, optional) – Precision to use for calculations, by default np.float64.

  • num_drivers (int, optional) – Number of driver/forcing functions, by default 1.

  • **kwargs (dict) – Additional arguments.

build()[source]

Compile the dxdt system as a CUDA device function.

Returns:

Compiled CUDA device function for the ODE system.

Return type:

function

Notes

Assign dxdt contents into local scope by assigning before you define the dxdt function, as the CUDA device function can’t handle a reference to self.

property contants

Get the constants of the system.

Returns:

The constants of the system.

Return type:

SystemValues

correct_answer_python(states, parameters, drivers)[source]

Python version of the dxdt function for testing.

This function is used in testing. Overload this with a simpler, Python version of the dxdt function. This will be run in a python test to compare the output of your CUDA function with this known, correct answer.

Parameters:
Returns:

A tuple containing (dxdt, observables) arrays.

Return type:

tuple of numpy.ndarray

property dxdt_function

Get the compiled device function.

Returns:

The compiled CUDA device function.

Return type:

function

property initial_values

Get the initial values of the system.

Returns:

The initial values of the system.

Return type:

SystemValues

property num_constants

Get the number of constants.

Returns:

Number of constants.

Return type:

int

property num_drivers

Get the number of driver variables.

Returns:

Number of driver variables.

Return type:

int

property num_observables

Get the number of observable variables.

Returns:

Number of observable variables.

Return type:

int

property num_parameters

Get the number of parameters.

Returns:

Number of parameters.

Return type:

int

property num_states

Get the number of state variables.

Returns:

Number of state variables.

Return type:

int

property observables

Get the observables of the system.

Returns:

The observables of the system.

Return type:

SystemValues

property parameters

Get the parameters of the system.

Returns:

The parameters of the system.

Return type:

SystemValues

property precision

Get the precision of the system.

Returns:

The precision of the system (numba type, float32 or float64).

Return type:

numpy.dtype

set_constants(updates_dict=None, silent=False, **kwargs)[source]

Update the constants of the system. Does not relabel parameters to constants, just updates values already compiled as constants and forces a rebuild with new compile-time constants.

Parameters:
  • updates_dict (dict) – A dictionary of constant names and their

  • values. (new)

property sizes

Get system sizes.

Returns:

Dictionary of sizes (number of states, parameters, observables, constants, drivers) for the system.

Return type:

SystemSizes

update(updates_dict, silent=False, **kwargs)[source]

Update compile settings through the CUDAFactory interface.

Pass updates to compile settings through the CUDAFactory interface, which will invalidate cache if an update is successful.

Parameters:
  • updates_dict (dict) – Dictionary of updates to apply.

  • silent (bool, optional) – If True, suppress warnings about keys not found, by default False.

  • **kwargs (dict) – Additional update parameters.

Notes

Pass silent=True if doing a bulk update with other component’s params to suppress warnings about keys not found.

class cubie.systemmodels.ThreeChamberModel(initial_values=None, parameters=None, constants=None, observables=None, precision=<class 'numpy.float64'>, default_initial_values={'V_a': 1.0, 'V_h': 1.0, 'V_v': 1.0}, default_parameters={'E_a': 0.0133, 'E_h': 0.52, 'E_v': 0.0624, 'R_c': 0.008771929824561403, 'R_i': 0.012, 'R_o': 1.0, 'V_s3': 2.0}, default_constants={}, default_observable_names=['P_a', 'P_v', 'P_h', 'Q_i', 'Q_o', 'Q_c'], num_drivers=1, **kwargs)[source]

Bases: GenericODE

Three chamber cardiovascular model.

A cardiovascular model with three chambers (heart, arteries, veins) as described in Antoine Pironet’s thesis[1]_.

Parameters:
  • initial_values (dict, optional) – Initial values for state variables (V_h, V_a, V_v).

  • parameters (dict, optional) – Parameter values for the system (E_h, E_a, E_v, R_i, R_o, R_c, V_s3).

  • constants (dict, optional) – Constants that are not expected to change between simulations.

  • observables (dict, optional) – Observable values to track (P_a, P_v, P_h, Q_i, Q_o, Q_c).

  • precision (numpy.dtype, optional) – Precision to use for calculations, by default np.float64.

  • default_initial_values (dict, optional) – Default initial values if not provided in initial_values.

  • default_parameters (dict, optional) – Default parameter values if not provided in parameters.

  • default_constants (dict, optional) – Default constant values if not provided in constants.

  • default_observable_names (list, optional) – Default observable names if not provided in observables.

  • num_drivers (int, optional) – Number of driver/forcing functions, by default 1.

  • **kwargs (dict) – Additional arguments.

Notes

State variables: - V_h: Volume in heart - V_a: Volume in arteries - V_v: Volume in veins

Parameters: - E_h: Elastance of Heart (e(t) multiplier) - E_a: Elastance of Arteries - E_v: Elastance of Ventricles - R_i: Resistance of input (mitral) valve - R_o: Resistance of output (atrial) valve - R_c: Resistance of circulation (arteries -> veins) - V_s3: Total stressed blood volume

Observables: - P_a: Pressure in arteries - P_v: Pressure in veins - P_h: Pressure in heart - Q_i: Flow through input valve (Mitral) - Q_o: Flow through output valve (Aortic) - Q_c: Flow in circulation

References

[1] A. Pironet. “Model-Based Prediction of the Response to Vascular

Therapy.” Unpublished doctoral thesis, ULiège - Université de Liège, 2016.

https://hdl.handle.net/2268/194747

__init__(initial_values=None, parameters=None, constants=None, observables=None, precision=<class 'numpy.float64'>, default_initial_values={'V_a': 1.0, 'V_h': 1.0, 'V_v': 1.0}, default_parameters={'E_a': 0.0133, 'E_h': 0.52, 'E_v': 0.0624, 'R_c': 0.008771929824561403, 'R_i': 0.012, 'R_o': 1.0, 'V_s3': 2.0}, default_constants={}, default_observable_names=['P_a', 'P_v', 'P_h', 'Q_i', 'Q_o', 'Q_c'], num_drivers=1, **kwargs)[source]

Initialize the three chamber model.

Parameters:
  • initial_values (dict, optional) – Initial values for state variables.

  • parameters (dict, optional) – Parameter values for the system.

  • constants (dict, optional) – Constants that are not expected to change between simulations.

  • observables (dict, optional) – Observable values to track.

  • precision (numpy.dtype, optional) – Precision to use for calculations, by default np.float64.

  • default_initial_values (dict, optional) – Default initial values if not provided in initial_values.

  • default_parameters (dict, optional) – Default parameter values if not provided in parameters.

  • default_constants (dict, optional) – Default constant values if not provided in constants.

  • default_observable_names (list, optional) – Default observable names if not provided in observables.

  • num_drivers (int, optional) – Number of driver/forcing functions, by default 1.

  • **kwargs (dict) – Additional arguments.

Notes

num_drivers probably shouldn’t be an instantiation parameter, but rather a property of the system.

build()[source]

Build the CUDA device function for the three chamber model.

Returns:

Compiled CUDA device function implementing the three chamber cardiovascular dynamics.

Return type:

function

correct_answer_python(states, parameters, drivers)[source]

Python version of the three chamber model for testing.

More-direct port of Nic Davey’s MATLAB implementation.

Parameters:
  • states (numpy.ndarray) – Current state values [V_h, V_a, V_v].

  • parameters (numpy.ndarray) – Parameter values [E_h, E_a, E_v, R_i, R_o, R_c, V_s3].

  • drivers (numpy.ndarray) – Driver/forcing values [e(t)].

Returns:

A tuple containing (dxdt, observables) arrays.

Return type:

tuple of numpy.ndarray

Modules

SystemValues

systems

ODE system implementations with CUDA support.