Skip to content

Commit

Permalink
deploy: 8bcfc60
Browse files Browse the repository at this point in the history
  • Loading branch information
martinjrobins committed Nov 30, 2024
1 parent b6f3a83 commit 743247f
Show file tree
Hide file tree
Showing 28 changed files with 1,611 additions and 1,517 deletions.
102 changes: 59 additions & 43 deletions choosing_a_solver.html
Original file line number Diff line number Diff line change
Expand Up @@ -161,63 +161,79 @@ <h1 id="choosing-a-solver"><a class="header" href="#choosing-a-solver">Choosing
<li><a href="https://docs.rs/diffsol/latest/diffsol/ode_solver/bdf/struct.Bdf.html"><code>diffsol::Bdf</code></a>: A Backwards Difference Formulae solver, suitable for stiff problems and singular mass matrices.</li>
<li><a href="https://docs.rs/diffsol/latest/diffsol/ode_solver/sdirk/struct.Sdirk.html"><code>diffsol::Sdirk</code></a> A Singly Diagonally Implicit Runge-Kutta (SDIRK or ESDIRK) solver. You can define your own butcher tableau using <a href="https://docs.rs/diffsol/latest/diffsol/ode_solver/tableau/struct.Tableau.html"><code>Tableau</code></a> or use one of the pre-defined tableaues.</li>
</ul>
<p>Each of these solvers has a number of generic arguments, for example the <code>Bdf</code> solver has three generic arguments:</p>
<p>For each solver, you will need to specify the linear solver type to use. The available linear solvers are:</p>
<ul>
<li><code>M</code>: The matrix type used to define the problem.</li>
<li><code>Eqn</code>: The type of the equations struct that defines the problem.</li>
<li><code>Nls</code>: The type of the non-linear solver used to solve the implicit equations in the solver.</li>
<li><a href="https://docs.rs/diffsol/latest/diffsol/linear_solver/nalgebra_lu/struct.NalgebraLU.html"><code>diffsol::NalgebraLU</code></a>: A LU decomposition solver using the <a href="https://nalgebra.org">nalgebra</a> crate.</li>
<li><a href="https://docs.rs/diffsol/latest/diffsol/linear_solver/faer_lu/struct.FaerLU.html"><code>diffsol::FaerLU</code></a>: A LU decomposition solver using the <a href="https://github.com/sarah-ek/faer-rs">faer</a> crate.</li>
<li><a href="https://docs.rs/diffsol/latest/diffsol/linear_solver/faer_sparse_lu/struct.FaerSparseLU.html"><code>diffsol::FaerSparseLU</code></a>: A sparse LU decomposition solver using the <code>faer</code> crate.</li>
</ul>
<p>In normal use cases, Rust can infer these from your code so you don't need to specify these explicitly. The <code>Bdf</code> solver implements the <code>Default</code> trait so can be easily created using:</p>
<p>Each solver can be created directly, but it generally easier to use the methods on the <a href="https://docs.rs/diffsol/latest/diffsol/ode_solver/problem/struct.OdeSolverProblem.html"><code>OdeSolverProblem</code></a> struct to create the solver.
For example:</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">use diffsol::OdeBuilder;
</span><span class="boring">use nalgebra::DVector;
</span><span class="boring">type M = nalgebra::DMatrix&lt;f64&gt;;
</span>use diffsol::{Bdf, OdeSolverState, OdeSolverMethod};
</span>use diffsol::{OdeSolverState, NalgebraLU, BdfState, Tableau, SdirkState};
<span class="boring">type M = nalgebra::DMatrix&lt;f64&gt;;
</span>type LS = NalgebraLU&lt;f64&gt;;
<span class="boring">fn main() {
</span><span class="boring">
</span><span class="boring"> let problem = OdeBuilder::new()
</span><span class="boring"> let problem = OdeBuilder::&lt;M&gt;::new()
</span><span class="boring"> .p(vec![1.0, 10.0])
</span><span class="boring"> .build_ode::&lt;M, _, _, _&gt;(
</span><span class="boring"> .rhs_implicit(
</span><span class="boring"> |x, p, _t, y| y[0] = p[0] * x[0] * (1.0 - x[0] / p[1]),
</span><span class="boring"> |x, p, _t, v , y| y[0] = p[0] * v[0] * (1.0 - 2.0 * x[0] / p[1]),
</span><span class="boring"> |_p, _t| DVector::from_element(1, 0.1),
</span><span class="boring"> ).unwrap();
</span>let mut solver = Bdf::default();
let state = OdeSolverState::new(&amp;problem, &amp;solver).unwrap();
solver.set_problem(state, &amp;problem);
</span><span class="boring"> )
</span><span class="boring"> .init(|_p, _t| DVector::from_element(1, 0.1))
</span><span class="boring"> .build()
</span><span class="boring"> .unwrap();
</span>// Create a BDF solver with an initial state
let solver = problem.bdf::&lt;LS&gt;();

// Create a non-initialised state and manually set the values before
// creating the solver
let state = BdfState::new_without_initialise(&amp;problem).unwrap();
// ... set the state values manually
let solver = problem.bdf_solver::&lt;LS&gt;(state);

// Create a SDIRK solver with a pre-defined tableau
let tableau = Tableau::&lt;M&gt;::tr_bdf2();
let state = problem.sdirk_state::&lt;LS, _&gt;(&amp;tableau).unwrap();
let solver = problem.sdirk_solver::&lt;LS, _&gt;(state, tableau);

// Create a tr_bdf2 or esdirk34 solvers directly (both are SDIRK solvers with different tableaus)
let solver = problem.tr_bdf2::&lt;LS&gt;();
let solver = problem.esdirk34::&lt;LS&gt;();

// Create a non-initialised state and manually set the values before
// creating the solver
let state = SdirkState::new_without_initialise(&amp;problem).unwrap();
// ... set the state values manually
let solver = problem.tr_bdf2_solver::&lt;LS&gt;(state);
<span class="boring">}</span></code></pre></pre>
<p>The <code>Sdirk</code> solver requires a tableu to be specified so you can use its <code>new</code> method to create a new solver, for example using the <code>tr_bdf2</code> tableau:</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">use diffsol::{OdeBuilder};
</span><span class="boring">use nalgebra::DVector;
</span><span class="boring">type M = nalgebra::DMatrix&lt;f64&gt;;
</span>use diffsol::{Sdirk, Tableau, NalgebraLU, OdeSolverState, OdeSolverMethod};
<span class="boring">fn main() {
</span><span class="boring"> let problem = OdeBuilder::new()
</span><span class="boring"> .p(vec![1.0, 10.0])
</span><span class="boring"> .build_ode::&lt;M, _, _, _&gt;(
</span><span class="boring"> |x, p, _t, y| y[0] = p[0] * x[0] * (1.0 - x[0] / p[1]),
</span><span class="boring"> |x, p, _t, v , y| y[0] = p[0] * v[0] * (1.0 - 2.0 * x[0] / p[1]),
</span><span class="boring"> |_p, _t| DVector::from_element(1, 0.1),
</span><span class="boring"> ).unwrap();
</span>let mut solver = Sdirk::new(Tableau::&lt;M&gt;::tr_bdf2(), NalgebraLU::default());
let state = OdeSolverState::new(&amp;problem, &amp;solver).unwrap();
solver.set_problem(state, &amp;problem);
<span class="boring">}</span></code></pre></pre>
<p>You can also use one of the helper functions to create a SDIRK solver with a pre-defined tableau, which will create it with the default linear solver:</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">use diffsol::{OdeBuilder};
<h1 id="initialisation"><a class="header" href="#initialisation">Initialisation</a></h1>
<p>Each solver has an internal state that holds information like the current state vector, the gradient of the state vector, the current time, and the current step size. When you create a solver using the <code>bdf</code> or <code>sdirk</code> methods on the <code>OdeSolverProblem</code> struct, the solver will be initialised with an initial state based on the initial conditions of the problem as well as satisfying any algebraic constraints. An initial time step will also be chosen based on your provided equations.</p>
<p>Each solver's state struct implements the <a href="https://docs.rs/diffsol/latest/diffsol/ode_solver/state/trait.OdeSolverState.html"><code>OdeSolverState</code></a> trait, and if you wish to manually create and setup a state, you can use the methods on this trait to do so.</p>
<p>For example, say that you wish to bypass the initialisation of the state as you already have the algebraic constraints and so don't need to solve for them. You can use the <code>new_without_initialise</code> method on the <code>OdeSolverState</code> trait to create a new state without initialising it. You can then use the <code>as_mut</code> method to get a mutable reference to the state and set the values manually.</p>
<p>Note that each state struct has a <a href="https://docs.rs/diffsol/latest/diffsol/ode_solver/state/trait.OdeSolverState.html#tymethod.as_ref"><code>as_ref</code></a> and <a href="https://docs.rs/diffsol/latest/diffsol/ode_solver/state/trait.OdeSolverState.html#tymethod.as_mut"><code>as_mut</code></a> methods that return a <a href="https://docs.rs/diffsol/latest/diffsol/ode_solver/state/struct.StateRef.html"><code>StateRef</code></a> or <a href="https://docs.rs/diffsol/latest/diffsol/ode_solver/state/struct.StateRefMut.html">'StateRefMut`</a> struct respectively. These structs provide a solver-independent way to access the state values so you can use the same code with different solvers.</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">use diffsol::OdeBuilder;
</span><span class="boring">use nalgebra::DVector;
</span><span class="boring">type M = nalgebra::DMatrix&lt;f64&gt;;
</span>use diffsol::{Sdirk, Tableau, NalgebraLU, OdeSolverState, OdeSolverMethod};
</span>use diffsol::{OdeSolverState, NalgebraLU, BdfState};
type LS = NalgebraLU&lt;f64&gt;;

