Animation stopped working

Hello, I wrote a code that worked yesterday, but today the animation part did not work any longer:

using Timers
tic()
using ModelingToolkit, OrdinaryDiffEq, Parameters

using Plots
toc()

# 🔹 Define struct for simulation settings
@with_kw mutable struct SimulationSettings @deftype Float64
    g_earth::Float64 = 0  # Gravity [m/s²]
    k::Float64 = 1.0  # Spring constant [N/m]
    m::Float64 = 1.0  # Mass of P2 and P3 [kg]
    F2::Float64 = 1  # External force on P2 [N]
    F3::Float64 = 1  # External force on P3 [N]
    l1::Float64 = sqrt(5)  # Rest length of spring P1-P2 [m]
    l2::Float64 = 2.0  # Rest length of spring P2-P3 [m]
    l3::Float64 = sqrt(5)  # Rest length of spring P3-P1 [m]
    duration::Float64 = 10.0  # Simulation time [s]
    save::Bool = false  # Whether to save animation frames
end

# Now, update the instance name:
se = SimulationSettings()

# 🔹 Define symbolic parameters (Using values from `Settings3`)
@parameters t k m g F2 F3 l1 l2 l3

# 🔹 Define symbolic state variables (positions & velocities)
@variables x2(t) y2(t) x3(t) y3(t) vx2(t) vy2(t) vx3(t) vy3(t)

# 🔹 Define differential operator
D = Differential(t)    

# 🔹 Define Hooke’s Law for spring force
function spring_force(xa, ya, xb, yb, l)
    dx = xb - xa
    dy = yb - ya
    length = sqrt(dx^2 + dy^2)  # Compute current length
    force_mag = k * (length - l)  # Hooke’s Law: F = -k (x - L0)
    fx = force_mag * dx / length
    fy = force_mag * dy / length
    
    return [fx, fy]
end

# 🔹 Define fixed anchor point P1 at (0,0)
x1, y1 = 0.0, 0.0

# 🔹 Compute forces symbolically
F_s1 = spring_force(x1, y1, x2, y2, l1)  # Force from P1 to P2
F_s2 = spring_force(x2, y2, x3, y3, l2)  # Force from P2 to P3
F_s3 = spring_force(x3, y3, x1, y1, l3)  # Force from P3 to P1

# 🔹 Net forces on P2
Fx2 = -F_s1[1] + F_s2[1]
Fy2 = -F_s1[2] + F_s2[2] + F2

# 🔹 Net forces on P3
Fx3 = -F_s2[1] + F_s3[1]
Fy3 = -F_s2[2] + F_s3[2] + F3

# 🔹 Equations of motion using Newton's second law: F = ma
eqs = [
    D(x2) ~ vx2,
    D(y2) ~ vy2,
    D(x3) ~ vx3,
    D(y3) ~ vy3,
    D(vx2) ~ Fx2 / m,
    D(vy2) ~ (Fy2 - m * g) / m,
    D(vx3) ~ Fx3 / m,
    D(vy3) ~ (Fy3 - m * g) / m
]

# 🔹 Create an ODE system
@named sys = ODESystem(eqs, t, [x2, y2, x3, y3, vx2, vy2, vx3, vy3], [m, k, g, F2, F3, l1, l2, l3])

# 🔹 Parameter values from `Settings3`
params = Dict(
    m => se.m,
    k => se.k,
    g => se.g_earth,
    F2 => se.F2,
    F3 => se.F3,
    l1 => se.l1,
    l2 => se.l2,
    l3 => se.l3
)

# 🔹 Initial conditions
u0 = Dict(
    x2 => -1.0, y2 => 2.0, x3 => 1.0, y3 => 2.0,
    vx2 => 0.0, vy2 => 0.0, vx3 => 0.0, vy3 => 0.0
)

# 🔹 Time span
tspan = (0.0, se.duration)

# 🔹 Convert symbolic system to an ODEProblem
prob = ODEProblem(complete(sys), u0, tspan, params)

# 🔹 Solve numerically
sol = solve(prob, Tsit5(), saveat=0.05)

# 🔹 Extract the solution
x2_sol = sol[x2, :]
y2_sol = sol[y2, :]
x3_sol = sol[x3, :]
y3_sol = sol[y3, :]
 
# # 🔹 Create animation
# anim = @animate for i in eachindex(x2_sol)
#     plot(xlim=(-1.5, 1.5), ylim=(-0.5, 6.0), legend=false, framestyle=:box, grid=false, size=(600, 600))

#     # Scatter plot for mass points
#     scatter!([0, x2_sol[i], x3_sol[i]], [0, y2_sol[i], y3_sol[i]], markersize=5, label="")

#     # Spring connections
#     plot!([0, x2_sol[i]], [0, y2_sol[i]], linewidth=2, color=:blue, label="")  # P1-P2
#     plot!([x2_sol[i], x3_sol[i]], [y2_sol[i], y3_sol[i]], linewidth=2, color=:red, label="")  # P2-P3
#     plot!([x3_sol[i], 0], [y3_sol[i], 0], linewidth=2, color=:green, label="")  # P3-P1
# end

