使用Julia的钟摆运动动画
这个例子展示了使用微分方程模拟物理摆的运动并用Julia编程语言创建动画的实现。
导言
钟摆是最简单的物理系统,广泛用于研究周期性运动和振荡。 在这个例子中,我们考虑了使用二阶常微分方程组对简单摆的运动进行建模的问题,然后使用搭配方法(MIRK)在边界值问题的框架中求解。 找到解决方案后,使用卢克索以GIF动画格式可视化。基于开罗的jl图书馆。
主要目标是展示Julia语言在物理问题数值解和图形可视化生成方面的能力。 动画可以让你了解钟摆运动的动态—它是如何随着时间的推移移动的,从给定的位置开始,在一定的时间间隔后在相反的点结束。
In [ ]:
# Установка требуемых пакетов
import Pkg; Pkg.add("Luxor")
import Pkg; Pkg.add("Colors")
import Pkg; Pkg.add("BoundaryValueDiffEq")
连接图书馆
In [ ]:
using Luxor # для рисования анимации
using Colors # для управления цветами элементов анимации
using BoundaryValueDiffEq # для решения краевых задач обыкновенных дифференциальных уравнений
定义模型的常量和参数
物理模型和动画的常数
In [ ]:
const g = 9.81; # ускорение свободного падения (м/с²)
const L = 1.0; # длина нити маятника (метры)
const bobd = 0.10; # диаметр груза (bob) маятника (в метрах)
动画参数
In [ ]:
const framerate = 50.0; # частота кадров анимации (кадр/сек)
const t_0 = 0.0; # начальное время моделирования (сек)
const tf = 2.3; # конечное время моделирования (сек)
const dtframe = 1.0/framerate; # длительность 1 кадра в секундах
const tspan = LinRange(t_0, tf, Int(floor(tf*framerate))); # массив моментов времени для анимации
颜色和文件名
In [ ]:
const bgcolor = "black"; # цвет фона анимации
const leaderhue = (0.80, 0.70, 0.20); # светло-золотой цвет для рычага
const hslcolors = [HSL(col) for col in (distinguishable_colors(
Int(floor(tf*framerate)+3),[RGB(1,1,1)])[2:end])]; # набор цветов для элементов
const giffilename = "pendulum.gif"; # имя выходного файла GIF
微分方程的问题和解决方案的制定
钟摆运动方程函数的定义
In [ ]:
function simplependulum(du, u, p, t)
θ = u[1] # угол отклонения
dθ = u[2] # скорость изменения угла (угловая скорость)
du[1] = dθ # производная угла = угловая скорость
du[2] = -(g/L) * sin(θ) # уравнение движения: θ'' = -(g/L) * sin(θ)
end
Out[0]:
设置边界条件
In [ ]:
function bc2(residual, u, p, t)
residual[1] = u[end÷2][1] + pi/2 # значение угла в середине интервала равно π/2 (положение слева)
residual[2] = u[end][1] - pi/2 # значение угла в конце равно -π/2 (положение справа)
end
Out[0]:
边界值问题的形成与解决
In [ ]:
bvp2 = BVProblem(simplependulum, bc2, [pi/2, pi/2], (tspan[1], tspan[end]));
sol2 = solve(bvp2, MIRK4(), dt=dtframe); # метод Рунге–Кутты 4-го порядка с коррекцией
动画渲染函数
渲染帧的背景函数
In [ ]:
function backdrop(scene, framenumber)
background(bgcolor) # установка черного фона
end
Out[0]:
绘制每个帧的主要功能是
In [ ]:
function anim_frame(scene, framenumber)
# Получаем текущие значения угла и угловой скорости
u1, u2 = sol2.u[framenumber]
# Вычисляем координаты центра боба по формулам тригонометрии
y = L * cos(u1)
x = L * sin(u1)
# Нарисовать рычаг (от точки подвеса до груза)
sethue(leaderhue)
poly([Point(-4.0, 0.0), Point(4.0, 0.0),
Point(160.0x, 160.0y)], :fill)
# Нарисовать груз (bob) маятника
sethue(Colors.HSV(framenumber*4.0, 1, 1)) # меняющийся цвет в зависимости от номера кадра
circle(Point(160.0x, 160.0y), 160*bobd, :fill)
# Напечатать информацию о текущем кадре
Luxor.text(string("frame $framenumber of $(scene.framerange.stop)"),
Point(0.0, -190.0), halign=:center)
end
Out[0]:
创建和播放动画
创建具有指定窗口大小的动画对象
In [ ]:
muv = Movie(400, 400, "Pendulum Demo", 1:length(tspan))
Out[0]:
添加两个场景:背景和主要场景
In [ ]:
Luxor.animate(muv, [
Luxor.Scene(muv, backdrop), # фоновая сцена
Luxor.Scene(muv, anim_frame, easingfunction=easeinoutcubic) # главная сцена с плавным переходом
], creategif=true, pathname=joinpath(@__DIR__, giffilename)) # создаём .gif и сохраняем его под именем "pendulum.gif"
Out[0]:
结论
我们回顾了Julia语言的一个程序,该程序解决了摆运动模型的边界值问题,并在此基础上构建了GIF格式的平滑动画。 关键要素:物理模型(运动方程),数值解(MIRK4方法)和可视化(使用卢克索)。 这种方法不仅适用于教育目的,而且适用于对初始或最终条件有约束的更复杂系统进行建模。 这个例子说明了Julia生态系统中强大的科学计算和图形可视化工具。
该示例是使用[罗塞塔代码]的材料开发的(https://rosettacode.org/wiki/Animate_a_pendulum )
