Skip to content

Commit f62a3a0

Browse files
authored
Add an analytic solution field for PDESystem (#2082)
1 parent e93e23d commit f62a3a0

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

src/systems/pde/pdesystem.jl

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,19 @@ struct PDESystem <: ModelingToolkit.AbstractMultivariateSystem
6161
"""
6262
systems::Vector
6363
"""
64+
analytic: A vector of explicit symbolic expressions for the analytic solutions of each
65+
dependent variable. e.g. `analytic = [u(t, x) ~ a*sin(c*t) * cos(k*x)]`
66+
"""
67+
analytic::Any
68+
"""
69+
analytic_func: A vector of functions for the analytic solutions of each dependent
70+
variable. Will be generated from `analytic` if not provided. Should have the same
71+
argument signature as the variable, and a `ps` argument as the last argument,
72+
which takes an indexable of parameter values in the order you specified them in `ps`.
73+
e.g. `analytic_func = [u(t, x) => (ps, t, x) -> ps[1]*sin(ps[2]*t) * cos(ps[3]*x)]`
74+
"""
75+
analytic_func::Any
76+
"""
6477
name: the name of the system
6578
"""
6679
name::Symbol
@@ -78,15 +91,40 @@ struct PDESystem <: ModelingToolkit.AbstractMultivariateSystem
7891
systems = [],
7992
connector_type = nothing,
8093
metadata = nothing,
94+
analytic = nothing,
95+
analytic_func = nothing,
8196
gui_metadata = nothing,
8297
checks::Union{Bool, Int} = true,
8398
name)
8499
if checks == true || (checks & CheckUnits) > 0
85100
all_dimensionless([dvs; ivs; ps]) || check_units(eqs)
86101
end
102+
87103
eqs = eqs isa Vector ? eqs : [eqs]
88-
new(eqs, bcs, domain, ivs, dvs, ps, defaults, connector_type, systems, name,
89-
metadata, gui_metadata)
104+
105+
if !isnothing(analytic)
106+
analytic = analytic isa Vector ? analytic : [analytic]
107+
if length(analytic) != length(dvs)
108+
throw(ArgumentError("The number of analytic solutions must match the number of dependent variables"))
109+
end
110+
111+
if isnothing(analytic_func)
112+
analytic_func = map(analytic) do eq
113+
args = arguments(eq.lhs)
114+
p = ps isa SciMLBase.NullParameters ? [] : map(a -> a.first, ps)
115+
args = vcat(DestructuredArgs(p), args)
116+
ex = Func(args, [], eq.rhs) |> toexpr
117+
eq.lhs => @RuntimeGeneratedFunction(ex)
118+
end
119+
end
120+
end
121+
122+
if !isnothing(analytic_func)
123+
analytic_func = analytic_func isa Dict ? analytic_func : analytic_func |> Dict
124+
end
125+
126+
new(eqs, bcs, domain, ivs, dvs, ps, defaults, connector_type, systems, analytic,
127+
analytic_func, name, metadata, gui_metadata)
90128
end
91129
end
92130

test/pde.jl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using ModelingToolkit, DiffEqBase, LinearAlgebra
1+
using ModelingToolkit, DiffEqBase, LinearAlgebra, Test
22

33
# Define some variables
44
@parameters t x
@@ -13,7 +13,17 @@ bcs = [u(0, x) ~ -h * x * (x - 1) * sin(x),
1313
domains = [t (0.0, 1.0),
1414
x (0.0, 1.0)]
1515

16-
@named pdesys = PDESystem(eq, bcs, domains, [t, x], [u])
16+
analytic = [u(t, x) ~ -h * x * (x - 1) * sin(x) * exp(-2 * h * t)]
17+
analytic_function = (ps, t, x) -> -ps[1] * x * (x - 1) * sin(x) * exp(-2 * ps[1] * t)
18+
19+
@named pdesys = PDESystem(eq, bcs, domains, [t, x], [u], [h => 1], analytic = analytic)
1720
@show pdesys
1821

1922
@test all(isequal.(independent_variables(pdesys), [t, x]))
23+
24+
dx = 0:0.1:1
25+
dt = 0:0.1:1
26+
27+
# Test generated analytic_func
28+
@test all(pdesys.analytic_func[u(t, x)]([2], disct, discx)
29+
analytic_function([2], disct, discx) for disct in dt, discx in dx)

test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ using SafeTestsets, Test
2020
@safetestset "SteadyStateSystem Test" begin include("steadystatesystems.jl") end
2121
@safetestset "SDESystem Test" begin include("sdesystem.jl") end
2222
@safetestset "NonlinearSystem Test" begin include("nonlinearsystem.jl") end
23+
@safetestset "PDE Construction Test" begin include("pde.jl") end
2324
@safetestset "JumpSystem Test" begin include("jumpsystem.jl") end
2425
@safetestset "Constraints Test" begin include("constraints.jl") end
2526
@safetestset "Reduction Test" begin include("reduction.jl") end
@@ -31,7 +32,6 @@ using SafeTestsets, Test
3132
@safetestset "State Selection Test" begin include("state_selection.jl") end
3233
@safetestset "Symbolic Event Test" begin include("symbolic_events.jl") end
3334
@safetestset "Stream Connnect Test" begin include("stream_connectors.jl") end
34-
@safetestset "PDE Construction Test" begin include("pde.jl") end
3535
@safetestset "Lowering Integration Test" begin include("lowering_solving.jl") end
3636
@safetestset "Test Big System Usage" begin include("bigsystem.jl") end
3737
@safetestset "Depdendency Graph Test" begin include("dep_graphs.jl") end

0 commit comments

Comments
 (0)