• Stars
    star
    134
  • Rank 262,881 (Top 6 %)
  • Language
    R
  • License
    Other
  • Created about 6 years ago
  • Updated 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Solving differential equations in R using DifferentialEquations.jl and the SciML Scientific Machine Learning ecosystem

diffeqr

Join the chat at https://gitter.im/JuliaDiffEq/Lobby CRAN status R build status

diffeqr is a package for solving differential equations in R. It utilizes DifferentialEquations.jl for its core routines to give high performance solving of ordinary differential equations (ODEs), stochastic differential equations (SDEs), delay differential equations (DDEs), and differential-algebraic equations (DAEs) directly in R.

If you have any questions, or just want to chat about solvers/using the package, please feel free to chat in the Gitter channel. For bug reports, feature requests, etc., please submit an issue.

Installation

diffeqr is registered into CRAN. Thus to add the package, use:

install.packages("diffeqr")

To install the master branch of the package (for developers), use:

devtools::install_github('SciML/diffeqr', build_vignettes=T)

Note that the first invocation of diffeqr::diffeq_setup() will install both Julia and the required packages if they are missing. If you wish to have it use an existing Julia binary, make sure that julia is found in the path. For more information see the julia_setup() function from JuliaCall.

Usage

diffeqr provides a direct wrapper over DifferentialEquations.jl. The namespace is setup so that the standard syntax of Julia translates directly over to the R environment. There are two things to keep in mind:

  1. All DifferentialEquations.jl commands are prefaced by de$
  2. All commands with a ! are replaced with _bang, for example solve! becomes solve_bang.

Ordinary Differential Equation (ODE) Examples

1D Linear ODEs

Let's solve the linear ODE u'=1.01u. First setup the package:

de <- diffeqr::diffeq_setup()

Define the derivative function f(u,p,t).

f <- function(u,p,t) {
  return(1.01*u)
}

Then we give it an initial condition and a time span to solve over:

u0 <- 1/2
tspan <- c(0., 1.)

With those pieces we define the ODEProblem and solve the ODE:

prob = de$ODEProblem(f, u0, tspan)
sol = de$solve(prob)

This gives back a solution object for which sol$t are the time points and sol$u are the values. We can treat the solution as a continuous object in time via

sol$.(0.2)

and a high order interpolation will compute the value at t=0.2. We can check the solution by plotting it:

plot(sol$t,sol$u,"l")

linear_ode

Systems of ODEs

Now let's solve the Lorenz equations. In this case, our initial condition is a vector and our derivative functions takes in the vector to return a vector (note: arbitrary dimensional arrays are allowed). We would define this as:

f <- function(u,p,t) {
  du1 = p[1]*(u[2]-u[1])
  du2 = u[1]*(p[2]-u[3]) - u[2]
  du3 = u[1]*u[2] - p[3]*u[3]
  return(c(du1,du2,du3))
}

Here we utilized the parameter array p. Thus we use diffeqr::ode.solve like before, but also pass in parameters this time:

u0 <- c(1.0,0.0,0.0)
tspan <- c(0.0,100.0)
p <- c(10.0,28.0,8/3)
prob <- de$ODEProblem(f, u0, tspan, p)
sol <- de$solve(prob)

The returned solution is like before except now sol$u is an array of arrays, where sol$u[i] is the full system at time sol$t[i]. It can be convenient to turn this into an R matrix through sapply:

mat <- sapply(sol$u,identity)

This has each row as a time series. t(mat) makes each column a time series. It is sometimes convenient to turn the output into a data.frame which is done via:

udf <- as.data.frame(t(mat))

Now we can use matplot to plot the timeseries together:

matplot(sol$t,udf,"l",col=1:3)

timeseries

Now we can use the Plotly package to draw a phase plot:

plotly::plot_ly(udf, x = ~V1, y = ~V2, z = ~V3, type = 'scatter3d', mode = 'lines')

plotly_plot

Plotly is much prettier!

Option Handling

If we want to have a more accurate solution, we can send abstol and reltol. Defaults are 1e-6 and 1e-3 respectively. Generally you can think of the digits of accuracy as related to 1 plus the exponent of the relative tolerance, so the default is two digits of accuracy. Absolute tolernace is the accuracy near 0.

In addition, we may want to choose to save at more time points. We do this by giving an array of values to save at as saveat. Together, this looks like:

abstol <- 1e-8
reltol <- 1e-8
saveat <- 0:10000/100
sol <- de$solve(prob,abstol=abstol,reltol=reltol,saveat=saveat)
udf <- as.data.frame(t(sapply(sol$u,identity)))
plotly::plot_ly(udf, x = ~V1, y = ~V2, z = ~V3, type = 'scatter3d', mode = 'lines')

precise_solution

We can also choose to use a different algorithm. The choice is done using a string that matches the Julia syntax. See the ODE tutorial for details. The list of choices for ODEs can be found at the ODE Solvers page. For example, let's use a 9th order method due to Verner:

sol <- de$solve(prob,de$Vern9(),abstol=abstol,reltol=reltol,saveat=saveat)

