mirror of
https://github.com/3b1b/manim.git
synced 2025-09-19 04:41:56 +00:00
Up to the pont where phase space is introduced
This commit is contained in:
parent
0b56d6f311
commit
9cdf35475d
5 changed files with 348 additions and 97 deletions
|
@ -1,6 +1,7 @@
|
|||
from active_projects.ode.part1.pendulum import *
|
||||
from active_projects.ode.part1.staging import *
|
||||
from active_projects.ode.part1.pi_scenes import *
|
||||
from active_projects.ode.part1.wordy_scenes import *
|
||||
|
||||
OUTPUT_DIRECTORY = "ode/part1"
|
||||
ALL_SCENE_CLASSES = [
|
||||
|
@ -25,4 +26,7 @@ ALL_SCENE_CLASSES = [
|
|||
SubtleAirCurrents,
|
||||
DefineODE,
|
||||
ODEvsPDEinFrames,
|
||||
ProveTeacherWrong,
|
||||
SetAsideSeekingSolution,
|
||||
VisualizeStates,
|
||||
]
|
||||
|
|
|
@ -103,6 +103,95 @@ class FormulasAreLies(PiCreatureScene):
|
|||
return You().flip().to_corner(DR)
|
||||
|
||||
|
||||
class NewSceneName(Scene):
|
||||
class ProveTeacherWrong(TeacherStudentsScene):
|
||||
def construct(self):
|
||||
pass
|
||||
tex_config = {
|
||||
"tex_to_color_map": {"{\\theta}": BLUE}
|
||||
}
|
||||
func = TexMobject(
|
||||
"{\\theta}(t)", "=",
|
||||
"\\theta_0", "\\cos(\\sqrt{g / L} \\cdot t)",
|
||||
**tex_config,
|
||||
)
|
||||
d_func = TexMobject(
|
||||
"\\dot {\\theta}(t)", "=",
|
||||
"-\\left(\\sqrt{g / L}\\right)",
|
||||
"\\theta_0", "\\sin(\\sqrt{g / L} \\cdot t)",
|
||||
**tex_config,
|
||||
)
|
||||
dd_func = TexMobject(
|
||||
"\\ddot {\\theta}(t)", "=",
|
||||
"-\\left(g / L\\right)",
|
||||
"\\theta_0", "\\cos(\\sqrt{g / L} \\cdot t)",
|
||||
**tex_config,
|
||||
)
|
||||
ode = TexMobject(
|
||||
"\\ddot {\\theta}({t})", "=",
|
||||
"-\\mu \\dot {\\theta}({t})",
|
||||
"-{g \\over L} \\sin\\big({\\theta}({t})\\big)",
|
||||
**tex_config,
|
||||
)
|
||||
arrows = [TexMobject("\\Downarrow") for x in range(2)]
|
||||
|
||||
VGroup(func, d_func, dd_func, ode, *arrows).scale(0.7)
|
||||
|
||||
teacher = self.teacher
|
||||
you = self.students[2]
|
||||
|
||||
self.student_thinks(ode)
|
||||
you.add_updater(lambda m: m.look_at(func))
|
||||
self.teacher_holds_up(func)
|
||||
self.wait()
|
||||
|
||||
group = VGroup(arrows[0], d_func, arrows[1], dd_func)
|
||||
group.arrange(DOWN)
|
||||
group.move_to(func, DOWN)
|
||||
|
||||
arrow = Arrow(
|
||||
group.get_corner(UL),
|
||||
ode.get_top(),
|
||||
path_arc=PI / 2,
|
||||
)
|
||||
q_marks = VGroup(*[
|
||||
TexMobject("?").scale(1.5).next_to(
|
||||
arrow.point_from_proportion(a),
|
||||
UP
|
||||
)
|
||||
for a in np.linspace(0.2, 0.8, 5)
|
||||
])
|
||||
cycle_animation(VFadeInThenOut(
|
||||
q_marks,
|
||||
lag_ratio=0.2,
|
||||
run_time=4,
|
||||
rate_func=squish_rate_func(smooth, 0, 0.5)
|
||||
))
|
||||
|
||||
self.play(
|
||||
func.next_to, group, UP,
|
||||
LaggedStartMap(
|
||||
FadeInFrom, group,
|
||||
lambda m: (m, UP)
|
||||
),
|
||||
teacher.change, "guilty",
|
||||
you.change, "sassy",
|
||||
)
|
||||
|
||||
rect = SurroundingRectangle(
|
||||
VGroup(group, func)
|
||||
)
|
||||
dashed_rect = DashedVMobject(rect, num_dashes=75)
|
||||
animated_rect = AnimatedBoundary(dashed_rect, cycle_rate=1)
|
||||
|
||||
self.wait()
|
||||
self.add(animated_rect, q_marks)
|
||||
self.play(
|
||||
ShowCreation(arrow),
|
||||
# FadeInFromDown(q_mark),
|
||||
self.get_student_changes("confused", "confused")
|
||||
)
|
||||
self.wait(4)
|
||||
self.change_student_modes(
|
||||
*3 * ["pondering"],
|
||||
self.teacher.change, "maybe"
|
||||
)
|
||||
self.wait(8)
|
||||
|
|
|
@ -14,3 +14,19 @@ class You(PiCreature):
|
|||
CONFIG = {
|
||||
"color": BLUE_C,
|
||||
}
|
||||
|
||||
|
||||
def get_ode():
|
||||
tex_config = {
|
||||
"tex_to_color_map": {
|
||||
"{\\theta}": BLUE,
|
||||
"{t}": WHITE,
|
||||
}
|
||||
}
|
||||
ode = TexMobject(
|
||||
"\\ddot {\\theta}({t})", "=",
|
||||
"-\\mu \\dot {\\theta}({t})",
|
||||
"-{g \\over L} \\sin\\big({\\theta}({t})\\big)",
|
||||
**tex_config,
|
||||
)
|
||||
return ode
|
||||
|
|
|
@ -47,39 +47,6 @@ class VectorFieldTest(Scene):
|
|||
self.wait(10)
|
||||
|
||||
|
||||
class SmallAngleApproximationTex(Scene):
|
||||
def construct(self):
|
||||
approx = TexMobject(
|
||||
"\\sin", "(", "\\theta", ") \\approx \\theta",
|
||||
tex_to_color_map={"\\theta": RED},
|
||||
arg_separator="",
|
||||
)
|
||||
|
||||
implies = TexMobject("\\Downarrow")
|
||||
period = TexMobject(
|
||||
"\\text{Period}", "\\approx",
|
||||
"2\\pi \\sqrt{\\,{L} / {g}}",
|
||||
**Lg_formula_config,
|
||||
)
|
||||
group = VGroup(approx, implies, period)
|
||||
group.arrange(DOWN)
|
||||
|
||||
approx_brace = Brace(approx, UP, buff=SMALL_BUFF)
|
||||
approx_words = TextMobject(
|
||||
"For small $\\theta$",
|
||||
tex_to_color_map={"$\\theta$": RED},
|
||||
)
|
||||
approx_words.scale(0.75)
|
||||
approx_words.next_to(approx_brace, UP, SMALL_BUFF)
|
||||
|
||||
self.add(approx, approx_brace, approx_words)
|
||||
self.play(
|
||||
Write(implies),
|
||||
FadeInFrom(period, LEFT)
|
||||
)
|
||||
self.wait()
|
||||
|
||||
|
||||
class FollowThisThread(Scene):
|
||||
CONFIG = {
|
||||
"screen_rect_style": {
|
||||
|
@ -165,64 +132,6 @@ class FollowThisThread(Scene):
|
|||
self.wait()
|
||||
|
||||
|
||||
class StrogatzQuote(Scene):
|
||||
def construct(self):
|
||||
law_words = "laws of physics"
|
||||
language_words = "language of differential equations"
|
||||
author = "-Steven Strogatz"
|
||||
quote = TextMobject(
|
||||
"""
|
||||
\\Large
|
||||
``Since Newton, mankind has come to realize
|
||||
that the laws of physics are always expressed
|
||||
in the language of differential equations.''\\\\
|
||||
""" + author,
|
||||
alignment="",
|
||||
arg_separator=" ",
|
||||
substrings_to_isolate=[law_words, language_words, author]
|
||||
)
|
||||
law_part = quote.get_part_by_tex(law_words)
|
||||
language_part = quote.get_part_by_tex(language_words)
|
||||
author_part = quote.get_part_by_tex(author)
|
||||
quote.set_width(12)
|
||||
quote.to_edge(UP)
|
||||
quote[-2].shift(SMALL_BUFF * LEFT)
|
||||
author_part.shift(RIGHT + 0.5 * DOWN)
|
||||
author_part.scale(1.2, about_edge=UL)
|
||||
|
||||
movers = VGroup(*quote[:-1].family_members_with_points())
|
||||
for mover in movers:
|
||||
mover.save_state()
|
||||
disc = Circle(radius=0.05)
|
||||
disc.set_stroke(width=0)
|
||||
disc.set_fill(BLACK, 0)
|
||||
disc.move_to(mover)
|
||||
mover.become(disc)
|
||||
self.play(
|
||||
FadeInFrom(author_part, LEFT),
|
||||
LaggedStartMap(
|
||||
# FadeInFromLarge,
|
||||
# quote[:-1].family_members_with_points(),
|
||||
Restore, movers,
|
||||
lag_ratio=0.005,
|
||||
run_time=2,
|
||||
)
|
||||
# FadeInFromDown(quote[:-1]),
|
||||
# lag_ratio=0.01,
|
||||
)
|
||||
self.wait()
|
||||
self.play(
|
||||
Write(law_part.copy().set_color(YELLOW)),
|
||||
run_time=1,
|
||||
)
|
||||
self.wait()
|
||||
self.play(
|
||||
Write(language_part.copy().set_color(BLUE)),
|
||||
run_time=1.5,
|
||||
)
|
||||
self.wait(2)
|
||||
|
||||
|
||||
class ShowGravityAcceleration(Scene):
|
||||
def construct(self):
|
||||
self.add_gravity_field()
|
||||
|
@ -472,6 +381,7 @@ class DefineODE(Scene):
|
|||
self.show_value_slope_curvature()
|
||||
self.write_ode()
|
||||
self.show_second_order()
|
||||
self.show_higher_order_examples()
|
||||
self.show_changing_curvature_group()
|
||||
|
||||
def add_graph(self):
|
||||
|
@ -494,8 +404,8 @@ class DefineODE(Scene):
|
|||
de_word.to_edge(UP)
|
||||
|
||||
equation = TexMobject(
|
||||
"\\ddot \\theta({t}) = "
|
||||
"-\\mu \\dot \\theta({t})"
|
||||
"\\ddot \\theta({t})", "=",
|
||||
"-\\mu \\dot \\theta({t})",
|
||||
"-{g \\over L} \\sin\\big(\\theta({t})\\big)",
|
||||
tex_to_color_map={
|
||||
"\\theta": BLUE,
|
||||
|
@ -693,6 +603,7 @@ class DefineODE(Scene):
|
|||
v_line, slope_line, curve, dot
|
||||
)
|
||||
self.curvature_group_labels = VGroup(thetas, words)
|
||||
self.fake_graph = graph
|
||||
|
||||
def write_ode(self):
|
||||
equation = self.equation
|
||||
|
@ -761,12 +672,102 @@ class DefineODE(Scene):
|
|||
self.ode_initials = ode_initials
|
||||
|
||||
def show_second_order(self):
|
||||
pass
|
||||
so = TextMobject("Second order")
|
||||
so.scale(1.4)
|
||||
ode = self.ode_initials
|
||||
ode.generate_target()
|
||||
group = VGroup(so, ode.target)
|
||||
group.arrange(RIGHT, aligned_edge=DOWN)
|
||||
group.to_edge(UP, buff=MED_SMALL_BUFF)
|
||||
|
||||
second_deriv = self.equation[:5]
|
||||
|
||||
self.play(
|
||||
Write(so),
|
||||
MoveToTarget(ode),
|
||||
)
|
||||
self.wait()
|
||||
self.play(FocusOn(second_deriv))
|
||||
self.play(
|
||||
Indicate(second_deriv, color=RED),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
self.second_order_word = so
|
||||
|
||||
def show_higher_order_examples(self):
|
||||
main_example = VGroup(
|
||||
self.second_order_word,
|
||||
self.ode_initials,
|
||||
self.equation
|
||||
)
|
||||
tex_config = {"tex_to_color_map": {"{x}": BLUE}}
|
||||
example3 = VGroup(
|
||||
TextMobject("Third order ODE"),
|
||||
TexMobject(
|
||||
"\\dddot {x}(t) + \\dot {x}(t)^2 = 0",
|
||||
**tex_config,
|
||||
)
|
||||
)
|
||||
example4 = VGroup(
|
||||
TextMobject("Fourth order ODE"),
|
||||
TexMobject(
|
||||
"\\ddddot {x}(t) +",
|
||||
"a\\dddot {x}(t) \\dot {x}(t) + ",
|
||||
"b \\ddot {x}(t) {x}(t)",
|
||||
"= 1",
|
||||
**tex_config,
|
||||
)
|
||||
)
|
||||
for example in [example3, example4]:
|
||||
example[0].scale(1.2)
|
||||
example.arrange(DOWN, buff=MED_LARGE_BUFF)
|
||||
example.to_edge(UP, buff=MED_SMALL_BUFF)
|
||||
|
||||
self.play(
|
||||
FadeOut(main_example),
|
||||
FadeIn(example3),
|
||||
)
|
||||
self.wait(2)
|
||||
self.play(
|
||||
FadeOut(example3),
|
||||
FadeIn(example4),
|
||||
)
|
||||
self.wait(2)
|
||||
self.play(
|
||||
FadeOut(example4),
|
||||
FadeIn(main_example),
|
||||
)
|
||||
self.wait(2)
|
||||
|
||||
def show_changing_curvature_group(self):
|
||||
pass
|
||||
t_tracker = self.t_tracker
|
||||
curvature_group = self.curvature_group
|
||||
labels = self.curvature_group_labels
|
||||
graph = VMobject()
|
||||
graph.pointwise_become_partial(
|
||||
self.fake_graph,
|
||||
0.25, 1,
|
||||
)
|
||||
dashed_graph = DashedVMobject(graph, num_dashes=100)
|
||||
dashed_graph.set_stroke(GREEN, 1)
|
||||
|
||||
self.play(FadeOut(labels))
|
||||
self.add(dashed_graph, curvature_group)
|
||||
self.play(
|
||||
t_tracker.set_value, 10,
|
||||
ShowCreation(dashed_graph),
|
||||
run_time=15,
|
||||
rate_func=linear,
|
||||
)
|
||||
self.wait()
|
||||
|
||||
|
||||
class ODEvsPDEinFrames(Scene):
|
||||
def construct(self):
|
||||
pass
|
||||
|
||||
|
||||
class VisualizeStates(Scene):
|
||||
def construct(self):
|
||||
pass
|
||||
|
|
141
active_projects/ode/part1/wordy_scenes.py
Normal file
141
active_projects/ode/part1/wordy_scenes.py
Normal file
|
@ -0,0 +1,141 @@
|
|||
from big_ol_pile_of_manim_imports import *
|
||||
from active_projects.ode.part1.shared_constructs import *
|
||||
|
||||
|
||||
class SmallAngleApproximationTex(Scene):
|
||||
def construct(self):
|
||||
approx = TexMobject(
|
||||
"\\sin", "(", "\\theta", ") \\approx \\theta",
|
||||
tex_to_color_map={"\\theta": RED},
|
||||
arg_separator="",
|
||||
)
|
||||
|
||||
implies = TexMobject("\\Downarrow")
|
||||
period = TexMobject(
|
||||
"\\text{Period}", "\\approx",
|
||||
"2\\pi \\sqrt{\\,{L} / {g}}",
|
||||
**Lg_formula_config,
|
||||
)
|
||||
group = VGroup(approx, implies, period)
|
||||
group.arrange(DOWN)
|
||||
|
||||
approx_brace = Brace(approx, UP, buff=SMALL_BUFF)
|
||||
approx_words = TextMobject(
|
||||
"For small $\\theta$",
|
||||
tex_to_color_map={"$\\theta$": RED},
|
||||
)
|
||||
approx_words.scale(0.75)
|
||||
approx_words.next_to(approx_brace, UP, SMALL_BUFF)
|
||||
|
||||
self.add(approx, approx_brace, approx_words)
|
||||
self.play(
|
||||
Write(implies),
|
||||
FadeInFrom(period, LEFT)
|
||||
)
|
||||
self.wait()
|
||||
|
||||
|
||||
class StrogatzQuote(Scene):
|
||||
def construct(self):
|
||||
law_words = "laws of physics"
|
||||
language_words = "language of differential equations"
|
||||
author = "-Steven Strogatz"
|
||||
quote = TextMobject(
|
||||
"""
|
||||
\\Large
|
||||
``Since Newton, mankind has come to realize
|
||||
that the laws of physics are always expressed
|
||||
in the language of differential equations.''\\\\
|
||||
""" + author,
|
||||
alignment="",
|
||||
arg_separator=" ",
|
||||
substrings_to_isolate=[law_words, language_words, author]
|
||||
)
|
||||
law_part = quote.get_part_by_tex(law_words)
|
||||
language_part = quote.get_part_by_tex(language_words)
|
||||
author_part = quote.get_part_by_tex(author)
|
||||
quote.set_width(12)
|
||||
quote.to_edge(UP)
|
||||
quote[-2].shift(SMALL_BUFF * LEFT)
|
||||
author_part.shift(RIGHT + 0.5 * DOWN)
|
||||
author_part.scale(1.2, about_edge=UL)
|
||||
|
||||
movers = VGroup(*quote[:-1].family_members_with_points())
|
||||
for mover in movers:
|
||||
mover.save_state()
|
||||
disc = Circle(radius=0.05)
|
||||
disc.set_stroke(width=0)
|
||||
disc.set_fill(BLACK, 0)
|
||||
disc.move_to(mover)
|
||||
mover.become(disc)
|
||||
self.play(
|
||||
FadeInFrom(author_part, LEFT),
|
||||
LaggedStartMap(
|
||||
# FadeInFromLarge,
|
||||
# quote[:-1].family_members_with_points(),
|
||||
Restore, movers,
|
||||
lag_ratio=0.005,
|
||||
run_time=2,
|
||||
)
|
||||
# FadeInFromDown(quote[:-1]),
|
||||
# lag_ratio=0.01,
|
||||
)
|
||||
self.wait()
|
||||
self.play(
|
||||
Write(law_part.copy().set_color(YELLOW)),
|
||||
run_time=1,
|
||||
)
|
||||
self.wait()
|
||||
self.play(
|
||||
Write(language_part.copy().set_color(BLUE)),
|
||||
run_time=1.5,
|
||||
)
|
||||
self.wait(2)
|
||||
|
||||
|
||||
class SetAsideSeekingSolution(Scene):
|
||||
def construct(self):
|
||||
ode = get_ode()
|
||||
ode.to_edge(UP)
|
||||
q1 = TextMobject("Find an exact solution")
|
||||
q1.set_color(YELLOW)
|
||||
q2 = TexMobject(
|
||||
"\\text{What is }", "\\theta", "(t)",
|
||||
"\\text{'s personality?}",
|
||||
tex_to_color_map={"\\theta": BLUE},
|
||||
arg_separator="",
|
||||
)
|
||||
theta = q2.get_part_by_tex("\\theta")
|
||||
|
||||
for q in q1, q2:
|
||||
q.scale(1.5)
|
||||
q.next_to(ode, DOWN, MED_LARGE_BUFF)
|
||||
eyes = Eyes(theta, height=0.1)
|
||||
|
||||
self.add(ode)
|
||||
self.add(q1)
|
||||
self.wait()
|
||||
self.play(
|
||||
q1.scale, 0.3,
|
||||
q1.to_corner, UR, MED_SMALL_BUFF,
|
||||
)
|
||||
self.play(FadeInFrom(q2, DOWN))
|
||||
self.play(
|
||||
eyes.blink,
|
||||
rate_func=lambda t: smooth(1 - t),
|
||||
)
|
||||
self.play(eyes.look_at, q2.get_left())
|
||||
self.play(eyes.look_at, q2.get_right())
|
||||
self.play(
|
||||
eyes.blink,
|
||||
rate_func=squish_rate_func(there_and_back)
|
||||
)
|
||||
self.wait()
|
||||
self.play(
|
||||
eyes.change_mode, "confused",
|
||||
eyes.look_at, ode.get_left(),
|
||||
)
|
||||
self.play(
|
||||
eyes.blink,
|
||||
rate_func=squish_rate_func(there_and_back)
|
||||
)
|
Loading…
Add table
Reference in a new issue