Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++ Implementation of the Tau Hybrid solver #557

Merged
merged 100 commits into from
Jul 20, 2021
Merged

C++ Implementation of the Tau Hybrid solver #557

merged 100 commits into from
Jul 20, 2021

Conversation

jtcooper10
Copy link
Collaborator

@jtcooper10 jtcooper10 commented Jun 25, 2021

Initial Implementation

This PR only includes the base C++ solver. None of the additional SBML features (rate rules, events, etc.) have been implemented, making this an MVP as it is not yet up to feature parity with the Python implementation. Each additional SBML feature will likely be included as its own PR.

  • Adds TauHybridCSolver class to Python
  • Adds tau_hybrid_cpp_solver directory to C++ solver base
  • Adds rudimentary template_opts.h implementation to support solver-specific arguments
    • This was included to prevent non-Hybrid options from being required on every solver
  • Adds TauHybridCSolver to C++ solver tests, both variable and non-variable
  • Separates Tau initialization/selection methods in C++ into a separate file, to share between Tau-leaping and hybrid solvers

Hybrid Data Structures

Extended data structures specific to the Tau Hybrid solver were added to C++. This is to prevent requiring hybrid-specific runtime state from being applied directly to the base Species, Reaction, and Model classes.

Compile Times

As with the ODE C++ solver, the compile step is slow and may give the appearance of poor performance compared to its Python equivalent. The majority of the compile time is due to the Sundials compile dependency, and may be mitigated in the future by caching.

Species Mode Support

Assigning a discrete/stochastic mode value to a species is properly reflected by the C++ solver. This is achieved with the template_opts.h "optional" header described above.

mdip226 and others added 30 commits March 1, 2021 13:59
- Creates platformutils.py, for putting platform-specific wrapper functions
- Adds Popen wrapper (`open_simulation`) to "inject" platform-specific kwargs
- Extracts the `sim_kill` lambda into a separate helper function
- Adds new class in platformutils: `SimulationReader`
- Handles reading the output of simulation in background thread
- Optionally handles timeout
- Define signal handler info as macros
- Use `INTERRUPT_*` macros as type definitions
- Use `SET_INTERRUPT_HANDLER` as a wrapper around signal installer
@jtcooper10 jtcooper10 requested review from mdip226 and seanebum July 1, 2021 17:54
Copy link
Collaborator

@ethangreen-dev ethangreen-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only recommendation is a format pass through the C++ source. This looks fantastic, great work!

Copy link
Contributor

@BryanRumsey BryanRumsey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simulations with multiple trajectories are generating constant/near constant results after the first trajectory.

Error occurs with the following models:

  • Michaelis Menten
  • Opiod
  • Tyson 2 State Oscillator

NumPy Tau Hybrid Results for Michaelis Menten

Unknown

Tau Hybrid C Results for Michaelis Menten

Unknown-2

Toogle Switch model is returning strictly deterministic results when they should be stochastic

NumPy Tau Hybrid Results

Unknown-3

Tau Hybrid C Solver Results

Unknown-4

Specifying >1 for `number_of_trajectories` was resulting in constant output at best, integration errors at worst.
- Supply simulation seed to prevent deterministic behavior
- Back up `y0` and reset integrator completely on each trajectory
- Explicitly initialize partition modes for each species
Species would often get "stuck" on deterministic output. This was due to propensities not being initialized on the first run.
- Add propensity computation to beginning of solver loop
- Implement `validate` function to set integrator status based on CVODE return code
- Stop trajectory if the timestep is too small
- Fixes issue where fractional initial populations have unexpected results (i.e. Lotka-Volterra model)
@jtcooper10
Copy link
Collaborator Author

Included update to ODE solver to use double rather than unsigned int for initial populations. Should fix issue where real-valued initial populations get truncated by ODE solvers.

@ethangreen-dev ethangreen-dev mentioned this pull request Jul 13, 2021
- Revert `SimulationState` enum properties to not use bit packing
- Fix incorrect computation of standard deviation, which caused unexpected output
- Fix CVODE error caused by uninitialized time value
- Limits the number of sequential invalid states from exceeding 1000
  - Prevents "occasionally invalid" output from terminating the simulation
- Allow `tau_tol` to be properly accepted as argument
@ethangreen-dev ethangreen-dev merged commit 97dbd57 into develop Jul 20, 2021
@seanebum seanebum deleted the hybrid-c branch January 11, 2022 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

C++ solvers display incorrect results when real-valued initial populations are used on the model.
5 participants