Note that each algorithm choice will cause a JIT compilation.

Performance Enhancements

One way to enhance the performance of your code is to define the function in Julia so that way it is JIT compiled. diffeqr is built using the JuliaCall package, and so you can utilize the Julia JIT compiler. We expose this automatically over ODE functions via jitoptimize_ode, like in the following example:

f <- function(u,p,t) {
  du1 = p[1]*(u[2]-u[1])
  du2 = u[1]*(p[2]-u[3]) - u[2]
  du3 = u[1]*u[2] - p[3]*u[3]
  return(c(du1,du2,du3))
}
u0 <- c(1.0,0.0,0.0)
tspan <- c(0.0,100.0)
p <- c(10.0,28.0,8/3)
prob <- de$ODEProblem(f, u0, tspan, p)
fastprob <- diffeqr::jitoptimize_ode(de,prob)
sol <- de$solve(fastprob,de$Tsit5())

Note that the first evaluation of the function will have an ~2 second lag since the compiler will run, and all subsequent runs will be orders of magnitude faster than the pure R function. This means it's great for expensive functions (ex. large PDEs) or functions called repeatedly, like during optimization of parameters.

We can also use the JuliaCall functions to directly define the function in Julia to eliminate the R interpreter overhead and get full JIT compilation:

julf <- JuliaCall::julia_eval("
function julf(du,u,p,t)
  du[1] = 10.0*(u[2]-u[1])
  du[2] = u[1]*(28.0-u[3]) - u[2]
  du[3] = u[1]*u[2] - (8/3)*u[3]
end")
JuliaCall::julia_assign("u0", u0)
JuliaCall::julia_assign("p", p)
JuliaCall::julia_assign("tspan", tspan)
prob3 = JuliaCall::julia_eval("ODEProblem(julf, u0, tspan, p)")
sol = de$solve(prob3,de$Tsit5())

To demonstrate the performance advantage, let's time them all:

> system.time({ for (i in 1:100){ de$solve(prob    ,de$Tsit5()) }})
   user  system elapsed
   6.69    0.06    6.78
> system.time({ for (i in 1:100){ de$solve(fastprob,de$Tsit5()) }})
   user  system elapsed
   0.11    0.03    0.14
> system.time({ for (i in 1:100){ de$solve(prob3   ,de$Tsit5()) }})
   user  system elapsed
   0.14    0.02    0.15

This is about a 50x improvement!

Limitations of the JIT Compilation

Using Julia's ModelingToolkit for tracing to JIT compile via Julia has a few known limitations:

  • It requires that all of the function calls are tracable. Scalar functions like cos and sin all fall into this category. Notably, matrix multiplication is not supported.
  • It will have a compilation lag on the first call.

Stochastic Differential Equation (SDE) Examples

1D SDEs

Solving stochastic differential equations (SDEs) is the similar to ODEs. To solve an SDE, you use diffeqr::sde.solve and give two functions: f and g, where du = f(u,t)dt + g(u,t)dW_t

de <- diffeqr::diffeq_setup()
f <- function(u,p,t) {
  return(1.01*u)
}
g <- function(u,p,t) {
  return(0.87*u)
}
u0 <- 1/2
tspan <- c(0.0,1.0)
prob <- de$SDEProblem(f,g,u0,tspan)
sol <- de$solve(prob)
udf <- as.data.frame(t(sapply(sol$u,identity)))
plotly::plot_ly(udf, x = sol$t, y = sol$u, type = 'scatter', mode = 'lines')

geometric_sdes

Systems of Diagonal Noise SDEs

Let's add diagonal multiplicative noise to the Lorenz attractor. diffeqr defaults to diagonal noise when a system of equations is given. This is a unique noise term per system variable. Thus we generalize our previous functions as follows:

f <- function(u,p,t) {
  du1 = p[1]*(u[2]-u[1])
  du2 = u[1]*(p[2]-u[3]) - u[2]
  du3 = u[1]*u[2] - p[3]*u[3]
  return(c(du1,du2,du3))
}
g <- function(u,p,t) {
  return(c(0.3*u[1],0.3*u[2],0.3*u[3]))
}
u0 <- c(1.0,0.0,0.0)
tspan <- c(0.0,1.0)
p <- c(10.0,28.0,8/3)
prob <- de$SDEProblem(f,g,u0,tspan,p)
sol <- de$solve(prob,saveat=0.005)
udf <- as.data.frame(t(sapply(sol$u,identity)))
plotly::plot_ly(udf, x = ~V1, y = ~V2, z = ~V3, type = 'scatter3d', mode = 'lines')

Using a JIT compiled function for the drift and diffusion functions can greatly enhance the speed here. With the speed increase we can comfortably solve over long time spans:

tspan <- c(0.0,100.0)
prob <- de$SDEProblem(f,g,u0,tspan,p)
fastprob <- diffeqr::jitoptimize_sde(de,prob)
sol <- de$solve(fastprob,saveat=0.005)
udf <- as.data.frame(t(sapply(sol$u,identity)))
plotly::plot_ly(udf, x = ~V1, y = ~V2, z = ~V3, type = 'scatter3d', mode = 'lines')

stochastic_lorenz

Let's see how much faster the JIT-compiled version was:

> system.time({ for (i in 1:5){ de$solve(prob    ) }})
   user  system elapsed
 146.40    0.75  147.22
> system.time({ for (i in 1:5){ de$solve(fastprob) }})
   user  system elapsed
   1.07    0.10    1.17

Holy Monster's Inc. that's about 145x faster.

Systems of SDEs with Non-Diagonal Noise

In many cases you may want to share noise terms across the system. This is known as non-diagonal noise. The DifferentialEquations.jl SDE Tutorial explains how the matrix form of the diffusion term corresponds to the summation style of multiple Wiener processes. Essentially, the row corresponds to which system the term is applied to, and the column is which noise term. So du[i,j] is the amount of noise due to the jth Wiener process that's applied to u[i]. We solve the Lorenz system with correlated noise as follows:

f <- JuliaCall::julia_eval("
function f(du,u,p,t)
  du[1] = 10.0*(u[2]-u[1])
  du[2] = u[1]*(28.0-u[3]) - u[2]
  du[3] = u[1]*u[2] - (8/3)*u[3]
end")
g <- JuliaCall::julia_eval("
function g(du,u,p,t)
  du[1,1] = 0.3u[1]
  du[2,1] = 0.6u[1]
  du[3,1] = 0.2u[1]
  du[1,2] = 1.2u[2]
  du[2,2] = 0.2u[2]
  du[3,2] = 0.3u[2]
end")
u0 <- c(1.0,0.0,0.0)
tspan <- c(0.0,100.0)
noise_rate_prototype <- matrix(c(0.0,0.0,0.0,0.0,0.0,0.0), nrow = 3, ncol = 2)

JuliaCall::julia_assign("u0", u0)
JuliaCall::julia_assign("tspan", tspan)
JuliaCall::julia_assign("noise_rate_prototype", noise_rate_prototype)
prob <- JuliaCall::julia_eval("SDEProblem(f, g, u0, tspan, p, noise_rate_prototype=noise_rate_prototype)")
sol <- de$solve(prob)
udf <- as.data.frame(t(sapply(sol$u,identity)))
plotly::plot_ly(udf, x = ~V1, y = ~V2, z = ~V3, type = 'scatter3d', mode = 'lines')

noise_corr

Here you can see that the warping effect of the noise correlations is quite visible! Note that we applied JIT compilation since it's quite necessary for any difficult stochastic example.

Differential-Algebraic Equation (DAE) Examples

A differential-algebraic equation is defined by an implicit function f(du,u,p,t)=0. All of the controls are the same as the other examples, except here you define a function which returns the residuals for each part of the equation to define the DAE. The initial value u0 and the initial derivative du0 are required, though they do not necessarily have to satisfy f (known as inconsistent initial conditions). The methods will automatically find consistent initial conditions. In order for this to occur, differential_vars must be set. This vector states which of the variables are differential (have a derivative term), with false meaning that the variable is purely algebraic.

This example shows how to solve the Robertson equation:

f <- function (du,u,p,t) {
  resid1 = - 0.04*u[1]              + 1e4*u[2]*u[3] - du[1]
  resid2 = + 0.04*u[1] - 3e7*u[2]^2 - 1e4*u[2]*u[3] - du[2]
  resid3 = u[1] + u[2] + u[3] - 1.0
  c(resid1,resid2,resid3)
}
u0 <- c(1.0, 0, 0)
du0 <- c(-0.04, 0.04, 0.0)
tspan <- c(0.0,100000.0)
differential_vars <- c(TRUE,TRUE,FALSE)
prob <- de$DAEProblem(f,du0,u0,tspan,differential_vars=differential_vars)
sol <- de$solve(prob)
udf <- as.data.frame(t(sapply(sol$u,identity)))
plotly::plot_ly(udf, x = sol$t, y = ~V1, type = 'scatter', mode = 'lines') %>%
  plotly::add_trace(y = ~V2) %>%
  plotly::add_trace(y = ~V3)

Additionally, an in-place JIT compiled form for f can be used to enhance the speed:

f = JuliaCall::julia_eval("function f(out,du,u,p,t)
  out[1] = - 0.04u[1]              + 1e4*u[2]*u[3] - du[1]
  out[2] = + 0.04u[1] - 3e7*u[2]^2 - 1e4*u[2]*u[3] - du[2]
  out[3] = u[1] + u[2] + u[3] - 1.0
end")
u0 <- c(1.0, 0, 0)
du0 <- c(-0.04, 0.04, 0.0)
tspan <- c(0.0,100000.0)
differential_vars <- c(TRUE,TRUE,FALSE)
JuliaCall::julia_assign("du0", du0)
JuliaCall::julia_assign("u0", u0)
JuliaCall::julia_assign("p", p)
JuliaCall::julia_assign("tspan", tspan)
JuliaCall::julia_assign("differential_vars", differential_vars)
prob = JuliaCall::julia_eval("DAEProblem(f, du0, u0, tspan, p, differential_vars=differential_vars)")
sol = de$solve(prob)

daes

Delay Differential Equation (DDE) Examples

A delay differential equation is an ODE which allows the use of previous values. In this case, the function needs to be a JIT compiled Julia function. It looks just like the ODE, except in this case there is a function h(p,t) which allows you to interpolate and grab previous values.

We must provide a history function h(p,t) that gives values for u before t0. Here we assume that the solution was constant before the initial time point. Additionally, we pass constant_lags = c(20.0) to tell the solver that only constant-time lags were used and what the lag length was. This helps improve the solver accuracy by accurately stepping at the points of discontinuity. Together this is:

f <- JuliaCall::julia_eval("function f(du, u, h, p, t)
  du[1] = 1.1/(1 + sqrt(10)*(h(p, t-20)[1])^(5/4)) - 10*u[1]/(1 + 40*u[2])
  du[2] = 100*u[1]/(1 + 40*u[2]) - 2.43*u[2]
end")
h <- JuliaCall::julia_eval("function h(p, t)
  [1.05767027/3, 1.030713491/3]
end")
u0 <- c(1.05767027/3, 1.030713491/3)
tspan <- c(0.0, 100.0)
constant_lags <- c(20.0)
JuliaCall::julia_assign("u0", u0)
JuliaCall::julia_assign("tspan", tspan)
JuliaCall::julia_assign("constant_lags", tspan)
prob <- JuliaCall::julia_eval("DDEProblem(f, u0, h, tspan, constant_lags = constant_lags)")
sol <- de$solve(prob,de$MethodOfSteps(de$Tsit5()))
udf <- as.data.frame(t(sapply(sol$u,identity)))
plotly::plot_ly(udf, x = sol$t, y = ~V1, type = 'scatter', mode = 'lines') %>% plotly::add_trace(y = ~V2)

delay

Notice that the solver accurately is able to simulate the kink (discontinuity) at t=20 due to the discontinuity of the derivative at the initial time point! This is why declaring discontinuities can enhance the solver accuracy.

GPU-Accelerated ODE Solving of Ensembles

In many cases one is interested in solving the same ODE many times over many different initial conditions and parameters. In diffeqr parlance this is called an ensemble solve. diffeqr inherits the parallelism tools of the SciML ecosystem that are used for things like automated equation discovery and acceleration. Here we will demonstrate using these parallel tools to accelerate the solving of an ensemble.

First, let's define the JIT-accelerated Lorenz equation like before:

de <- diffeqr::diffeq_setup()
lorenz <- function (u,p,t){
  du1 = p[1]*(u[2]-u[1])
  du2 = u[1]*(p[2]-u[3]) - u[2]
  du3 = u[1]*u[2] - p[3]*u[3]
  c(du1,du2,du3)
}
u0 <- c(1.0,1.0,1.0)
tspan <- c(0.0,100.0)
p <- c(10.0,28.0,8/3)
prob <- de$ODEProblem(lorenz,u0,tspan,p)
fastprob <- diffeqr::jitoptimize_ode(de,prob)

Now we use the EnsembleProblem as defined on the ensemble parallelism page of the documentation: Let's build an ensemble by utilizing uniform random numbers to randomize the initial conditions and parameters:

prob_func <- function (prob,i,rep){
  de$remake(prob,u0=runif(3)*u0,p=runif(3)*p)
}
ensembleprob = de$EnsembleProblem(fastprob, prob_func = prob_func, safetycopy=FALSE)

Now we solve the ensemble in serial:

sol = de$solve(ensembleprob,de$Tsit5(),de$EnsembleSerial(),trajectories=10000,saveat=0.01)

To add GPUs to the mix, we need to bring in DiffEqGPU. The diffeqr::diffeqgpu_setup() helper function will install CUDA for you and bring all of the bindings into the returned object:

degpu <- diffeqr::diffeqgpu_setup()

Now we simply use EnsembleGPUArray() to solve 10,000 ODEs on the GPU in parallel:

sol <- de$solve(ensembleprob,de$Tsit5(),degpu$EnsembleGPUArray(),trajectories=10000,saveat=0.01)

Benchmark

To see how much of an effect the parallelism has, let's test this against R's deSolve package. This is exactly the same problem as the documentation example for deSolve, so let's copy that verbatim and then add a function to do the ensemble generation:

library(deSolve)
Lorenz <- function(t, state, parameters) {
  with(as.list(c(state, parameters)), {
    dX <-  a * X + Y * Z
    dY <-  b * (Y - Z)
    dZ <- -X * Y + c * Y - Z
    list(c(dX, dY, dZ))
  })
}

parameters <- c(a = -8/3, b = -10, c = 28)
state      <- c(X = 1, Y = 1, Z = 1)
times      <- seq(0, 100, by = 0.01)
out <- ode(y = state, times = times, func = Lorenz, parms = parameters)

lorenz_solve <- function (i){
  state      <- c(X = runif(1), Y = runif(1), Z = runif(1))
  parameters <- c(a = -8/3 * runif(1), b = -10 * runif(1), c = 28 * runif(1))
  out <- ode(y = state, times = times, func = Lorenz, parms = parameters)
}

Using lapply to generate the ensemble we get:

> system.time({ lapply(1:1000,lorenz_solve) })
   user  system elapsed
 225.81    0.46  226.63

Now let's see how the JIT-accelerated serial Julia version stacks up against that:

> system.time({ de$solve(ensembleprob,de$Tsit5(),de$EnsembleSerial(),trajectories=1000,saveat=0.01) })
   user  system elapsed
   2.75    0.30    3.08

Julia is already about 73x faster than the pure R solvers here! Now let's add GPU-acceleration to the mix:

> system.time({ de$solve(ensembleprob,de$Tsit5(),degpu$EnsembleGPUArray(),trajectories=1000,saveat=0.01) })
   user  system elapsed
   1.33    1.57    2.93

That's only around 2x faster. But the GPU acceleartion is made for massively parallel problems, so let's up the trajectories a bit. We will not use more trajectories from R because that would take too much computing power, so let's see what happens to the Julia serial and GPU at 10,000 trajectories:

> system.time({ de$solve(ensembleprob,de$Tsit5(),de$EnsembleSerial(),trajectories=10000,saveat=0.01) })
   user  system elapsed
  35.02    4.19   39.25
> system.time({ de$solve(ensembleprob,de$Tsit5(),degpu$EnsembleGPUArray(),trajectories=10000,saveat=0.01) })
   user  system elapsed
  12.03    3.57   15.60

To compare this to the pure Julia code:

using OrdinaryDiffEq, DiffEqGPU
function lorenz(du,u,p,t)
 @inbounds begin
     du[1] = p[1]*(u[2]-u[1])
     du[2] = u[1]*(p[2]-u[3]) - u[2]
     du[3] = u[1]*u[2] - p[3]*u[3]
 end
 nothing
end

u0 = Float32[1.0;1.0;1.0]
tspan = (0.0f0,100.0f0)
p = [10.0f0,28.0f0,8/3f0]
prob = ODEProblem(lorenz,u0,tspan,p)
prob_func = (prob,i,repeat) -> remake(prob,u0=rand(Float32,3).*u0,p=rand(Float32,3).*p)
monteprob = EnsembleProblem(prob, prob_func = prob_func, safetycopy=false)
@time sol = solve(monteprob,Tsit5(),EnsembleGPUArray(),trajectories=10_000,saveat=0.01f0)

# 9.444439 seconds (22.96 M allocations: 6.464 GiB, 44.53% gc time)

which is more than an order of magnitude faster for computing 10,000 trajectories, note that the major factors are that we cannot define 32-bit floating point values from R and the prob_func for generating the initial conditions and parameters is a major bottleneck since this function is written in R.

To see how this scales in Julia, let's take it to insane heights. First, let's reduce the amount we're saving:

@time sol = solve(monteprob,Tsit5(),EnsembleGPUArray(),trajectories=10_000,saveat=1.0f0)
# 0.801215 seconds (1.66 M allocations: 133.846 MiB)

This highlights that controlling memory pressure is key with GPU usage: you will get much better performance when requiring less saved points on the GPU.

@time sol = solve(monteprob,Tsit5(),EnsembleGPUArray(),trajectories=100_000,saveat=1.0f0)
# 1.871536 seconds (6.66 M allocations: 919.521 MiB, 2.48% gc time)

compared to serial:

@time sol = solve(monteprob,Tsit5(),EnsembleSerial(),trajectories=100_000,saveat=1.0f0)
# 22.136743 seconds (16.40 M allocations: 1.628 GiB, 42.98% gc time)

And now we start to see that scaling power! Let's solve 1 million trajectories:

@time sol = solve(monteprob,Tsit5(),EnsembleGPUArray(),trajectories=1_000_000,saveat=1.0f0)
# 25.234710 seconds (56.53 M allocations: 8.579 GiB, 51.61% gc time)

For reference, let's look at deSolve with the change to only save that much:

times      <- seq(0, 100, by = 1.0)
lorenz_solve <- function (i){
  state      <- c(X = runif(1), Y = runif(1), Z = runif(1))
  parameters <- c(a = -8/3 * runif(1), b = -10 * runif(1), c = 28 * runif(1))
  out <- ode(y = state, times = times, func = Lorenz, parms = parameters)
}

system.time({ lapply(1:1000,lorenz_solve) })

The GPU version is solving 1000x as many trajectories, 2x as fast! So conclusion, if you need the most speed, you may want to move to the Julia version to get the most out of your GPU due to Float32's, and when using GPUs make sure it's a problem with a relatively average or low memory pressure, and these methods will give orders of magnitude acceleration compared to what you might be used to.

More Repositories

1

DifferentialEquations.jl

Multi-language suite for high-performance solvers of differential equations and scientific machine learning (SciML) components. Ordinary differential equations (ODEs), stochastic differential equations (SDEs), delay differential equations (DDEs), differential-algebraic equations (DAEs), and more in Julia.
Julia
2,599
star
2

SciMLBook

Parallel Computing and Scientific Machine Learning (SciML): Methods and Applications (MIT 18.337J/6.338J)
HTML
1,780
star
3

ModelingToolkit.jl

An acausal modeling framework for automatically parallelized scientific machine learning (SciML) in Julia. A computer algebra system for integrated symbolics for physics-informed machine learning and automated transformations of differential equations
Julia
1,319
star
4

NeuralPDE.jl

Physics-Informed Neural Networks (PINN) Solvers of (Partial) Differential Equations for Scientific Machine Learning (SciML) accelerated simulation
Julia
891
star
5

DiffEqFlux.jl

Pre-built implicit layer architectures with O(1) backprop, GPUs, and stiff+non-stiff DE solvers, demonstrating scientific machine learning (SciML) and physics-informed machine learning methods
Julia
827
star
6

SciMLTutorials.jl

Tutorials for doing scientific machine learning (SciML) and high-performance differential equation solving with open source software.
CSS
705
star
7

Optimization.jl

Mathematical Optimization in Julia. Local, global, gradient-based and derivative-free. Linear, Quadratic, Convex, Mixed-Integer, and Nonlinear Optimization in one simple, fast, and differentiable interface.
Julia
680
star
8

OrdinaryDiffEq.jl

High performance ordinary differential equation (ODE) and differential-algebraic equation (DAE) solvers, including neural ordinary differential equations (neural ODEs) and scientific machine learning (SciML)
Julia
493
star
9

diffeqpy

Solving differential equations in Python using DifferentialEquations.jl and the SciML Scientific Machine Learning organization
Python
481
star
10

Catalyst.jl

Chemical reaction network and systems biology interface for scientific machine learning (SciML). High performance, GPU-parallelized, and O(1) solvers in open source software.
Julia
414
star
11

DataDrivenDiffEq.jl

Data driven modeling and automated discovery of dynamical systems for the SciML Scientific Machine Learning organization
Julia
398
star
12

Surrogates.jl

Surrogate modeling and optimization for scientific machine learning (SciML)
Julia
309
star
13

SciMLSensitivity.jl

A component of the DiffEq ecosystem for enabling sensitivity analysis for scientific machine learning (SciML). Optimize-then-discretize, discretize-then-optimize, adjoint methods, and more for ODEs, SDEs, DDEs, DAEs, etc.
Julia
301
star
14

DiffEqOperators.jl

Linear operators for discretizations of differential equations and scientific machine learning (SciML)
Julia
283
star
15

SciMLBenchmarks.jl

Scientific machine learning (SciML) benchmarks, AI for science, and (differential) equation solvers. Covers Julia, Python (PyTorch, Jax), MATLAB, R
MATLAB
283
star
16

DiffEqGPU.jl

GPU-acceleration routines for DifferentialEquations.jl and the broader SciML scientific machine learning ecosystem
Julia
268
star
17

DiffEqDocs.jl

Documentation for the DiffEq differential equations and scientific machine learning (SciML) ecosystem
Julia
256
star
18

DiffEqBase.jl

The lightweight Base library for shared types and functionality for defining differential equation and scientific machine learning (SciML) problems
Julia
254
star
19

NeuralOperators.jl

DeepONets, (Fourier) Neural Operators, Physics-Informed Neural Operators, and more in Julia
Julia
229
star
20

LinearSolve.jl

LinearSolve.jl: High-Performance Unified Interface for Linear Solvers in Julia. Easily switch between factorization and Krylov methods, add preconditioners, and all in one interface.
Julia
223
star
21

StochasticDiffEq.jl

Solvers for stochastic differential equations which connect with the scientific machine learning (SciML) ecosystem
Julia
209
star
22

Integrals.jl

A common interface for quadrature and numerical integration for the SciML scientific machine learning organization
Julia
202
star
23

ReservoirComputing.jl

Reservoir computing utilities for scientific machine learning (SciML)
Julia
196
star
24

Sundials.jl

Julia interface to Sundials, including a nonlinear solver (KINSOL), ODE's (CVODE and ARKODE), and DAE's (IDA) in a SciML scientific machine learning enabled manner
Julia
195
star
25

SciMLStyle

A style guide for stylish Julia developers
Julia
172
star
26

DataInterpolations.jl

A library of data interpolation and smoothing functions
Julia
169
star
27

RecursiveArrayTools.jl

Tools for easily handling objects like arrays of arrays and deeper nestings in scientific machine learning (SciML) and other applications
Julia
167
star
28

NonlinearSolve.jl

High-performance and differentiation-enabled nonlinear solvers (Newton methods), bracketed rootfinding (bisection, Falsi), with sparsity and Newton-Krylov support.
Julia
165
star
29

MethodOfLines.jl

Automatic Finite Difference PDE solving with Julia SciML
Julia
148
star
30

JumpProcesses.jl

Build and simulate jump equations like Gillespie simulations and jump diffusions with constant and state-dependent rates and mix with differential equations and scientific machine learning (SciML)
Julia
131
star
31

NBodySimulator.jl

A differentiable simulator for scientific machine learning (SciML) with N-body problems, including astrophysical and molecular dynamics
Julia
123
star
32

DiffEqBayes.jl

Extension functionality which uses Stan.jl, DynamicHMC.jl, and Turing.jl to estimate the parameters to differential equations and perform Bayesian probabilistic scientific machine learning
Julia
119
star
33

ColPrac

Contributor's Guide on Collaborative Practices for Community Packages
Julia
117
star
34

LabelledArrays.jl

Arrays which also have a label for each element for easy scientific machine learning (SciML)
Julia
117
star
35

PolyChaos.jl

A Julia package to construct orthogonal polynomials, their quadrature rules, and use it with polynomial chaos expansions.
Julia
114
star
36

SymbolicNumericIntegration.jl

SymbolicNumericIntegration.jl: Symbolic-Numerics for Solving Integrals
Julia
113
star
37

SciMLBase.jl

The Base interface of the SciML ecosystem
Julia
112
star
38

PreallocationTools.jl

Tools for building non-allocating pre-cached functions in Julia, allowing for GC-free usage of automatic differentiation in complex codes
Julia
106
star
39

ODE.jl

Assorted basic Ordinary Differential Equation solvers for scientific machine learning (SciML). Deprecated: Use DifferentialEquations.jl instead.
Julia
103
star
40

ModelingToolkitStandardLibrary.jl

A standard library of components to model the world and beyond
Julia
97
star
41

RuntimeGeneratedFunctions.jl

Functions generated at runtime without world-age issues or overhead
Julia
95
star
42

QuasiMonteCarlo.jl

Lightweight and easy generation of quasi-Monte Carlo sequences with a ton of different methods on one API for easy parameter exploration in scientific machine learning (SciML)
Julia
95
star
43

FEniCS.jl

A scientific machine learning (SciML) wrapper for the FEniCS Finite Element library in the Julia programming language
Julia
94
star
44

ExponentialUtilities.jl

Fast and differentiable implementations of matrix exponentials, Krylov exponential matrix-vector multiplications ("expmv"), KIOPS, ExpoKit functions, and more. All your exponential needs in SciML form.
Julia
88
star
45

DiffEqCallbacks.jl

A library of useful callbacks for hybrid scientific machine learning (SciML) with augmented differential equation solvers
Julia
82
star
46

EasyModelAnalysis.jl

High level functions for analyzing the output of simulations
Julia
80
star
47

EllipsisNotation.jl

Julia-based implementation of ellipsis array indexing notation `..`
Julia
80
star
48

AutoOptimize.jl

Automatic optimization and parallelization for Scientific Machine Learning (SciML)
Julia
78
star
49

StructuralIdentifiability.jl

Fast and automatic structural identifiability software for ODE systems
Julia
75
star
50

ParameterizedFunctions.jl

A simple domain-specific language (DSL) for defining differential equations for use in scientific machine learning (SciML) and other applications
Julia
73
star
51

HighDimPDE.jl

A Julia package for Deep Backwards Stochastic Differential Equation (Deep BSDE) and Feynman-Kac methods to solve high-dimensional PDEs without the curse of dimensionality
Julia
65
star
52

MultiScaleArrays.jl

A framework for developing multi-scale arrays for use in scientific machine learning (SciML) simulations
Julia
64
star
53

DiffEqNoiseProcess.jl

A library of noise processes for stochastic systems like stochastic differential equations (SDEs) and other systems that are present in scientific machine learning (SciML)
Julia
61
star
54

SciMLExpectations.jl

Fast uncertainty quantification for scientific machine learning (SciML) and differential equations
Julia
61
star
55

SimpleNonlinearSolve.jl

Fast and simple nonlinear solvers for the SciML common interface. Newton, Broyden, Bisection, Falsi, and more rootfinders on a standard interface.
Julia
58
star
56

SparsityDetection.jl

Automatic detection of sparsity in pure Julia functions for sparsity-enabled scientific machine learning (SciML)
Julia
58
star
57

DelayDiffEq.jl

Delay differential equation (DDE) solvers in Julia for the SciML scientific machine learning ecosystem. Covers neutral and retarded delay differential equations, and differential-algebraic equations.
Julia
55
star
58

DiffEqProblemLibrary.jl

A library of premade problems for examples and testing differential equation solvers and other SciML scientific machine learning tools
Julia
53
star
59

CellMLToolkit.jl

CellMLToolkit.jl is a Julia library that connects CellML models to the Scientific Julia ecosystem.
Julia
53
star
60

DiffEqParamEstim.jl

Easy scientific machine learning (SciML) parameter estimation with pre-built loss functions
Julia
52
star
61

SciMLDocs

Global documentation for the Julia SciML Scientific Machine Learning Organization
Julia
51
star
62

Static.jl

Static types useful for dispatch and generated functions.
Julia
51
star
63

GlobalSensitivity.jl

Robust, Fast, and Parallel Global Sensitivity Analysis (GSA) in Julia
Julia
49
star
64

sciml.ai

The SciML Scientific Machine Learning Software Organization Website
CSS
49
star
65

MinimallyDisruptiveCurves.jl

Finds relationships between the parameters of a mathematical model
Julia
49
star
66

DiffEqPhysics.jl

A library for building differential equations arising from physical problems for physics-informed and scientific machine learning (SciML)
Julia
48
star
67

MuladdMacro.jl

This package contains a macro for converting expressions to use muladd calls and fused-multiply-add (FMA) operations for high-performance in the SciML scientific machine learning ecosystem
Julia
46
star
68

DeepEquilibriumNetworks.jl

Implicit Layer Machine Learning via Deep Equilibrium Networks, O(1) backpropagation with accelerated convergence.
Julia
45
star
69

DiffEqDevTools.jl

Benchmarking, testing, and development tools for differential equations and scientific machine learning (SciML)
Julia
43
star
70

OperatorLearning.jl

No need to train, he's a smooth operator
Julia
43
star
71

SciMLOperators.jl

SciMLOperators.jl: Matrix-Free Operators for the SciML Scientific Machine Learning Common Interface in Julia
Julia
41
star
72

BoundaryValueDiffEq.jl

Boundary value problem (BVP) solvers for scientific machine learning (SciML)
Julia
39
star
73

HelicopterSciML.jl

Helicopter Scientific Machine Learning (SciML) Challenge Problem
Julia
37
star
74

RootedTrees.jl

A collection of functionality around rooted trees to generate order conditions for Runge-Kutta methods in Julia for differential equations and scientific machine learning (SciML)
Julia
36
star
75

SBMLToolkit.jl

SBML differential equation and chemical reaction model (Gillespie simulations) for Julia's SciML ModelingToolkit
Julia
35
star
76

AutoOffload.jl

Automatic GPU, TPU, FPGA, Xeon Phi, Multithreaded, Distributed, etc. offloading for scientific machine learning (SciML) and differential equations
Julia
34
star
77

SciMLWorkshop.jl

Workshop materials for training in scientific computing and scientific machine learning
Julia
34
star
78

ModelOrderReduction.jl

High-level model-order reduction to automate the acceleration of large-scale simulations
Julia
32
star
79

DifferenceEquations.jl

Solving difference equations with DifferenceEquations.jl and the SciML ecosystem.
Julia
31
star
80

DASSL.jl

Solves stiff differential algebraic equations (DAE) using variable stepsize backwards finite difference formula (BDF) in the SciML scientific machine learning organization
Julia
31
star
81

SteadyStateDiffEq.jl

Solvers for steady states in scientific machine learning (SciML)
Julia
30
star
82

TruncatedStacktraces.jl

Simpler stacktraces for the Julia Programming Language
Julia
28
star
83

ModelingToolkitCourse

A course on composable system modeling, differential-algebraic equations, acausal modeling, compilers for simulation, and building digital twins of real-world devices
Julia
28
star
84

DiffEqOnline

It's Angular2 business in the front, and a Julia party in the back! It's scientific machine learning (SciML) for the web
TypeScript
27
star
85

PDESystemLibrary.jl

A library of systems of partial differential equations, as defined with ModelingToolkit.jl in Julia
Julia
27
star
86

FiniteVolumeMethod.jl

Solver for two-dimensional conservation equations using the finite volume method in Julia.
Julia
27
star
87

DiffEqOnlineServer

Backend for DiffEqOnline, a webapp for scientific machine learning (SciML)
Julia
25
star
88

ReactionNetworkImporters.jl

Julia Catalyst.jl importers for various reaction network file formats like BioNetGen and stoichiometry matrices
Julia
25
star
89

MathML.jl

Julia MathML parser
Julia
23
star
90

StochasticDelayDiffEq.jl

Stochastic delay differential equations (SDDE) solvers for the SciML scientific machine learning ecosystem
Julia
22
star
91

SimpleDiffEq.jl

Simple differential equation solvers in native Julia for scientific machine learning (SciML)
Julia
22
star
92

DiffEqFinancial.jl

Differential equation problem specifications and scientific machine learning for common financial models
Julia
22
star
93

IRKGaussLegendre.jl

Implicit Runge-Kutta Gauss-Legendre 16th order (Julia)
Jupyter Notebook
21
star
94

MATLABDiffEq.jl

Common interface bindings for the MATLAB ODE solvers via MATLAB.jl for the SciML Scientific Machine Learning ecosystem
Julia
21
star
95

SciMLTutorialsOutput

Tutorials for doing scientific machine learning (SciML) and high-performance differential equation solving with open source software.
HTML
20
star
96

OptimalControl.jl

A component of the SciML scientific machine learning ecosystem for optimal control
Julia
20
star
97

SciPyDiffEq.jl

Wrappers for the SciPy differential equation solvers for the SciML Scientific Machine Learning organization
Julia
20
star
98

IfElse.jl

Under some conditions you may need this function
Julia
19
star
99

QuantumNLDiffEq.jl

Julia
18
star
100

FiniteStateProjection.jl

Finite State Projection algorithms for chemical reaction networks
Julia
17
star