Sophon
Sophon.jl is a Julia package for solving partial differential equations (PDEs) using physics-informed neural networks (PINNs). We will go through the steps to solve the nonlinear Schrödinger equation using Sophon.jl.
Step 1: Import the required packages
using ModelingToolkit, IntervalSets, Sophon, CairoMakie
using Optimization, OptimizationOptimJL
Step 2: Define the PDE system
In this step, we define the PDE system for the nonlinear Schrödinger equation using ModelingToolkit.jl.
@parameters x,t
@variables u(..), v(..)
Dₜ = Differential(t)
Dₓ² = Differential(x)^2
eqs=[Dₜ(u(x,t)) ~ -Dₓ²(v(x,t))/2 - (abs2(v(x,t)) + abs2(u(x,t))) * v(x,t),
Dₜ(v(x,t)) ~ Dₓ²(u(x,t))/2 + (abs2(v(x,t)) + abs2(u(x,t))) * u(x,t)]
bcs = [u(x, 0.0) ~ 2sech(x),
v(x, 0.0) ~ 0.0,
u(-5.0, t) ~ u(5.0, t),
v(-5.0, t) ~ v(5.0, t)]
domains = [x ∈ Interval(-5.0, 5.0),
t ∈ Interval(0.0, π/2)]
@named pde_system = PDESystem(eqs, bcs, domains, [x,t], [u(x,t),v(x,t)])
The @parameters
macro defines the parameters of the PDE system, and the @variables
macro defines the dependent variables. We use Differential
to define the derivatives with respect to time and space. The eqs
array defines the equations in the PDE system. The bcs array defines the boundary conditions. The domains
array defines the spatial and temporal domains of the PDE system. Finally, we use the @named
macro to give a name to the PDE system.
Step 3: Define the neural network architecture
Next, we define the physics-informed neural network (PINN) using Sophon.jl. In this example, we will use a Siren network with 2 sine layers and 1 cosine layer for each variable, and 16 hidden dimensions per layer. We will use 4 layers for both variables, and set the frequency parameter $\omega$ to 1.0.
pinn = PINN(u = Siren(2,1; hidden_dims=16,num_layers=4, omega = 1.0),
v = Siren(2,1; hidden_dims=16,num_layers=4, omega = 1.0))
We define a physics-informed neural network (PINN) with the pinn variable. The PINN macro takes a dictionary that maps the dependent variables to their corresponding neural network architecture. In this case, we use the Siren architecture for both u and v with 2 input dimensions, 1 output dimension, 16 hidden dimensions, and 4 layers. We also set the frequency of the sine activation functions to 1.0.
Step 4: Create a QuasiRandomSampler object
Here, we create a QuasiRandomSampler object with 500 sample points, where the first argument corresponds to the number of data points for each equation, and the second argument corresponds to the number of data points for each boundary condition.
sampler = QuasiRandomSampler(500, (200,200,20,20))
Step 5: Define a training strategy
Here, we use a NonAdaptiveTraining strategy with 1
as the weight of all equations, and (10,10,1,1)
for the four boundary conditions.
strategy = NonAdaptiveTraining(1,(10,10,1,1))
Step 6: Discretize the PDE system using Sophon
prob = Sophon.discretize(pde_system, pinn, sampler, strategy)
Step 7: Solve the optimization problem
res = Optimization.solve(prob, BFGS(); maxiters=2000)