Quickstart
Solving an equation with odecast involves three steps: declaring the unknown
functions, writing the equations, and calling odecast.solve().
Variables
odecast.var() declares an unknown function of the independent
variable \(t\). Derivatives are written with .d():
from odecast import var
y = var("y")
y.d() # y'
y.d(2) # y''
Vector-valued unknowns are declared with shape; see User Guide.
Equations
odecast.Eq takes a left-hand and a right-hand side:
from odecast import Eq
Eq(y.d(2) + y, 0) # y'' + y = 0
Eq(y.d(2) + 0.1*y.d() + y, 0) # y'' + 0.1 y' + y = 0
Nonlinear terms and terms that depend explicitly on the independent
variable odecast.t are written with SymPy (or NumPy) functions:
import sympy as sp
from odecast import t
Eq(y.d(2) + sp.sin(y), 0) # y'' + sin(y) = 0
Eq(y.d(2) + y, sp.sin(t)) # y'' + y = sin(t)
Solving
An initial value problem needs a value for each variable and each of its derivatives below the highest order that occurs, here \(y(0)\) and \(y'(0)\):
from odecast import solve
eq = Eq(y.d(2) + 0.3*y.d() + y, 0)
sol = solve(eq, ivp={y: 1.0, y.d(): 0.0}, tspan=(0, 10))
The initial conditions are taken at tspan[0]. By default the equation is
integrated with scipy.integrate.solve_ivp().
Results
sol.t # time points chosen by the integrator
sol[y] # y at those points
sol[y.d()] # y' at those points
sol.eval(y, 5.0) # y(5), interpolated
sol.eval(y, [1, 2]) # y at several points
Full example
import matplotlib.pyplot as plt
import numpy as np
from odecast import var, Eq, solve
y = var("y")
eq = Eq(y.d(2) + 0.3*y.d() + y, 0)
sol = solve(eq, ivp={y: 1.0, y.d(): 0.0}, tspan=(0, 10))
t = np.linspace(0, 10, 500)
plt.plot(t, sol.eval(y, t), label="y")
plt.plot(t, sol.eval(y.d(), t), label="y'")
plt.xlabel("t")
plt.legend()
plt.show()
Where to go next: the User Guide covers systems, vector variables, boundary value problems and backends; Examples contains worked problems from several fields.