mirror of
https://github.com/3b1b/videos.git
synced 2025-08-21 05:43:57 +00:00
99 lines
2.7 KiB
Python
99 lines
2.7 KiB
Python
![]() |
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)
|