srenevey / ode-solvers

Numerical methods to solve ordinary differential equations in Rust.
BSD 3-Clause "New" or "Revised" License
64 stars 26 forks source link

Allow the state to be mut #16

Closed Siel closed 1 year ago

Siel commented 1 year ago

In some scenarios (Like Pharmacometrics) bolus doses are represented as impulses into the 'compartment' of interest. To make it work it is necessary to modify the state based on the time of the dose.

i.e:

impl ode_solvers::System<State> for c1_pk {
    fn system(&self, t: Time, y: &mut State, dy: &mut State) {

        dy[0] = -self.ka*y[0];
        dy[1] = self.ka*y[0] - self.ke*y[1];

        if (t-5.0).abs() < 1.0e-10 {
            y[0] = y[0]+500.0;
        }

    }
}

represents a dose of 500mg at time 5.0.

My changes allow the state to be mut, all examples and tests still work.

Siel commented 1 year ago

image

SoutrikBandyopadhyay commented 1 year ago

I think forcing the state to be 'mut' by default may cause problems for systems where the state doesn't have to be mut. I think, we could create a new trait "SystemMut" where the function

fn system(&self, x: f64, y: &V, dy: &mut V);

could be

fn system(&self, x:f64, y: &mut V, dy: &mut V);

In this way, the two approaches could be separated without causing confusion.

Siel commented 1 year ago

That is an option, the problem is that there are a lot of different options regarding mut/non-mut, for example issue #15 is asking for a mut reference to self (and there are some scenarios in which that's ok).

In my opinion, there are some alternatives. One is allowing everything to be mut and hoping the users behave Another one is to find a way to define a trait that allows its parameters to be defined as mut/non-mut (don't know if that is possible). And the last one is to define a trait for every different combination.