from manimlib.imports import * from active_projects.diffyq.part1.shared_constructs import * class SomeOfYouWatching(TeacherStudentsScene): CONFIG = { "camera_config": { "background_color": DARKER_GREY, } } def construct(self): screen = self.screen screen.scale(1.25, about_edge=UL) screen.set_fill(BLACK, 1) self.add(screen) self.teacher.change("raise_right_hand") for student in self.students: student.change("pondering", screen) self.student_says( "Well...yeah", target_mode="tease" ) self.wait(3) class FormulasAreLies(PiCreatureScene): def construct(self): you = self.pi_creature t2c = { "{L}": BLUE, "{g}": YELLOW, "\\theta_0": WHITE, "\\sqrt{\\,": WHITE, } kwargs = {"tex_to_color_map": t2c} period_eq = TexMobject( "\\text{Period} = 2\\pi \\sqrt{\\,{L} / {g}}", **kwargs ) theta_eq = TexMobject( "\\theta(t) = \\theta_0 \\cos\\left(" "\\sqrt{\\,{L} / {g}} \\cdot t" "\\right)", **kwargs ) equations = VGroup(theta_eq, period_eq) equations.arrange(DOWN, buff=LARGE_BUFF) for eq in period_eq, theta_eq: i = eq.index_of_part_by_tex("\\sqrt") eq.sqrt_part = eq[i:i + 4] theta0 = theta_eq.get_part_by_tex("\\theta_0") theta0_words = TextMobject("Starting angle") theta0_words.next_to(theta0, UL) theta0_words.shift(UP + 0.5 * RIGHT) arrow = Arrow( theta0_words.get_bottom(), theta0, color=WHITE, tip_length=0.25, ) bubble = SpeechBubble() bubble.pin_to(you) bubble.write("Lies!") bubble.content.scale(2) bubble.resize_to_content() self.add(period_eq) you.change("pondering", period_eq) self.wait() theta_eq.remove(*theta_eq.sqrt_part) self.play( TransformFromCopy( period_eq.sqrt_part, theta_eq.sqrt_part, ), FadeIn(theta_eq) ) theta_eq.add(*theta_eq.sqrt_part) self.play( FadeInFrom(theta0_words, LEFT), GrowArrow(arrow), ) self.wait() self.play(you.change, "confused") self.wait() self.play( you.change, "angry", ShowCreation(bubble), FadeInFromPoint(bubble.content, you.mouth), equations.to_edge, LEFT, FadeOut(arrow), FadeOut(theta0_words), ) self.wait() def create_pi_creature(self): return You().flip().to_corner(DR) # class TourOfDifferentialEquations(Scene): # def construct(self): # pass class SoWhatIsThetaThen(TeacherStudentsScene): def construct(self): ode = get_ode() ode.to_corner(UL) self.add(ode) self.student_says( "Okay, but then\\\\" "what \\emph{is} $\\theta(t)$?" ) self.wait() self.play(self.teacher.change, "happy") self.wait(2) self.teacher_says( "First, you must appreciate\\\\" "a deep truth...", added_anims=[self.get_student_changes( *3 * ["confused"] )] ) self.wait(4) class ProveTeacherWrong(TeacherStudentsScene): def construct(self): tex_config = { "tex_to_color_map": { "{\\theta}": BLUE, "{\\dot\\theta}": YELLOW, "{\\ddot\\theta}": RED, } } 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, # ) ode = get_ode() 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) class PhysicistPhaseSpace(PiCreatureScene): def construct(self): physy = self.pi_creature name = TextMobject("Physicist") name.scale(1.5) name.to_corner(DL, buff=MED_SMALL_BUFF) physy.next_to(name, UP, SMALL_BUFF) VGroup(name, physy).shift_onto_screen() axes = Axes( x_min=-1, x_max=10, y_min=-1, y_max=7, ) axes.set_height(6) axes.next_to(physy, RIGHT) axes.to_edge(UP) axes.set_stroke(width=1) x_label = TextMobject("Position") x_label.next_to(axes.x_axis.get_right(), UP) y_label = TextMobject("Momentum") y_label.next_to(axes.y_axis.get_top(), RIGHT) title = TextMobject("Phase space") title.scale(1.5) title.set_color(YELLOW) title.move_to(axes) self.add(name, physy) self.play( physy.change, "angry", Write(axes), FadeInFromDown(title) ) self.wait(2) self.play( GrowFromPoint(x_label, physy.get_corner(UR)), physy.change, "raise_right_hand", axes.x_axis.get_right() ) self.play( GrowFromPoint(y_label, physy.get_corner(UR)), physy.look_at, axes.y_axis.get_top(), ) self.wait(3) def create_pi_creature(self): return PiCreature(color=GREY).to_corner(DL) class AskAboutActuallySolving(TeacherStudentsScene): def construct(self): ode = get_ode() ode.to_corner(UL) self.add(ode) morty = self.teacher self.student_says( "Yeah yeah, but how do\\\\" "you actually \\emph{solve} it?", student_index=1, target_mode="sassy", added_anims=[morty.change, "thinking"], ) self.change_student_modes( "confused", "sassy", "confused", look_at_arg=ode, ) self.wait() self.teacher_says( "What do you mean\\\\ by ``solve''?", target_mode="speaking", added_anims=[self.get_student_changes( *3 * ["erm"] )] ) self.play(self.students[1].change, "angry") self.wait(3) class HungerForExactness(TeacherStudentsScene): def construct(self): students = self.students you = students[2] teacher = self.teacher ode = get_ode() ode.to_corner(UL) left_part = ode[:5] friction_part = ode[5:11] self.add(ode) proposed_solution = TexMobject( "\\theta_0\\cos((\\sqrt{g/L})t)e^{-\\mu t}" ) proposed_solution.next_to( you.get_corner(UL), UP, buff=0.7 ) proposed_solution_rect = SurroundingRectangle( proposed_solution, buff=MED_SMALL_BUFF, ) proposed_solution_rect.set_color(BLUE) proposed_solution_rect.round_corners() solution_p1 = TexMobject( """ \\theta(t) = 2\\text{am}\\left( \\frac{\\sqrt{2g + Lc_1} (t + c_2)}{2\\sqrt{L}}, \\frac{4g}{2g + Lc_1} \\right) """, ) solution_p1.to_corner(UL) solution_p2 = TexMobject( "c_1, c_2 = \\text{Constants depending on initial conditions}" ) solution_p2.set_color(LIGHT_GREY) solution_p2.scale(0.75) solution_p3 = TexMobject( """ \\text{am}(u, k) = \\int_0^u \\text{dn}(v, k)\\,dv """ ) solution_p3.name = TextMobject( "(Jacobi amplitude function)" ) solution_p4 = TexMobject( """ \\text{dn}(u, k) = \\sqrt{1 - k^2 \\sin^2(\\phi)} """ ) solution_p4.name = TextMobject( "(Jacobi elliptic function)" ) solution_p5 = TextMobject("Where $\\phi$ satisfies") solution_p6 = TexMobject( """ u = \\int_0^\\phi \\frac{dt}{\\sqrt{1 - k^2 \\sin^2(t)}} """ ) solution = VGroup( solution_p1, solution_p2, solution_p3, solution_p4, solution_p5, solution_p6, ) solution.arrange(DOWN) solution.scale(0.7) solution.to_corner(UL, buff=MED_SMALL_BUFF) solution.set_stroke(width=0, background=True) solution.remove(solution_p2) solution_p1.add(solution_p2) solution.remove(solution_p5) solution_p6.add(solution_p5) for part in [solution_p3, solution_p4]: part.name.scale(0.7 * 0.7) part.name.set_color(LIGHT_GREY) part.name.next_to(part, RIGHT) part.add(part.name) self.student_says( "Right, but like,\\\\" "what \\emph{is} $\\theta(t)$?", target_mode="sassy", added_anims=[teacher.change, "guilty"], ) self.wait() self.play( FadeInFromDown(proposed_solution), RemovePiCreatureBubble( you, target_mode="raise_left_hand", look_at_arg=proposed_solution, ), teacher.change, "pondering", students[0].change, "pondering", students[1].change, "hesitant", ) self.play(ShowCreation(proposed_solution_rect)) self.play( proposed_solution.shift, 3 * RIGHT, proposed_solution_rect.shift, 3 * RIGHT, you.change, "raise_right_hand", teacher.eyes, ) self.wait(3) self.play( FadeOut(proposed_solution), FadeOut(proposed_solution_rect), ode.move_to, self.hold_up_spot, DOWN, ode.shift, LEFT, teacher.change, "raise_right_hand", self.get_student_changes(*3 * ["pondering"]) ) self.wait() ode.save_state() self.play( left_part.move_to, friction_part, RIGHT, left_part.match_y, left_part, friction_part.to_corner, DR, friction_part.fade, 0.5, ) self.wait() modes = ["erm", "sad", "sad", "horrified"] for part, mode in zip(solution, modes): self.play( FadeInFrom(part, UP), self.get_student_changes( *3 * [mode], look_at_arg=part, ) ) self.wait() self.wait(3) self.change_student_modes("tired", "sad", "concerned_musician") self.wait(4) self.look_at(solution) self.wait(5) self.play( FadeOutAndShift(solution, 2 * LEFT), Restore(ode), self.get_student_changes( "sick", "angry", "tired", ) ) self.wait(3) mystery = TexMobject( "\\theta(t) = ???", tex_to_color_map={"\\theta": BLUE}, ) mystery.scale(2) mystery.to_edge(UP) mystery.set_stroke(width=0, background=True) mystery_boundary = AnimatedBoundary( mystery, stroke_width=1 ) self.play( FadeInFromDown(mystery), self.teacher.change, "pondering" ) self.add(mystery_boundary, mystery) self.change_all_student_modes("sad") self.look_at(mystery) self.wait(5) # Define self.student_says( "Let $\\text{P}(\\mu, g, L; t)$ be a\\\\" "function satisfying this ODE.", student_index=0, target_mode="speaking", added_anims=[ FadeOut(mystery), FadeOut(mystery_boundary), ode.to_corner, UR ] ) self.change_student_modes( "hooray", "sassy", "sassy", look_at_arg=students[0].eyes.get_corner(UR), ) self.wait(2) class ItGetsWorse(TeacherStudentsScene): def construct(self): self.teacher_says("It gets\\\\worse") self.change_student_modes( "hesitant", "pleading", "erm" ) self.wait(5)