Skip to content

Fixes for symbolic arrays change #989

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Jun 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ SciMLBase = "1.3"
Setfield = "0.7"
SpecialFunctions = "0.7, 0.8, 0.9, 0.10, 1.0"
StaticArrays = "0.10, 0.11, 0.12, 1.0"
SymbolicUtils = "0.11.0"
Symbolics = "0.1.21"
SymbolicUtils = "0.12"
Symbolics = "1"
UnPack = "0.1, 1.0"
Unitful = "1.1"
julia = "1.2"
Expand All @@ -83,10 +83,11 @@ NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
ReferenceTests = "324d217c-45ce-50fc-942e-d289b448e8cf"
SteadyStateDiffEq = "9672c7b4-1e72-59bd-8a11-6ac3964bc41f"
StochasticDiffEq = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0"
Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["BenchmarkTools", "ForwardDiff", "GalacticOptim", "NonlinearSolve", "OrdinaryDiffEq", "Optim", "Random", "SteadyStateDiffEq", "Test", "StochasticDiffEq", "Sundials"]
test = ["BenchmarkTools", "ForwardDiff", "GalacticOptim", "NonlinearSolve", "OrdinaryDiffEq", "Optim", "Random", "ReferenceTests", "SteadyStateDiffEq", "Test", "StochasticDiffEq", "Sundials"]
4 changes: 2 additions & 2 deletions src/ModelingToolkit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import JuliaFormatter
using Reexport
@reexport using Symbolics
export @derivatives
using Symbolics: _parse_vars, value, makesym, @derivatives, get_variables,
using Symbolics: _parse_vars, value, @derivatives, get_variables,
exprs_occur_in, solve_for, build_expr
import Symbolics: rename, get_variables!, _solve, hessian_sparsity,
jacobian_sparsity, islinear, _iszero, _isone,
Expand All @@ -49,7 +49,7 @@ import Symbolics: rename, get_variables!, _solve, hessian_sparsity,
ParallelForm, SerialForm, MultithreadedForm, build_function,
unflatten_long_ops, rhss, lhss, prettify_expr, gradient,
jacobian, hessian, derivative, sparsejacobian, sparsehessian,
substituter
substituter, scalarize

import DiffEqBase: @add_kwonly

Expand Down
14 changes: 12 additions & 2 deletions src/parameters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,17 @@ isparameter(x) = false