How can this be resolved?
Kind regards Friso

Welcome Friso!

Can you post the output of:

versioninfo()

and the output of:

using Pkg
Pkg.status()

And you wrote “it stopped working”. What happens when you run your code? Is there an error message?

I tested your code on Ubuntu 24.04 using Julia 1.10.8 and it works fine.
I had to add the line:

gif(anim, "video/symbolic_mass_spring_simulation.gif", fps=30)

to save the result.
symbolic_mass_spring_simulation

2 Likes

Welcome to discourse @Friso

Further to @ufechner7 requests for info; Have you updated anything between yesterday and today? If yes, what and from which to which version(s).
Given the code works for @ufechner7, it must be something in your environment.

See Please read: make it easier to help you .
Try whittling your code down to a Minimum Working Example that still shows the error, instead of just dumping your entire code. This will a. often help you find the error yourself or b. make it easier for us to focus on the error.

BTW: You can measure how long it takes for the packages to load by simply using @time maco instead of Timers tic-toc

@time using ModelingToolkit, OrdinaryDiffEq, Parameters, Plots

I tested the script on Linux and on Windows.

Linux, AMD Ryzen 7850U

[ Info: Saved animation to /home/ufechner/repos/Tethers.jl/video/symbolic_mass_spring_simulation.gif
 17.842573 seconds (10.09 M allocations: 694.917 MiB, 2.44% gc time, 24.93% compilation time: 2% of which was recompilation)

Windows, i7-1265U

[ Info: Saved animation to C:\Users\ufechner\repos\Tethers.jl\video\symbolic_mass_spring_simulation.gif
538.429607 seconds (10.23 M allocations: 706.479 MiB, 0.10% gc time, 1.47% compilation time: 2% of which was recompilation)

So my Windows laptop is 30 times slower than Linux. OK, it is older and the CPU is slower, which might make it 2 times slower.

But is Windows 15 times slower than Linux?

This looks like a bug somewhere. Perhaps @Friso just did not wait long enough? Perhaps yesterday he used old package versions and they were 10 times faster?

1 Like

The output of versioninfo() :

versioninfo()
Julia Version 1.10.8
Commit 4c16ff44be (2025-01-22 10:06 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 16 × AMD Ryzen 7 PRO 8845HS w/ Radeon 780M Graphics
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, znver3)
Threads: 8 default, 0 interactive, 5 GC (on 16 virtual cores)

Pkg.status() :

`C:\Users\friso\Tethers\Tethers.jl\Project.toml`
  [8f4d0f93] Conda v1.10.2
  [992eb4ea] CondaPkg v0.2.24
  [23c2ee80] ControlPlots v0.2.5
  [0c46a032] DifferentialEquations v7.16.0
  [b964fa9f] LaTeXStrings v1.4.0
⌅ [7ed4a6bd] LinearSolve v2.39.0
  [16fef848] LiveServer v1.4.0
⌅ [961ee093] ModelingToolkit v9.40.1
⌅ [1dea7af3] OrdinaryDiffEq v6.89.0
  [9b87118b] PackageCompiler v2.2.0
  [d96e819e] Parameters v0.12.3
  [91a5bcdd] Plots v1.40.9
  [438e738f] PyCall v1.96.4
  [2913bbd2] StatsBase v0.34.4
⌅ [9672c7b4] SteadyStateDiffEq v2.4.0
⌅ [0c5d862f] Symbolics v6.13.1
  [21f18d07] Timers v0.1.5
  [37e2e46d] LinearAlgebra
  [44cfe95a] Pkg v1.10.0
  [8dfed614] Test
Info Packages marked with ⌅ have new versions available but compatibility constraints restrict them from upgrading. To see why use `status --outdated

I added line println("Frame: $i") and now it works, only slowly.

Yesterday it was very fast, what I changed was that I updated Julia to 1.10.8, and I updated the packages.

I had some performance issues in the past after small updates. Both Julia and ModelingToolkit have had some significant updates since your versions.
The trouble most likely being caused by some misaligned package between your current versions, a few things you could try:

  1. You have a lot of packages in this Environment compared to what you actually use, and something is holding back the versions of MTK and ODE. Try removing as many of the other pkgs as possible and see if you can update the packages you actually use. You could do this in a fresh project environment and add only the pkgs you need.

  2. Force the versions back to your old ones using
    Pkg.add("Packagename@v.X.xx)
    and see if that resolves the issue… although that might now work since you upgraded Julia itself.

  3. Update to the latest (Julia 1.11, MTK v9.62.0 etc) and hopefully whatever is causing your bug has been resolved in more recent versions. Note however that this is likely to introduce a few other breakages due to being major updates. (But MTK 9.62 does work slick with 3D Connectors now :slight_smile: )

@Friso Don’t update to newer versions. There is a good reason to keep the current versions. The performance issue of creating an animation with Plots.jl is not related to the versions of MTK or ODE.

It would be useful to create an MWE just for the performance of creating animations that does not use MTK or ODE.