Git Product home page Git Product logo

diffsol's People

Contributors

martinjrobins avatar mhovd avatar siel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

diffsol's Issues

inplace update of jacobians

the NonLinearOp and LinearOp have a jacobian function which returns a matrix

fn jacobian(&self, x: &Self::V, t: Self::T) -> Self::M

This requires creating a new matrix everytime the jacobian is recalculated. Need an "inplace" version that can update an existing jacobian.

This will require additions to the Matrix trait to allow for mutation of existing matrices

related to #6 and #7

add optional stop time to step

Add an optional stop time to step to halt the solve at this time point (e.g for time-based events, see #42 )

fn step(&mut self, stop_time: Option<Eqn::T>) -> Result<()>;

replace take_state with set_state

at the moment OdeEquations has the following function for take state:

/// Take the current state of the solver, if it exists, returning it to the user. This is useful if you want to use this
/// state in another solver or problem. Note that this will unset the current problem and solver state, so you will need to call
/// `set_problem` again before calling `step` or `solve`.
fn take_state(&mut self) -> Option<OdeSolverState<Eqn::V>>;

However, when you set the state again with set_problem, there is a lot of unnecessary initialisation done, e.g. setting the initial timestep (see #34 ).

Option A:

I'm thinking of replacing take_step by a set_state, which would allow a user to set the internal OdeSolverState, while keeping the initialisation of other internal variables to a minimum

fn set_state(&mut self, new_state: &Eqn::V);

So user code would be:

let mut new_state = solver.state().clone();
new_state[0] += 1.0;
solver.set_state(&new_state);

Option B:

An alternative is to keep take_step, and add set_state that takes ownership of the vector, like so

fn set_state(&mut self, new_state: Eqn::V);

So then in user code you have:

let mut state = solver.take_state().unwrap();
state[0] += 1.0;
solver.set_state(state);

This allows you to mutate the state in-place so you don't have to have two versions of the state vector

make mass matrix truly optional

atm the mass matrix is sorta optional in that it defaults to the identity matrix if not provided, but to be more explicit and allow algorithms to do efficiencies in the case of an identity mass matrix this should be truely optional, so the OdeEquations trait goes from

pub trait OdeEquations {
    /// returns the mass matrix `M` as a [LinearOp]
    fn mass(&self) -> &Rc<Self::Mass>;

to

pub trait OdeEquations {
    /// returns the mass matrix `M` as a [LinearOp]
    fn mass(&self) -> Option<&Rc<Self::Mass>>;

don't initialise step size if not required

When set_problem is called for the solvers they calculate an initial step size. If the solve is a continuation of a previous solve this might not be required, so there should be an option to disable this

improve handling of identity or constant mass matrix

mass matrix currently implemented via an implicit function $Mv$, for a large majority of cases $M=I$ or $M$ is constant, so I think we need to factor in efficiencies for these cases

  • Should the solvers be aware if $M=I$ or not and act accordingly? Or should the efficiencies be implemented in OdeEquations?
  • for the latter above, should OdeEquations provide a gemv style function for the implicit solvers to use?
  • and an $M^{-1}$ function for the explicit solvers?

events

There needs to be a way for the user to specify events at which to terminate the solve. This could be another function in the OdeEquations trait that writes to a vector given the current state x and time t. The solver will terminate if any of the elements in that vector cross zero

use VectorView and VectorViewMut instead of &Vector and &mut Vector

atm the main call function for NonLinearOp is:

pub trait NonLinearOp: Op {
    /// Compute the operator at a given state and time.
    fn call_inplace(&self, x: &Self::V, t: Self::T, y: &mut Self::V);
    ...

To make this more flexible, we should use VectorView and VectorViewMut instead, ie:

pub trait NonLinearOp: Op {
    /// Compute the operator at a given state and time.
    fn call_inplace(&self, x: Self::VView, t: Self::T, y: Self::VViewMut);
    ...

This allows algorithms to call these functions with views rather than references to owned vectors. One usecase for this is to concatentate solves with varying parameters into a larger statevector

refactor OdeSolverMethod to improve state ownership

Its a bit confusing atm who owns the solver state, I propose the API is refactored thus:

pub trait OdeSolverMethod<Eqn: OdeEquations> {

    fn problem(&self) -> Option<&OdeSolverProblem<Eqn>>;

    // solver now takes ownership of the state, which has been initialised by the user
    fn set_problem(&mut self, state: OdeSolverState<Eqn::M>, problem: &OdeSolverProblem<Eqn>);

    // solver can return a ref to the state for reading
    fn state(&self) -> Option<&OdeSolverState<Eqn>>

    // or you can take ownership of the state for editing, or initialising another problem/solver
    // note that `set_problem` must be called again after this, or subsequent `step` calls
    // will fail
    fn take_state(&mut self) -> Option<OdeSolverState<Eqn>>

    fn step(&mut self) -> Result<()>;
    fn interpolate(&self, t: Eqn::T) -> Eqn::V;
    fn solve(&mut self, problem: &OdeSolverProblem<Eqn>, t: Eqn::T) -> Result<Eqn::V> {
        let state = OdeSolverState::new(problem);
        self.set_problem(state, problem);
        while state.t <= t {
            self.step()?;
        }
        Ok(self.interpolate(t))
    }

    fn make_consistent_and_solve<RS: NonLinearSolver<FilterCallable<OdeRhs<Eqn>>>>(
        &mut self,
        problem: &OdeSolverProblem<Eqn>,
        t: Eqn::T,
        root_solver: &mut RS,
    ) -> Result<Eqn::V> {
        let state = OdeSolverState::new_consistent(problem, root_solver)?;
        self.set_problem(state, problem);
        while state.t <= t {
            self.step()?;
        }
        Ok(self.interpolate(t))
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.