Maps the variable to a paramter.
"""
toparam(s::Symbolic) = setmetadata(s, MTKParameterCtx, true)
function toparam(s)
if s isa Symbolics.Arr
Symbolics.wrap(toparam(Symbolics.unwrap(s)))
elseif s isa AbstractArray
map(toparam, s)
elseif symtype(s) <: AbstractArray
Symbolics.recurse_and_apply(toparam, s)
else
setmetadata(s, MTKParameterCtx, true)
end
end
toparam(s::Num) = Num(toparam(value(s)))

"""
Expand All @@ -30,6 +40,6 @@ macro parameters(xs...)
Symbolics._parse_vars(:parameters,
Real,
xs,
x -> x isa Array ? toparam.(x) : toparam(x)
toparam,
) |> esc
end
1 change: 0 additions & 1 deletion src/systems/diffeqs/abstractodesystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ function generate_function(
# substitute x(t) by just x
rhss = implicit_dae ? [_iszero(eq.lhs) ? eq.rhs : eq.rhs - eq.lhs for eq in eqs] :
[eq.rhs for eq in eqs]
#obss = [makesym(value(eq.lhs)) ~ substitute(eq.rhs, sub) for eq ∈ observed(sys)]
#rhss = Let(obss, rhss)

# TODO: add an optional check on the ordering of observed equations
Expand Down
16 changes: 12 additions & 4 deletions src/systems/diffeqs/odesystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ function ODESystem(
defaults=_merge(Dict(default_u0), Dict(default_p)),
connection_type=nothing,
)
iv′ = value(iv)
dvs′ = value.(dvs)
ps′ = value.(ps)
iv′ = value(scalarize(iv))
dvs′ = value.(scalarize(dvs))
ps′ = value.(scalarize(ps))

if !(isempty(default_u0) && isempty(default_p))
Base.depwarn("`default_u0` and `default_p` are deprecated. Use `defaults` instead.", :ODESystem, force=true)
Expand Down Expand Up @@ -115,11 +115,19 @@ vars(exprs::Symbolic) = vars([exprs])
vars(exprs) = foldl(vars!, exprs; init = Set())
vars!(vars, eq::Equation) = (vars!(vars, eq.lhs); vars!(vars, eq.rhs); vars)
function vars!(vars, O)
isa(O, Sym) && return push!(vars, O)
if isa(O, Sym)
return push!(vars, O)
end
!istree(O) && return vars

operation(O) isa Differential && return push!(vars, O)

if operation(O) === (getindex) &&
first(arguments(O)) isa Symbolic

return push!(vars, O)
end

operation(O) isa Sym && push!(vars, O)
for arg in arguments(O)
vars!(vars, arg)
Expand Down
3 changes: 3 additions & 0 deletions src/systems/diffeqs/sdesystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ function DiffEqBase.SDEFunction{iip}(sys::SDESystem, dvs = states(sys), ps = par
u0 = nothing;
version = nothing, tgrad=false, sparse = false,
jac = false, Wfact = false, eval_expression = true, kwargs...) where {iip}
dvs = scalarize.(dvs)
ps = scalarize.(ps)

f_gen = generate_function(sys, dvs, ps; expression=Val{eval_expression}, kwargs...)
f_oop,f_iip = eval_expression ? (@RuntimeGeneratedFunction(ex) for ex in f_gen) : f_gen
g_gen = generate_diffusion_function(sys, dvs, ps; expression=Val{eval_expression}, kwargs...)
Expand Down
11 changes: 2 additions & 9 deletions src/systems/nonlinear/nonlinearsystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,18 +103,11 @@ end
function generate_function(sys::NonlinearSystem, dvs = states(sys), ps = parameters(sys); kwargs...)
#obsvars = map(eq->eq.lhs, observed(sys))
#fulldvs = [dvs; obsvars]
fulldvs = dvs
fulldvs′ = makesym.(value.(fulldvs))

sub = Dict(fulldvs .=> fulldvs′)
# substitute x(t) by just x
rhss = [substitute(deq.rhs, sub) for deq ∈ equations(sys)]
#obss = [makesym(value(eq.lhs)) ~ substitute(eq.rhs, sub) for eq ∈ observed(sys)]
rhss = [deq.rhs for deq ∈ equations(sys)]
#rhss = Let(obss, rhss)

dvs′ = fulldvs′[1:length(dvs)]
ps′ = makesym.(value.(ps), states=())
return build_function(rhss, dvs′, ps′;
return build_function(rhss, value.(dvs), value.(ps);
conv = AbstractSysToExpr(sys), kwargs...)
end

Expand Down
8 changes: 5 additions & 3 deletions src/systems/reaction/reactionsystem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -462,11 +462,13 @@ function Base.convert(::Type{<:SDESystem}, rs::ReactionSystem;
noise_scaling=nothing, name=nameof(rs), combinatoric_ratelaws=true,
include_zero_odes=true, kwargs...)

if noise_scaling isa Vector
if noise_scaling isa AbstractArray
(length(noise_scaling)!=length(equations(rs))) &&
error("The number of elements in 'noise_scaling' must be equal " *
"to the number of reactions in the reaction system.")
noise_scaling = value.(noise_scaling)
if !(noise_scaling isa Symbolics.Arr)
noise_scaling = value.(noise_scaling)
end
elseif !isnothing(noise_scaling)
noise_scaling = fill(value(noise_scaling),length(equations(rs)))
end
Expand All @@ -477,7 +479,7 @@ function Base.convert(::Type{<:SDESystem}, rs::ReactionSystem;
combinatoric_ratelaws=combinatoric_ratelaws)
systems = convert.(SDESystem, get_systems(rs))
SDESystem(eqs, noiseeqs, get_iv(rs), get_states(rs),
(noise_scaling===nothing) ? get_ps(rs) : union(get_ps(rs), toparam.(noise_scaling));
(noise_scaling===nothing) ? get_ps(rs) : union(get_ps(rs), toparam(noise_scaling));
name=name,
systems=systems,
kwargs...)
Expand Down
2 changes: 1 addition & 1 deletion src/systems/systemstructure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ function initialize_system_structure(sys)
for algvar in algvars
# it could be that a variable appeared in the states, but never appeared
# in the equations.
algvaridx = get(var2idx, algvar, 0)
algvaridx = var2idx[algvar]
vartype[algvaridx] = ALGEBRAIC_VARIABLE
end

Expand Down
5 changes: 5 additions & 0 deletions test/bigsystem.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using ModelingToolkit, LinearAlgebra, SparseArrays
using Symbolics
using Symbolics: scalarize

# Define the constants for the PDE
const α₂ = 1.0
Expand Down Expand Up @@ -27,6 +29,9 @@ My[end,end-1] = 2.0
# Define the initial condition as normal arrays
@variables du[1:N,1:N,1:3] u[1:N,1:N,1:3] MyA[1:N,1:N] AMx[1:N,1:N] DA[1:N,1:N]

du,u,MyA,AMx,DA = scalarize.((du,u,MyA,AMx,DA))
@show typeof.((du,u,MyA,AMx,DA))

# Define the discretized PDE as an ODE function
function f(du,u,p,t)
A = @view u[:,:,1]
Expand Down
32 changes: 5 additions & 27 deletions test/latexify.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Test
using Latexify
using ModelingToolkit
using ReferenceTests

### Tips for generating latex tests:
### Latexify has an unexported macro:
Expand Down Expand Up @@ -28,47 +29,24 @@ eqs = [D(x) ~ σ*(y-x)*D(x-y)/D(z),


# Latexify.@generate_test latexify(eqs)
@test latexify(eqs) == replace(
raw"\begin{align}
\frac{dx(t)}{dt} =& \frac{\sigma \mathrm{\frac{d}{d t}}\left( x\left( t \right) - y\left( t \right) \right) \left( y\left( t \right) - x\left( t \right) \right)}{\frac{dz(t)}{dt}} \\
0 =& - y\left( t \right) + 0.1 \sigma x\left( t \right) \left( \rho - z\left( t \right) \right) \\
\frac{dz(t)}{dt} =& \left( y\left( t \right) \right)^{\frac{2}{3}} x\left( t \right) - \beta z\left( t \right)
\end{align}
", "\r\n"=>"\n")
@test_reference "latexify/10.tex" latexify(eqs)

@variables u[1:3](t)
@parameters p[1:3]
eqs = [D(u[1]) ~ p[3]*(u[2]-u[1]),
0 ~ p[2]*p[3]*u[1]*(p[1]-u[1])/10-u[2],
D(u[3]) ~ u[1]*u[2]^(2//3) - p[3]*u[3]]

@test latexify(eqs) == replace(
raw"\begin{align}
\frac{du{_1}(t)}{dt} =& p{_3} \left( \mathrm{u{_2}}\left( t \right) - \mathrm{u{_1}}\left( t \right) \right) \\
0 =& - \mathrm{u{_2}}\left( t \right) + 0.1 p{_2} p{_3} \mathrm{u{_1}}\left( t \right) \left( p{_1} - \mathrm{u{_1}}\left( t \right) \right) \\
\frac{du{_3}(t)}{dt} =& \left( \mathrm{u{_2}}\left( t \right) \right)^{\frac{2}{3}} \mathrm{u{_1}}\left( t \right) - p{_3} \mathrm{u{_3}}\left( t \right)
\end{align}
", "\r\n"=>"\n")
@test_reference "latexify/20.tex" latexify(eqs)

eqs = [D(u[1]) ~ p[3]*(u[2]-u[1]),
D(u[2]) ~ p[2]*p[3]*u[1]*(p[1]-u[1])/10-u[2],
D(u[3]) ~ u[1]*u[2]^(2//3) - p[3]*u[3]]

@test latexify(eqs) == replace(
raw"\begin{align}
\frac{du{_1}(t)}{dt} =& p{_3} \left( \mathrm{u{_2}}\left( t \right) - \mathrm{u{_1}}\left( t \right) \right) \\
\frac{du{_2}(t)}{dt} =& - \mathrm{u{_2}}\left( t \right) + 0.1 p{_2} p{_3} \mathrm{u{_1}}\left( t \right) \left( p{_1} - \mathrm{u{_1}}\left( t \right) \right) \\
\frac{du{_3}(t)}{dt} =& \left( \mathrm{u{_2}}\left( t \right) \right)^{\frac{2}{3}} \mathrm{u{_1}}\left( t \right) - p{_3} \mathrm{u{_3}}\left( t \right)
\end{align}
", "\r\n"=>"\n")

@test_reference "latexify/30.tex" latexify(eqs)
@parameters t
@variables x(t)
D = Differential(t)
eqs = [D(x) ~ (1+cos(t))/(1+2*x)]

@test latexify(eqs) == replace(
raw"\begin{align}
\frac{dx(t)}{dt} =& \frac{\left( 1 + \cos\left( t \right) \right)}{\left( 1 + 2 x\left( t \right) \right)}
\end{align}
", "\r\n"=>"\n")
@test_reference "latexify/40.tex" latexify(eqs)
5 changes: 5 additions & 0 deletions test/latexify/10.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
\begin{align}
\frac{dx(t)}{dt} =& \frac{\sigma \mathrm{\frac{d}{d t}}\left( x\left( t \right) - y\left( t \right) \right) \left( y\left( t \right) - x\left( t \right) \right)}{\frac{dz(t)}{dt}} \\
0 =& - y\left( t \right) + 0.1 \sigma x\left( t \right) \left( \rho - z\left( t \right) \right) \\
\frac{dz(t)}{dt} =& \left( y\left( t \right) \right)^{\frac{2}{3}} x\left( t \right) - \beta z\left( t \right)
\end{align}
5 changes: 5 additions & 0 deletions test/latexify/20.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
\begin{align}
\frac{du{_1}(t)}{dt} =& p{_3} \left( \mathrm{u{_2}}\left( t \right) - \mathrm{u{_1}}\left( t \right) \right) \\
0 =& - \mathrm{u{_2}}\left( t \right) + 0.1 \mathrm{u{_1}}\left( t \right) p{_2} p{_3} \left( p{_1} - \mathrm{u{_1}}\left( t \right) \right) \\
\frac{du{_3}(t)}{dt} =& \left( \mathrm{u{_2}}\left( t \right) \right)^{\frac{2}{3}} \mathrm{u{_1}}\left( t \right) - \mathrm{u{_3}}\left( t \right) p{_3}
\end{align}
5 changes: 5 additions & 0 deletions test/latexify/30.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
\begin{align}
\frac{du{_1}(t)}{dt} =& p{_3} \left( \mathrm{u{_2}}\left( t \right) - \mathrm{u{_1}}\left( t \right) \right) \\
\frac{du{_2}(t)}{dt} =& - \mathrm{u{_2}}\left( t \right) + 0.1 \mathrm{u{_1}}\left( t \right) p{_2} p{_3} \left( p{_1} - \mathrm{u{_1}}\left( t \right) \right) \\
\frac{du{_3}(t)}{dt} =& \left( \mathrm{u{_2}}\left( t \right) \right)^{\frac{2}{3}} \mathrm{u{_1}}\left( t \right) - \mathrm{u{_3}}\left( t \right) p{_3}
\end{align}
3 changes: 3 additions & 0 deletions test/latexify/40.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
\begin{align}
\frac{dx(t)}{dt} =& \frac{1 + \cos\left( t \right)}{1 + 2 x\left( t \right)}
\end{align}
2 changes: 1 addition & 1 deletion test/simplify.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ null_op = 0*t
one_op = 1*t
@test isequal(simplify(one_op), t)

identity_op = Num(Term(identity,[x.val]))
identity_op = Num(Term(identity,[value(x)]))
@test isequal(simplify(identity_op), x)

minus_op = -x
Expand Down
44 changes: 22 additions & 22 deletions test/variable_parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,29 +43,29 @@ D1 = Differential(t)
# Test array expressions
@parameters begin
t[1:2]
s[1:2:4,1:2]
s[1:4,1:2]
end
@parameters σ[1:2](..)

@test all(ModelingToolkit.isparameter, t)
@test all(ModelingToolkit.isparameter, s)
@test all(ModelingToolkit.isparameter, σ)

fntype(n, T) = FnType{NTuple{n, Any}, T}
t1 = Num[Variable{Real}(:t, 1), Variable{Real}(:t, 2)]
s1 = Num[Variable{Real}(:s, 1, 1) Variable{Real}(:s, 1, 2);
Variable{Real}(:s, 3, 1) Variable{Real}(:s, 3, 2)]
σ1 = [Num(Variable{fntype(1, Real)}(:σ, 1)), Num(Variable{fntype(1, Real)}(:σ, 2))]
@test isequal(t1, t)
@test isequal(s1, s)
@test isequal(σ1, σ)

@parameters t
@variables x[1:2](t)
x1 = Num[Variable{FnType{Tuple{Any}, Real}}(:x, 1)(t.val),
Variable{FnType{Tuple{Any}, Real}}(:x, 2)(t.val)]

@test isequal(x1, x)
@test all(ModelingToolkit.isparameter, collect(t))
@test all(ModelingToolkit.isparameter, collect(s))
@test all(ModelingToolkit.isparameter, Any[σ[1], σ[2]])

# fntype(n, T) = FnType{NTuple{n, Any}, T}
# t1 = Num[Variable{Real}(:t, 1), Variable{Real}(:t, 2)]
# s1 = Num[Variable{Real}(:s, 1, 1) Variable{Real}(:s, 1, 2);
# Variable{Real}(:s, 3, 1) Variable{Real}(:s, 3, 2)]
# σ1 = [Num(Variable{fntype(1, Real)}(:σ, 1)), Num(Variable{fntype(1, Real)}(:σ, 2))]
# @test isequal(t1, collect(t))
# @test isequal(s1, collect(s))
# @test isequal(σ1, σ)

#@parameters t
#@variables x[1:2](t)
#x1 = Num[Variable{FnType{Tuple{Any}, Real}}(:x, 1)(t.val),
# Variable{FnType{Tuple{Any}, Real}}(:x, 2)(t.val)]
#
#@test isequal(x1, x)

@variables a[1:11,1:2]
@variables a()
Expand All @@ -78,8 +78,8 @@ vals = [1,2,3,4]
@variables x=1 xs[1:4]=vals ys[1:5]=1

@test getmetadata(x, VariableDefaultValue) === 1
@test getmetadata.(xs, (VariableDefaultValue,)) == vals
@test getmetadata.(ys, (VariableDefaultValue,)) == ones(Int, 5)
@test getmetadata.(collect(xs), (VariableDefaultValue,)) == vals
@test getmetadata.(collect(ys), (VariableDefaultValue,)) == ones(Int, 5)

struct Flow end
u = u"m^3/s"
Expand Down
4 changes: 2 additions & 2 deletions test/variable_utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ new = (((1 / β - 1) + δ) / γ) ^ (1 / (γ - 1))

# test namespace_expr
@parameters t a p(t)
pterm = p.val
pterm = value(p)
pnsp = ModelingToolkit.namespace_expr(pterm, :namespace, :t)
@test typeof(pterm) == typeof(pnsp)
@test ModelingToolkit.getname(pnsp) == Symbol("namespace₊p")
asym = a.val
asym = value(a)
ansp = ModelingToolkit.namespace_expr(asym, :namespace, :t)
@test typeof(asym) == typeof(ansp)
@test ModelingToolkit.getname(ansp) == Symbol("namespace₊a")