Files
manim/active_projects/diffyq/part3/wordy_scenes.py
2019-06-19 16:24:44 -07:00

920 lines
25 KiB
Python

from manimlib.imports import *
from active_projects.diffyq.part2.wordy_scenes import *
class ThreeMainObservations(Scene):
def construct(self):
fourier = ImageMobject("Joseph Fourier")
name = TextMobject("Joseph Fourier")
name.match_width(fourier)
name.next_to(fourier, DOWN, SMALL_BUFF)
fourier.add(name)
fourier.set_height(5)
fourier.to_corner(DR)
fourier.shift(LEFT)
bubble = ThoughtBubble(
direction=RIGHT,
height=3,
width=4,
)
bubble.move_tip_to(fourier.get_corner(UL) + 0.5 * DR)
observations = VGroup(
TextMobject(
"1)",
"Sine = Nice",
),
TextMobject(
"2)",
"Linearity"
),
TextMobject(
"3)",
"Fourier series"
),
)
# heart = SuitSymbol("hearts")
# heart.replace(observations[0][2])
# observations[0][2].become(heart)
# observations[0][1].add(happiness)
# observations[2][2].align_to(
# observations[2][1], LEFT,
# )
observations.arrange(
DOWN,
aligned_edge=LEFT,
buff=2 * LARGE_BUFF,
)
observations.set_height(FRAME_HEIGHT - 2)
observations.to_corner(UL, buff=LARGE_BUFF)
self.add(fourier)
self.play(ShowCreation(bubble))
self.wait()
self.play(LaggedStart(*[
TransformFromCopy(bubble, observation[0])
for observation in observations
], lag_ratio=0.2))
self.play(
FadeOut(fourier),
FadeOut(bubble),
)
self.wait()
for obs in observations:
self.play(FadeInFrom(obs[1], LEFT))
self.wait()
class LastChapterWrapper(Scene):
def construct(self):
full_rect = FullScreenFadeRectangle(
fill_color=DARK_GREY,
fill_opacity=1,
)
rect = ScreenRectangle(height=6)
rect.set_stroke(WHITE, 2)
rect.set_fill(BLACK, 1)
title = TextMobject("Last chapter")
title.scale(2)
title.to_edge(UP)
rect.next_to(title, DOWN)
self.add(full_rect)
self.play(
FadeIn(rect),
Write(title, run_time=2),
)
self.wait()
class ThreeConstraints(WriteHeatEquationTemplate):
def construct(self):
self.cross_out_solving()
self.show_three_conditions()
def cross_out_solving(self):
equation = self.get_d1_equation()
words = TextMobject("Solve this equation")
words.to_edge(UP)
equation.next_to(words, DOWN)
cross = Cross(words)
self.add(words, equation)
self.wait()
self.play(ShowCreation(cross))
self.wait()
self.equation = equation
self.to_remove = VGroup(words, cross)
def show_three_conditions(self):
equation = self.equation
to_remove = self.to_remove
title = TexMobject(
"\\text{Constraints }"
"T({x}, {t})"
"\\text{ must satisfy:}",
**self.tex_mobject_config
)
title.to_edge(UP)
items = VGroup(
TextMobject("1)", "The PDE"),
TextMobject("2)", "Boundary condition"),
TextMobject("3)", "Initial condition"),
)
items.scale(0.7)
items.arrange(RIGHT, buff=LARGE_BUFF)
items.set_width(FRAME_WIDTH - 2)
items.next_to(title, DOWN, LARGE_BUFF)
items[1].set_color(MAROON_B)
items[2].set_color(RED)
bc_paren = TextMobject("(Explained soon)")
bc_paren.scale(0.7)
bc_paren.next_to(items[1], DOWN)
self.play(
FadeInFromDown(title),
FadeOutAndShift(to_remove, UP),
equation.scale, 0.6,
equation.next_to, items[0], DOWN,
equation.shift_onto_screen,
LaggedStartMap(FadeIn, [
items[0],
items[1][0],
items[2][0],
])
)
self.wait()
self.play(Write(items[1][1]))
bc_paren.match_y(equation)
self.play(FadeInFrom(bc_paren, UP))
self.wait(2)
self.play(Write(items[2][1]))
self.wait(2)
self.title = title
self.items = items
self.pde = equation
self.bc_paren = bc_paren
class RectAroundEquation(WriteHeatEquationTemplate):
def construct(self):
eq = self.get_d1_equation()
self.play(ShowCreationThenFadeAround(eq))
class BorderRect(Scene):
def construct(self):
rect = FullScreenFadeRectangle()
rect.set_stroke(WHITE, 3)
rect.set_fill(opacity=0)
self.add(rect)
class SeekIdealized(Scene):
def construct(self):
phrases = VGroup(*[
TextMobject(
"Seek", text, "problems",
tex_to_color_map={
"realistic": GREEN,
"{idealized}": YELLOW,
"over-idealized": YELLOW,
"general": BLUE,
}
)
for text in [
"realistic",
"{idealized}",
"over-idealized",
"general",
]
])
phrases.scale(2)
words = VGroup()
for phrase in phrases:
phrase.center()
word = phrase[1]
words.add(word)
phrase.remove(word)
arrow = Vector(DOWN)
arrow.set_stroke(WHITE, 6)
arrow.next_to(words[3], UP)
low_arrow = arrow.copy()
low_arrow.next_to(words[3], DOWN)
solutions = TextMobject("solutions")
solutions.scale(2)
solutions.move_to(phrases[3][1], UL)
models = TextMobject("models")
models.scale(2)
models.next_to(
words[0], RIGHT, buff=0.35,
aligned_edge=DOWN
)
phrases.center()
phrase = phrases[0]
self.add(phrase)
self.add(words[0])
self.wait()
words[0].save_state()
self.play(
words[0].to_edge, DOWN,
words[0].set_opacity, 0.5,
Transform(phrase, phrases[1]),
FadeInFrom(words[1], UP)
)
self.wait()
# self.play(
# words[1].move_to, words[2], RIGHT,
# FadeIn(words[2]),
# Transform(phrase, phrases[2])
# )
# self.wait()
self.play(
words[1].next_to, arrow, UP,
ShowCreation(arrow),
MaintainPositionRelativeTo(
phrase, words[1]
),
FadeInFrom(solutions, LEFT),
FadeIn(words[3]),
)
self.wait()
words[0].generate_target()
words[0].target.next_to(low_arrow, DOWN)
words[0].target.set_opacity(1)
models.shift(
words[0].target.get_center() -
words[0].saved_state.get_center()
)
self.play(
MoveToTarget(words[0]),
ShowCreation(low_arrow),
FadeInFrom(models, LEFT)
)
self.wait()
class SecondDerivativeOfSine(Scene):
def construct(self):
equation = TexMobject(
"{d^2 \\over d{x}^2}",
"\\cos\\left({x}\\right) =",
"-\\cos\\left({x}\\right)",
tex_to_color_map={
"{x}": GREEN,
}
)
self.add(equation)
class EquationAboveSineAnalysis(WriteHeatEquationTemplate):
def construct(self):
equation = self.get_d1_equation()
equation.to_edge(UP)
equation.shift(2 * LEFT)
eq_index = equation.index_of_part_by_tex("=")
lhs = equation[:eq_index]
eq = equation[eq_index]
rhs = equation[eq_index + 1:]
t_terms = equation.get_parts_by_tex("{t}")[1:]
t_terms.save_state()
zeros = VGroup(*[
TexMobject("0").replace(t, dim_to_match=1)
for t in t_terms
])
zeros.align_to(t_terms, DOWN)
new_rhs = TexMobject(
"=", "-\\alpha \\cdot {T}", "({x}, 0)",
**self.tex_mobject_config
)
# new_rhs.move_to(equation.get_right())
# new_rhs.next_to(equation, DOWN, MED_LARGE_BUFF)
# new_rhs.align_to(eq, LEFT)
new_rhs.next_to(equation, RIGHT)
new_rhs.shift(SMALL_BUFF * DOWN)
self.add(equation)
self.play(ShowCreationThenFadeAround(rhs))
self.wait()
self.play(
FadeOutAndShift(t_terms, UP),
FadeInFrom(zeros, DOWN),
)
t_terms.fade(1)
self.wait()
self.play(
# VGroup(equation, zeros).next_to,
# new_rhs, LEFT,
FadeIn(new_rhs),
)
self.wait()
self.play(
VGroup(
lhs[6:],
eq,
rhs,
new_rhs[0],
new_rhs[-3:],
zeros,
).fade, 0.5,
)
self.play(ShowCreationThenFadeAround(lhs[:6]))
self.play(ShowCreationThenFadeAround(new_rhs[1:-3]))
self.wait()
class ExpVideoWrapper(Scene):
def construct(self):
self.add(FullScreenFadeRectangle(
fill_color=DARKER_GREY,
fill_opacity=1,
))
screen = ImageMobject("eoc_chapter5_thumbnail")
screen.set_height(6)
rect = SurroundingRectangle(screen, buff=0)
rect.set_stroke(WHITE, 2)
screen.add(rect)
title = TextMobject("Need a refresher?")
title.scale(1.5)
title.to_edge(UP)
screen.next_to(title, DOWN)
screen.center()
self.play(
# FadeInFrom(title, LEFT),
FadeInFrom(screen, DOWN),
)
self.wait()
class ShowSinExpDerivatives(WriteHeatEquationTemplate):
CONFIG = {
"tex_mobject_config": {
"tex_to_color_map": {
"{0}": WHITE,
"\\partial": WHITE,
"=": WHITE,
}
}
}
def construct(self):
pde = self.get_d1_equation_without_inputs()
pde.to_edge(UP)
pde.generate_target()
new_rhs = TexMobject(
"=- \\alpha \\cdot T",
**self.tex_mobject_config,
)
new_rhs.next_to(pde, RIGHT)
new_rhs.align_to(pde.get_part_by_tex("alpha"), DOWN)
equation1 = TexMobject(
"T({x}, {0}) = \\sin\\left({x}\\right)",
**self.tex_mobject_config
)
equation2 = TexMobject(
"T({x}, {t}) = \\sin\\left({x}\\right)",
"e^{-\\alpha{t}}",
**self.tex_mobject_config
)
for eq in equation1, equation2:
eq.next_to(pde, DOWN, MED_LARGE_BUFF)
eq2_part1 = equation2[:len(equation1)]
eq2_part2 = equation2[len(equation1):]
# Rectangles
exp_rect = SurroundingRectangle(eq2_part2)
exp_rect.set_stroke(RED, 3)
sin_rect = SurroundingRectangle(
eq2_part1[-3:]
)
sin_rect.set_color(BLUE)
VGroup(pde.target, new_rhs).center().to_edge(UP)
# Show proposed solution
self.add(pde)
self.add(equation1)
self.wait()
self.play(
MoveToTarget(pde),
FadeInFrom(new_rhs, LEFT)
)
self.wait()
self.play(
ReplacementTransform(equation1, eq2_part1),
FadeIn(eq2_part2),
)
self.play(ShowCreation(exp_rect))
self.wait()
self.play(FadeOut(exp_rect))
# Take partial derivatives wrt x
q_mark = TexMobject("?")
q_mark.next_to(pde.get_part_by_tex("="), UP)
q_mark.set_color(RED)
arrow1 = Vector(3 * DOWN + 1 * RIGHT, color=WHITE)
arrow1.scale(1.2 / arrow1.get_length())
arrow1.next_to(
eq2_part2.get_corner(DL),
DOWN, MED_LARGE_BUFF
)
ddx_label1 = TexMobject(
"\\partial \\over \\partial {x}",
**self.tex_mobject_config,
)
ddx_label1.scale(0.7)
ddx_label1.next_to(
arrow1.point_from_proportion(0.8),
UR, SMALL_BUFF
)
pde_ddx = VGroup(
*pde.get_parts_by_tex("\\partial")[2:],
pde.get_parts_by_tex("\\over")[1],
pde.get_part_by_tex("{x}"),
)
pde_ddx_rect = SurroundingRectangle(pde_ddx)
pde_ddx_rect.set_color(GREEN)
eq2_part2_rect = SurroundingRectangle(eq2_part2)
dx = TexMobject(
"\\cos\\left({x}\\right)", "e^{-\\alpha {t}}",
**self.tex_mobject_config
)
ddx = TexMobject(
"-\\sin\\left({x}\\right)", "e^{-\\alpha {t}}",
**self.tex_mobject_config
)
dx.next_to(arrow1, DOWN)
dx.align_to(eq2_part2, RIGHT)
x_shift = arrow1.get_end()[0] - arrow1.get_start()[0]
x_shift *= 2
dx.shift(x_shift * RIGHT)
arrow2 = arrow1.copy()
arrow2.next_to(dx, DOWN)
arrow2.shift(MED_SMALL_BUFF * RIGHT)
dx_arrows = VGroup(arrow1, arrow2)
ddx_label2 = ddx_label1.copy()
ddx_label2.shift(
arrow2.get_center() - arrow1.get_center()
)
ddx.next_to(arrow2, DOWN)
ddx.align_to(eq2_part2, RIGHT)
ddx.shift(2 * x_shift * RIGHT)
rhs = equation2[-6:]
self.play(
FadeInFromDown(q_mark)
)
self.play(
ShowCreation(pde_ddx_rect)
)
self.wait()
self.play(
LaggedStart(
GrowArrow(arrow1),
GrowArrow(arrow2),
),
TransformFromCopy(
pde_ddx[0], ddx_label1
),
TransformFromCopy(
pde_ddx[0], ddx_label2
),
)
self.wait()
self.play(
TransformFromCopy(rhs, dx)
)
self.wait()
self.play(
FadeIn(eq2_part2_rect)
)
self.play(
Transform(
eq2_part2_rect,
SurroundingRectangle(dx[-3:])
)
)
self.play(
FadeOut(eq2_part2_rect)
)
self.wait()
self.play(
TransformFromCopy(dx, ddx)
)
self.play(
FadeIn(
SurroundingRectangle(ddx).match_style(
pde_ddx_rect
)
)
)
self.wait()
# Take partial derivative wrt t
pde_ddt = pde[:pde.index_of_part_by_tex("=") - 1]
pde_ddt_rect = SurroundingRectangle(pde_ddt)
dt_arrow = Arrow(
arrow1.get_start(),
arrow2.get_end() + RIGHT,
buff=0
)
dt_arrow.flip(UP)
dt_arrow.next_to(dx_arrows, LEFT, MED_LARGE_BUFF)
dt_label = TexMobject(
"\\partial \\over \\partial {t}",
**self.tex_mobject_config,
)
dt_label.scale(1)
dt_label.next_to(
dt_arrow.get_center(), UL,
SMALL_BUFF,
)
rhs_copy = rhs.copy()
rhs_copy.next_to(dt_arrow.get_end(), DOWN)
rhs_copy.shift(MED_LARGE_BUFF * LEFT)
rhs_copy.match_y(ddx)
minus_alpha_in_exp = rhs_copy[-3][1:].copy()
minus_alpha_in_exp.set_color(RED)
minus_alpha = TexMobject("-\\alpha")
minus_alpha.next_to(rhs_copy, LEFT)
minus_alpha.align_to(rhs_copy[0][0], DOWN)
dot = TexMobject("\\cdot")
dot.move_to(midpoint(
minus_alpha.get_right(),
rhs_copy.get_left(),
))
self.play(
TransformFromCopy(
pde_ddx_rect,
pde_ddt_rect,
)
)
self.play(
GrowArrow(dt_arrow),
TransformFromCopy(
pde_ddt,
dt_label,
)
)
self.wait()
self.play(TransformFromCopy(rhs, rhs_copy))
self.play(FadeIn(minus_alpha_in_exp))
self.play(
ApplyMethod(
minus_alpha_in_exp.replace, minus_alpha,
path_arc=TAU / 4
),
FadeIn(dot),
)
self.play(
FadeIn(minus_alpha),
FadeOut(minus_alpha_in_exp),
)
self.wait()
rhs_copy.add(minus_alpha, dot)
self.play(
FadeIn(SurroundingRectangle(rhs_copy))
)
self.wait()
#
checkmark = TexMobject("\\checkmark")
checkmark.set_color(GREEN)
checkmark.move_to(q_mark, DOWN)
self.play(
FadeInFromDown(checkmark),
FadeOutAndShift(q_mark, UP)
)
self.wait()
class DerivativesOfLinearFunction(WriteHeatEquationTemplate):
CONFIG = {
"tex_mobject_config": {
"tex_to_color_map": {
"{c}": WHITE,
}
}
}
def construct(self):
func = TexMobject(
"T({x}, {t}) = {c} \\cdot {x}",
**self.tex_mobject_config
)
dx_T = TexMobject("{c}", **self.tex_mobject_config)
ddx_T = TexMobject("0")
dt_T = TexMobject("0")
for mob in func, dx_T, ddx_T, dt_T:
mob.scale(1.5)
func.generate_target()
arrows = VGroup(*[
Vector(1.5 * RIGHT, color=WHITE)
for x in range(3)
])
dx_arrows = arrows[:2]
dt_arrow = arrows[2]
dt_arrow.rotate(-TAU / 4)
dx_group = VGroup(
func.target,
dx_arrows[0],
dx_T,
dx_arrows[1],
ddx_T,
)
dx_group.arrange(RIGHT)
for arrow, char, vect in zip(arrows, "xxt", [UP, UP, RIGHT]):
label = TexMobject(
"\\partial \\over \\partial {%s}" % char,
**self.tex_mobject_config
)
label.scale(0.7)
label.next_to(arrow.get_center(), vect)
arrow.add(label)
dt_arrow.shift(
func.target[-3:].get_bottom() + MED_SMALL_BUFF * DOWN -
dt_arrow.get_start(),
)
dt_T.next_to(dt_arrow.get_end(), DOWN)
self.play(FadeInFromDown(func))
self.wait()
self.play(
MoveToTarget(func),
LaggedStartMap(Write, dx_arrows),
run_time=1,
)
self.play(
TransformFromCopy(func[-3:], dx_T),
path_arc=-TAU / 4,
)
self.play(
TransformFromCopy(dx_T, ddx_T),
path_arc=-TAU / 4,
)
self.wait()
# dt
self.play(Write(dt_arrow))
self.play(
TransformFromCopy(func[-3:], dt_T)
)
self.wait()
class FlatAtBoundaryWords(Scene):
def construct(self):
words = self.get_bc_words()
self.play(Write(words))
self.wait()
def get_bc_words(self):
return TextMobject(
"Flat at boundary\\\\"
"for all", "${t}$", "$> 0$",
)
class WriteOutBoundaryCondition(FlatAtBoundaryWords, ThreeConstraints, MovingCameraScene):
def construct(self):
self.force_skipping()
ThreeConstraints.construct(self)
self.revert_to_original_skipping_status()
self.add_ic()
self.write_bc_words()
self.write_bc_equation()
def add_ic(self):
image = ImageMobject("temp_initial_condition_example")
image.set_width(3)
border = SurroundingRectangle(image, buff=SMALL_BUFF)
border.shift(SMALL_BUFF * UP)
border.set_stroke(WHITE, 2)
group = Group(image, border)
group.next_to(self.items[2], DOWN)
self.add(group)
def write_bc_words(self):
bc_paren = self.bc_paren
bc_words = self.get_bc_words()
bc_words.match_width(self.items[1][1])
bc_words.move_to(bc_paren, UP)
bc_words.set_color_by_tex("{t}", YELLOW)
self.play(ShowCreationThenFadeAround(
VGroup(self.items[0], self.pde)
))
self.play(
FadeOutAndShift(bc_paren, UP),
FadeInFrom(bc_words, DOWN),
)
self.wait()
self.bc_words = bc_words
def write_bc_equation(self):
bc_words = self.bc_words
equation = TexMobject(
"{\\partial {T} \\over \\partial {x}}(0, {t}) = ",
"{\\partial {T} \\over \\partial {x}}(L, {t}) = ",
"0",
**self.tex_mobject_config,
)
equation.next_to(bc_words, DOWN, MED_LARGE_BUFF)
self.play(
self.camera_frame.shift, 0.8 * DOWN,
)
self.play(FadeInFrom(equation, UP))
self.wait()
class HeatEquationFrame(WriteHeatEquationTemplate):
def construct(self):
equation = self.get_d1_equation()
equation.to_edge(UP, buff=MED_SMALL_BUFF)
ddx = equation[-11:]
dt = equation[:11]
full_rect = FullScreenFadeRectangle(
fill_color=DARK_GREY,
fill_opacity=1,
)
smaller_rect = ScreenRectangle(
height=6,
fill_color=BLACK,
fill_opacity=1,
stroke_color=WHITE,
stroke_width=2,
)
smaller_rect.next_to(equation, DOWN)
self.add(full_rect)
self.add(smaller_rect)
self.add(equation)
self.wait()
self.play(ShowCreationThenFadeAround(
ddx,
surrounding_rectangle_config={
"stroke_color": GREEN,
}
))
self.wait()
self.play(ShowCreationThenFadeAround(dt))
self.wait()
class CompareFreqDecays1to2(Scene):
CONFIG = {
"freqs": [1, 2]
}
def construct(self):
background = FullScreenFadeRectangle(
fill_color=DARKER_GREY,
fill_opacity=1,
)
screens = VGroup(*[
ScreenRectangle(
height=4,
fill_color=BLACK,
fill_opacity=1,
stroke_width=1,
stroke_color=WHITE,
)
for x in range(2)
])
screens.arrange(RIGHT)
screens.set_width(FRAME_WIDTH - 1)
formulas = VGroup(*[
self.get_formula(freq)
for freq in self.freqs
])
for formula, screen in zip(formulas, screens):
formula.next_to(screen, UP)
self.add(background)
self.add(screens)
self.add(formulas)
self.wait()
def get_formula(self, freq):
f_str = str(freq)
return TexMobject(
"\\cos\\left(%s \\cdot {x}\\right)" % f_str,
"e^{-\\alpha \\cdot %s^2 \\cdot {t}}" % f_str,
tex_to_color_map={
"{x}": GREEN,
"{t}": YELLOW,
f_str: MAROON_B,
}
)
class CompareFreqDecays1to4(CompareFreqDecays1to2):
CONFIG = {
"freqs": [1, 4],
}
class CompareFreqDecays2to4(CompareFreqDecays1to2):
CONFIG = {
"freqs": [2, 4],
}
class WorryAboutGenerality(TeacherStudentsScene, WriteHeatEquationTemplate):
def construct(self):
eq = self.get_d1_equation()
diffyq = self.get_diffyq_set()
is_in = TexMobject("\\in")
is_in.scale(2)
group = VGroup(eq, is_in, diffyq)
group.arrange(RIGHT, buff=MED_LARGE_BUFF)
group.to_edge(UP)
arrow = Vector(DOWN)
arrow.set_stroke(WHITE, 5)
arrow.next_to(eq, DOWN)
themes = TextMobject("Frequent themes")
themes.scale(1.5)
themes.next_to(arrow, DOWN)
self.play(
self.get_student_changes(
"sad", "tired", "pleading"
),
self.teacher.change, "raise_right_hand",
FadeInFromDown(eq)
)
self.play(Write(group[1:]))
self.wait(2)
self.play(
ShowCreation(arrow),
self.get_student_changes(*3 * ["pondering"]),
)
self.play(
FadeInFrom(themes, UP),
self.get_student_changes(*3 * ["thinking"]),
self.teacher.change, "happy"
)
self.wait(4)
# def get_d1_equation(self):
# result = super().get_d1_equation()
# lp, rp = parens = TexMobject("(", ")")
# parens.match_height(result)
# lp.next_to(result, LEFT, SMALL_BUFF)
# rp.next_to(result, RIGHT, SMALL_BUFF)
# result.add_to_back(lp)
# result.add(rp)
# return result
def get_diffyq_set(self):
words = TextMobject(
"Differential\\\\equations"
)
words.scale(1.5)
words.set_color(BLUE)
lb = Brace(words, LEFT)
rb = Brace(words, RIGHT)
return VGroup(lb, words, rb)