Solving DAEs with Physics-Informed Neural Networks (PINNs)
It is highly recommended you first read the solving ordinary differential equations with DifferentialEquations.jl tutorial before reading this tutorial.
This tutorial is an introduction to using physics-informed neural networks (PINNs) for solving differential algebraic equations (DAEs).
Solving an DAE with PINNs
Let's solve a simple DAE system:
using NeuralPDE, Random, OrdinaryDiffEq, Statistics, Lux, OptimizationOptimisers
example = (du, u, p, t) -> [cos(2pi * t) - du[1], u[2] + cos(2pi * t) - du[2]]
u₀ = [1.0, -1.0]
du₀ = [0.0, 0.0]
tspan = (0.0, 1.0)
(0.0, 1.0)
Differential_vars is a logical array which declares which variables are the differential (non-algebraic) vars
differential_vars = [true, false]
2-element Vector{Bool}:
1
0
prob = DAEProblem(example, du₀, u₀, tspan; differential_vars = differential_vars)
chain = Lux.Chain(Lux.Dense(1, 15, cos), Lux.Dense(15, 15, sin), Lux.Dense(15, 2))
opt = OptimizationOptimisers.Adam(0.1)
alg = NNDAE(chain, opt; autodiff = false)
sol = solve(prob, alg, verbose = true, dt = 1 / 100.0, maxiters = 3000, abstol = 1e-10)
retcode: Success
Interpolation: 1st order linear
t: 0.0:0.01:1.0
u: 101-element Vector{Vector{Float64}}:
[1.0, -1.0]
[1.0104371745734326, -0.9809714151006407]
[1.0206948793337574, -0.9603745847290079]
[1.03075136985688, -0.9381357096073094]
[1.0405848482158406, -0.9141887609005457]
[1.0501734609532696, -0.8884761220595233]
[1.059495306523612, -0.8609491994044184]
[1.068528452801886, -0.8315689965540741]
[1.0772509651692859, -0.8003066478678361]
[1.0856409455864178, -0.7671439061922686]
⋮
[0.922840989871401, -0.8758496540539453]
[0.9317701463289463, -0.900229674606199]
[0.9409795308331141, -0.9211569671930178]
[0.9504300972968065, -0.9386775769693866]
[0.9600808508541842, -0.9528610336540203]
[0.9698890031656155, -0.9637989970420656]
[0.9798101597366279, -0.9716036833674075]
[0.9897985394803436, -0.9764060940783827]
[0.9998072260914305, -0.9783540711849884]
Now let's compare the predictions from the learned network with the ground truth which we can obtain by numerically solving the DAE.
function example1(du, u, p, t)
du[1] = cos(2pi * t)
du[2] = u[2] + cos(2pi * t)
nothing
end
M = [1.0 0.0; 0.0 0.0]
f = ODEFunction(example1, mass_matrix = M)
prob_mm = ODEProblem(f, u₀, tspan)
ground_sol = solve(prob_mm, Rodas5(), reltol = 1e-8, abstol = 1e-8)
retcode: Success
Interpolation: specialized 4rd order "free" stiffness-aware interpolation
t: 9-element Vector{Float64}:
0.0
1.0e-6
1.1e-5
0.00011099999999999999
0.0011109999999999998
0.011110999999999996
0.11111099999999996
0.7838612882520571
1.0
u: 9-element Vector{Vector{Float64}}:
[1.0, -1.0]
[1.0000010000000001, -0.9999999999802608]
[1.0000109999999913, -0.9999999976115558]
[1.0001109999910016, -0.9999997567932182]
[1.0011109909770284, -0.9999756355789903]
[1.011101976768569, -0.9975640989587868]
[1.1023025821686998, -0.7660448918691988]
[0.8238691280829226, -0.2111552898963995]
[0.9794681556857161, -1.0]
using Plots
plot(ground_sol, tspan = tspan, layout = (2, 1), label = "ground truth")
plot!(sol, tspan = tspan, layout = (2, 1), label = "dae with pinns")