The following code fails:
using ModelingToolkit, OrdinaryDiffEq, PyPlot, LinearAlgebra
G_EARTH = Float64[0.0, 0.0, -9.81] # gravitational acceleration
# model
@parameters mass=1.0 c_spring=50.0 damping=0.5 l0=10.0
@variables t pos(t)[1:3]=[0.0, 0.0, 0.0]
@variables vel(t)[1:3]=[0.0, 0.0, 50.0]
@variables acc(t)[1:3]=[0.0, 0.0, -9.81]
@variables unit_vector(t)[1:3]=[1.0, 0.0, 0.0]
@variables force(t) = 0.0 norm1(t) = l0
D = Differential(t)
eqs = vcat(D.(pos) ~ vel,
D.(vel) ~ acc,
norm1 ~ norm(pos),
unit_vector ~ normalize(pos),
force ~ norm1 * c_spring,
acc .~ G_EARTH)
@named sys = ODESystem(eqs, t)
with the message:
ERROR: LoadError: TypeError: non-boolean (Num) used in boolean context
Stacktrace:
[1] copyto!(dest::OffsetArrays.OffsetVector{Num, Vector{Num}}, src::Symbolics.Arr{Num, 1})
@ Base ./abstractarray.jl:1059
[2] copymutable_oftype(A::Symbolics.Arr{Num, 1}, ::Type{Num})
@ LinearAlgebra ~/.julia/juliaup/julia-1.10.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/LinearAlgebra.jl:404
[3] normalize(a::Symbolics.Arr{Num, 1}, p::Int64)
@ LinearAlgebra ~/.julia/juliaup/julia-1.10.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/generic.jl:1881
[4] normalize(a::Symbolics.Arr{Num, 1})
@ LinearAlgebra ~/.julia/juliaup/julia-1.10.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/generic.jl:1879
[5] top-level scope
@ ~/repos/Tethers.jl/src/Tether_03.jl:15
[6] include
@ ./client.jl:489 [inlined]
[7] macro expansion
@ ./timing.jl:279 [inlined]
[8] top-level scope
@ ./REPL[1]:1
in expression starting at /home/ufechner/repos/Tethers.jl/src/Tether_03.jl:15
It works if I comment the line:
unit_vector ~ normalize(pos),
What is the best way to solve this issue?
You could replace normalize
with pos ./ norm(pos)
to get rid of the error.
The problem seems to be that isempty(::Symbolics.Arr{Num,1})
or in your case isempty(pos)
(which is called inside normalize
) returns a Num
instead of a Bool
. Not sure if that is a feature or a bug, I suspect it is a feature for other aspects.
1 Like
Created a bug report: normalize() fails with symbolic arguments · Issue #52465 · JuliaLang/julia · GitHub
Not sure if it is a bug in LinearAlgebra or in ModelingToolkit, though…
Extra question:
The term pos / norm(pos)
works as good as your suggestion, pos ./ norm(pos)
.
When is the dot operator needed and when not?
It’s not a registered function, so it may need to wait until symbolic array registration merges (which is hopefully next week) to then be held lazy.
1 Like
Merges to which package, or to Julia itself?
Symbolics.jl. The PR is done but just missing tests.
2 Likes
It still crashes:
using ModelingToolkit, LinearAlgebra
@variables t pos(t)[1:3] = [0.0, 0.0, 10.0]
normalize(pos)
with:
julia> normalize(pos)
ERROR: TypeError: non-boolean (Num) used in boolean context
Stacktrace:
[1] copyto!(dest::OffsetArrays.OffsetVector{Num, Vector{Num}}, src::Symbolics.Arr{Num, 1})
@ Base ./abstractarray.jl:1059
[2] copymutable_oftype(A::Symbolics.Arr{Num, 1}, ::Type{Num})
@ LinearAlgebra ~/.julia/juliaup/julia-1.10.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/LinearAlgebra.jl:404
[3] normalize(a::Symbolics.Arr{Num, 1}, p::Int64)
@ LinearAlgebra ~/.julia/juliaup/julia-1.10.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/generic.jl:1881
[4] normalize(a::Symbolics.Arr{Num, 1})
@ LinearAlgebra ~/.julia/juliaup/julia-1.10.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/generic.jl:1879
[5] top-level scope
@ REPL[8]:1
(Mo) pkg> st
Status `~/repos/Mo/Project.toml`
[961ee093] ModelingToolkit v8.74.0
[0c5d862f] Symbolics v5.13.0
Shall I create a bug report for Modelingtoolkit?
Did you try registering it?
I do not understand what you mean… What shall I register, and how?
Dan
December 16, 2023, 2:05pm
10
From docs I think: @register_symbolic f_fun(t)
Not working:
using ModelingToolkit, LinearAlgebra
@variables t pos(t)[1:3] = [0.0, 0.0, 10.0]
@register_symbolic LinearAlgebra.normalize(pos)
normalize(pos)
Message:
ERROR: LoadError: TypeError: non-boolean (Num) used in boolean context
Stacktrace:
[1] copyto!(dest::OffsetArrays.OffsetVector{Num, Vector{Num}}, src::Symbolics.Arr{Num, 1})
@ Base ./abstractarray.jl:1059
[2] copymutable_oftype(A::Symbolics.Arr{Num, 1}, ::Type{Num})
@ LinearAlgebra ~/.julia/juliaup/julia-1.10.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/LinearAlgebra.jl:404
[3] normalize(a::Symbolics.Arr{Num, 1}, p::Int64)
@ LinearAlgebra ~/.julia/juliaup/julia-1.10.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/generic.jl:1881
[4] normalize(a::Symbolics.Arr{Num, 1})
@ LinearAlgebra ~/.julia/juliaup/julia-1.10.0-rc2+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/generic.jl:1879
[5] top-level scope
@ ~/repos/Tethers.jl/mwes/mwe01.jl:11
[6] include(fname::String)
@ Base.MainInclude ./client.jl:489
[7] top-level scope
@ REPL[1]:1
in expression starting at /home/ufechner/repos/Tethers.jl/mwes/mwe01.jl:11
Dan
December 17, 2023, 1:18am
12
Is this any help:
julia> using Symbolics
julia> @variables t pos(t)[1:3]
2-element Vector{Any}:
t
(pos(t))[1:3]
julia> using LinearAlgebra
julia> @register_symbolic LinearAlgebra.normalize(v::AbstractArray, p::Real)
julia> normalize(pos)
LinearAlgebra.normalize(pos(t), 2)
?
I thought you were linking to the new @register_array_symbolic
PR which is why you asked this the day after it merged? That gives the tool to register the array function normalize
but someone needs to add it to the list of registered functions for it to be kept lazy.