Essentially the API is “functional”, where parameterized functions are defined which give the variables, parameters, equations…etc of the model. The goal is to have a nice easy way to do experiments that involve changing the model itself including parameter, eqs…etc based on a descriptor object.
It’s very simple and small, only consisting of this block:
struct Model
variables::Any
parameters::Any
dep_vars::Any
equations::Any
bcs::Any
domain::Any
discretizer::Any
end
function (m::Model)(global_parameters, return_sys=false)
variables = m.variables(global_parameters)
params = m.parameters(global_parameters)
dep_vars = m.dep_vars(global_parameters)
equations = m.equations(global_parameters)
bcs = m.bcs(global_parameters)
domain = m.domain(global_parameters)
discretizer = m.discretizer(global_parameters)
default_params = [param => getdefault(param) for param in params]
@named pdesys = PDESystem(equations, bcs, domain, variables, dep_vars, default_params)
prob = discretizer(pdesys)
if return_sys
prob, pdesys
else
prob
end
end
A small example below (using MoL), I used a float as the descriptor:
using OrdinaryDiffEq
using ModelingToolkit
using MethodOfLines
using DomainSets
using Plots
using ModelDefiner
# Parameters, variables, and derivatives
@parameters t x
@variables u(..)
Dt = Differential(t)
Dxx = Differential(x)^2
function construct_eqs(i)
function coeff(t, x)
return i
end
return [Dt(u(t, x)) ~ coeff(t,x) * Dxx(u(t, x))]
end
function construct_bcs(i)
[u(0, x) ~ cos(x),
u(t, 0) ~ exp(-t),
u(t, 1) ~ exp(-t) * cos(1)]
end
function construct_variables(i)
[t, x]
end
function construct_domains(i)
[t ∈ Interval(0.0, 1.0),
x ∈ Interval(0.0, 1.0)]
end
function construct_depvars(i)
return [u(t, x)]
end
function construct_discretizer(i)
dx = 0.1
order = 2
discretization = MOLFiniteDifference([x => dx], t)
# Convert the PDE problem into an ODE problem
discretizer(pdesys) = discretize(pdesys,discretization)
return discretizer
end
function construct_parameters(i)
return []
end
m = Model(construct_variables, construct_parameters, construct_depvars, construct_eqs,
construct_bcs, construct_domains, construct_discretizer)
prob = m(1.)
sol = solve(prob, Tsit5(), saveat=0.2)
# Plot results and compare with exact solution
discrete_x = sol[x]
discrete_t = sol[t]
solu = sol[u(t, x)]
plt = plot()
for i in eachindex(discrete_t)
plot!(discrete_x, solu[i, :], label="Numerical, t=$(discrete_t[i])")
end
plt