3b1b-videos/_2024/chaos/lorenz.py

99 lines
2.7 KiB
Python
Raw Normal View History

2024-07-31 15:22:45 +02:00
from manim_imports_ext import *
from scipy.integrate import odeint
from scipy.integrate import solve_ivp
def lorenz_system(t, state, sigma=10, rho=28, beta=8 / 3):
x, y, z = state
dxdt = sigma * (y - x)
dydt = x * (rho - z) - y
dzdt = x * y - beta * z
return [dxdt, dydt, dzdt]
def ode_solution_points(function, state0, time, dt=0.01):
solution = solve_ivp(
function,
t_span=(0, time),
y0=state0,
t_eval=np.arange(0, time, dt)
)
return solution.y.T
class LorenzAttractor(InteractiveScene):
def construct(self):
# Set up axes
axes = ThreeDAxes(
x_range=(-50, 50, 5),
y_range=(-50, 50, 5),
z_range=(-0, 50, 5),
width=16,
height=16,
depth=8,
)
axes.set_width(FRAME_WIDTH)
axes.center()
self.frame.reorient(43, 76, 1, IN, 10)
self.add(axes)
# Add the equations
equations = Tex(
R"""
\begin{aligned}
\frac{\mathrm{d} x}{\mathrm{~d} t} & =\sigma(y-x) \\
\frac{\mathrm{d} y}{\mathrm{~d} t} & =x(\rho-z)-y \\
\frac{\mathrm{d} z}{\mathrm{~d} t} & =x y-\beta z .
\end{aligned}
""",
t2c={
"x": RED,
"y": GREEN,
"z": BLUE,
},
font_size=30
)
equations.fix_in_frame()
equations.to_corner(UL)
equations.set_backstroke()
self.play(Write(equations))
# Display Lorenz solutions
epsilon = 0.001
evolution_time = 120
states = [
[10, 10, 10 + n * epsilon]
for n in range(10)
]
colors = color_gradient([BLUE_E, BLUE_A], len(states))
curves = VGroup()
for state, color in zip(states, colors):
points = ode_solution_points(lorenz_system, state, evolution_time)
curve = VMobject().set_points_as_corners(axes.c2p(*points.T))
curve.set_stroke(color, 2)
curves.add(curve)
dots = Group(GlowDot(color=color, radius=0.5) for color in colors)
curves.set_stroke(opacity=0)
tails = VGroup(
TracingTail(dot, time_traced=5).match_color(dot)
for dot in dots
)
self.add(dots)
self.add(curves)
self.add(tails)
self.add(equations)
self.play(
*(
MoveAlongPath(dot, curve, rate_func=linear)
for dot, curve in zip(dots, curves)
),
self.frame.animate.reorient(270, 72, 0, (0.0, 0.0, -1.0), 10.00),
run_time=evolution_time,
)
self.wait(5)