DiffSL

Thus far we have used Rust code to specify the problem we want to solve. This is fine if you are using DiffSol from Rust, but what if you want to use DiffSol from a higher-level language like Python or R? For this usecase we have designed a Domain Specific Language (DSL) called DiffSL that can be used to specify the problem. DiffSL is not a general purpose language but is tightly constrained to the specification of a system of ordinary differential equations. It features a relatively simple syntax that consists of writing a series of tensors (dense or sparse) that represent the equations of the system. For more detail on the syntax of DiffSL see the DiffSL book. This section will focus on how to use DiffSL to specify a problem in DiffSol.

DiffSL Context

The main struct that is used to specify a problem in DiffSL is the DiffSl struct. Creating this struct Just-In-Time (JIT) compiles your DiffSL code into a form that can be executed efficiently by DiffSol.

fn main() {
use diffsol::{DiffSl, CraneliftModule};
type M = nalgebra::DMatrix<f64>;
type CG = CraneliftModule;
        
let eqn = DiffSl::<M, CG>::compile("
    in = [r, k]
    r { 1.0 }
    k { 1.0 }
    u { 0.1 }
    F { r * u * (1.0 - u / k) }
").unwrap();
}

The CG parameter specifies the backend that you want to use to compile the DiffSL code. The CraneliftModule backend is the default backend and is behind the diffsl feature flag. If you want to use the faster LLVM backend you can use the LlvmModule backend, which is behind one of the diffsl-llvm* feature flags, depending on the version of LLVM you have installed.

Once you have created the DiffSl struct you can use it to create a problem using the build_from_eqn method on the OdeBuilder struct.

fn main() {
use diffsol::{DiffSl, CraneliftModule};
use diffsol::{OdeBuilder, Bdf, OdeSolverMethod, OdeSolverState};
type M = nalgebra::DMatrix<f64>;
type CG = CraneliftModule;

        
let eqn = DiffSl::<M, CG>::compile("
    in = [r, k]
    r { 1.0 }
    k { 1.0 }
    u { 0.1 }
    F { r * u * (1.0 - u / k) }
").unwrap();
let problem = OdeBuilder::new()
.rtol(1e-6)
.p([1.0, 10.0])
.build_from_eqn(eqn).unwrap();
let mut solver = Bdf::default();
let t = 0.4;
let state = OdeSolverState::new(&problem, &solver).unwrap();
let _soln = solver.solve(&problem, state, t).unwrap();
}