Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Parameters

The fundamental trait that diffsol uses to specify a mathematical operation is Op. This trait defines the number of parameters in your ODE model via Op::nparams. When specifying your parameters with DiffSL or Rust closures, you are largely tied into a specific notion of a parameter being any input parameter of your model that you want to change between solves. However, if you use a custom struct and the OdeEquations trait, you have much more flexibility about defining and changing the parameters of your model, as we'll explore below.

What is a "parameter"

A parameter of your model does not continuously vary with time, like the state variables, but is instead constant over the duration of an individual solve. If you were writing your equations using a custom struct, you might have one or more model parameters as fields on that struct, for example:

struct MyModel {
  pub parameter_a: f64,
  pub parameter_b: f64,
}

These parameters could then be used in your implementation of NonLinearOp, or any other diffsol trait. However, it is entirely up to you if you report these to diffsol as parameters or not. You could set nparams in the Op trait to 2 and implement the set_params and get_params methods to set/get both parameter_a and parameter_b, or you can set nparams to 0 and just set parameter_a and parameter_b manually via their pub fields on the struct, its up to you. This also gives you flexibility to use parameter types that ain't supported by diffsol, for example int, bool, or arbitrary structs.

struct MyModel {
  pub parameter_a: f64,
  pub parameter_b: Hashmap<String, f64>,
}

When to tell diffsol about a parameter

There are a few cases where you do need to report your parameter to diffsol, these are:

  • You want to exclusively set/get parameters via the OdeEquations trait methods set_params and get_params. For example you might want to write generic code that can work over any set of equations.
  • You want to calculate the gradient of your solution with respect to that parameter using a forward sensitivity solver.
  • You want to calculate the gradient of a loss function with respect to that parameter using an adjoint sensitivity solver.

This decision can be made on a per-parameter basis. You can select which parameters of your model you want to tell diffsol about, and which parameters you don't. Just make sure you are consistent on the number and ordering of the parameters that you are reporting to diffsol, when you implement get/set_params and the *Sens traits.

Varying parameters

The rust borrow checker governs any change to your model. Any change in a parameter of your model, whether its a parameter you have reported to diffsol or otherwise, requires a mutation of your OdeEquations struct. Each solver that you create takes a reference to OdeSolverProblem, and therefore to your custom OdeEquations struct, so you won't be able to mutate it until you drop all the solvers with that reference. Given any instance of OdeSolverProblem, you can get a mutable reference to you custom OdeEquations struct using OdeSolverProblem::eqn_mut.