<span class="boring">fn main() {
</span><span class="boring"> let problem = OdeBuilder::new()
</span><span class="boring">
</span><span class="boring"> let problem = OdeBuilder::&lt;M&gt;::new()
</span><span class="boring"> .p(vec![1.0, 10.0])
</span><span class="boring"> .build_ode::&lt;M, _, _, _&gt;(
</span><span class="boring"> .rhs_implicit(
</span><span class="boring"> |x, p, _t, y| y[0] = p[0] * x[0] * (1.0 - x[0] / p[1]),
</span><span class="boring"> |x, p, _t, v , y| y[0] = p[0] * v[0] * (1.0 - 2.0 * x[0] / p[1]),
</span><span class="boring"> |_p, _t| DVector::from_element(1, 0.1),
</span><span class="boring"> ).unwrap();
</span>let mut solver = Sdirk::tr_bdf2();
let state = OdeSolverState::new(&amp;problem, &amp;solver).unwrap();
solver.set_problem(state, &amp;problem);
</span><span class="boring"> )
</span><span class="boring"> .init(|_p, _t| DVector::from_element(1, 0.1))
</span><span class="boring"> .build()
</span><span class="boring"> .unwrap();
</span>let mut state = BdfState::new_without_initialise(&amp;problem).unwrap();
state.as_mut().y[0] = 0.1;
let mut solver = problem.bdf_solver::&lt;LS&gt;(state);
<span class="boring">}</span></code></pre></pre>

</main>
Expand All @@ -228,7 +244,7 @@ <h1 id="choosing-a-solver"><a class="header" href="#choosing-a-solver">Choosing
<i class="fa fa-angle-left"></i>
</a>

<a rel="next prefetch" href="initialisation.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next prefetch" href="solving_the_problem.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>

Expand All @@ -242,7 +258,7 @@ <h1 id="choosing-a-solver"><a class="header" href="#choosing-a-solver">Choosing
<i class="fa fa-angle-left"></i>
</a>

<a rel="next prefetch" href="initialisation.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next prefetch" href="solving_the_problem.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
Expand Down
Loading

0 comments on commit 743247f

Please sign in to comment.