summaryrefslogtreecommitdiff
path: root/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem
diff options
context:
space:
mode:
Diffstat (limited to 'FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem')
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/README.md14
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file1_surface1.py232
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file2_surface2.py290
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file3.o_iteration_methods_checkpoint.py226
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file3_iteration_methods.py429
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file4_curvy_region.py102
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file1_surface1.gifbin0 -> 3752052 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file2_surface2.gifbin0 -> 3791121 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file3.o_iteration_methods_checkpoint.gifbin0 -> 465521 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file3_iteration_methods.gifbin0 -> 1813461 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file4_curvy_region.gifbin0 -> 1282583 bytes
11 files changed, 1293 insertions, 0 deletions
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/README.md b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/README.md
new file mode 100644
index 0000000..3aa9be2
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/README.md
@@ -0,0 +1,14 @@
+
+**file1_surface1**
+![file1_surface1](gifs/file1_surface1.gif)
+
+**file2_surface2**
+![file2_surface2](gifs/file2_surface2.gif)
+
+**file3_iteration_methods**
+![file3_iteration_methods](gifs/file3_iteration_methods.gif)
+
+**file4_curvy_limits**
+![file4_curvy_limits](gifs/file4_curvy_region.gif)
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file1_surface1.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file1_surface1.py
new file mode 100644
index 0000000..a590a53
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file1_surface1.py
@@ -0,0 +1,232 @@
+from manimlib.imports import *
+
+class SurfacesAnimation(ThreeDScene):
+
+ CONFIG = {
+ "axes_config": {
+ "x_min": 0,
+ "x_max": 4,
+ "y_min": 0,
+ "y_max": 4,
+ "z_min": -4,
+ "z_max": 4,
+ "a":0 ,"b": 4, "c":0 , "d":4,
+ "axes_shift":IN+LEFT,
+ "x_axis_config": {
+ "tick_frequency": 1,
+ "include_tip": False,
+ },
+ "y_axis_config": {
+ "tick_frequency": 1,
+ "include_tip": False,
+ },
+ "z_axis_config": {
+ "tick_frequency": 1,
+ # "include_tip": False,
+ },
+ "num_axis_pieces": 1,
+ },
+ "default_graph_style": {
+ "stroke_width": 2,
+ "stroke_color": WHITE,
+ },
+ "default_surface_config": {
+ "fill_opacity": 0.5,
+ "checkerboard_colors": [LIGHT_GREY],
+ "stroke_width": 0.5,
+ "stroke_color": WHITE,
+ "stroke_opacity": 0.5,
+ },
+ "Func": lambda x,y: 5*(x**2-y**2)/((1e-4+x**2+y**2)**2)
+ }
+
+
+ def construct(self):
+
+ self.setup_axes()
+ self.set_camera_orientation(#distance=10,
+ phi=80 * DEGREES,
+ theta=35 * DEGREES,
+ )
+
+ fn_text=TextMobject("$z=\dfrac{x^2-y^2}{(x^2+y^2)^2}$").set_color(BLUE)
+ fn_text.to_corner(UR,buff=1)
+ self.add_fixed_in_frame_mobjects(fn_text)
+
+ R=TextMobject("R").set_color(BLACK).scale(2).rotate(180*DEGREES , OUT)
+ R.move_to(self.axes.input_plane,IN)
+ self.add(R)
+
+ #get the surface
+ surface= self.get_surface(
+ self.axes, lambda x , y:
+ self.Func(x,y)
+ )
+ surface.set_style(
+ fill_opacity=0.6,
+ fill_color=BLUE_E,
+ stroke_width=0.8,
+ stroke_color=WHITE,
+ )
+
+
+ self.begin_ambient_camera_rotation(rate=0.2)
+ self.play(Write(surface))
+
+ self.get_lines()
+ self.wait(4)
+
+ def get_surface(self,axes, func, **kwargs):
+ config = {
+ "u_min": axes.x_max,
+ "u_max": axes.x_min,
+ "v_min": axes.y_max,
+ "v_max": axes.y_min,
+ "resolution": (10,10),
+ }
+
+ config.update(self.default_surface_config)
+ config.update(kwargs)
+ return ParametricSurface(
+ lambda x,y : axes.c2p(
+ x, y, func(x, y)
+ ),
+ **config
+ )
+
+ def get_lines(self):
+ axes = self.axes
+ labels=[axes.x_axis.n2p(axes.a), axes.x_axis.n2p(axes.b), axes.y_axis.n2p(axes.c),
+ axes.y_axis.n2p(axes.d)]
+
+
+ surface_corners=[]
+ for x,y,z in self.region_corners:
+ surface_corners.append([x,y,self.Func(x,y)])
+
+ lines=VGroup()
+ for start , end in zip(surface_corners,
+ self.region_corners):
+ lines.add(self.draw_lines(start,end,"YELLOW"))
+
+ for start , end in zip(labels,
+ self.region_corners):
+ # lines.add(self.draw_lines(start,end,"BLUE"))
+ # print (start,end)
+ pass
+ self.play(ShowCreation(lines))
+
+
+ def draw_lines(self,start,end,color):
+ start=self.axes.c2p(*start)
+ end=self.axes.c2p(*end)
+ line=DashedLine(start,end,color=color)
+
+ return line
+
+ def get_three_d_axes(self, include_labels=True, include_numbers=True, **kwargs):
+ config = dict(self.axes_config)
+ config.update(kwargs)
+ axes = ThreeDAxes(**config)
+ axes.set_stroke(width=2)
+
+ if include_numbers:
+ self.add_axes_numbers(axes)
+
+ if include_labels:
+ self.add_axes_labels(axes)
+
+ # Adjust axis orientation
+ axes.x_axis.rotate(
+ 90 * DEGREES, LEFT,
+ about_point=axes.c2p(0, 0, 0),
+ )
+ axes.y_axis.rotate(
+ 90 * DEGREES, UP,
+ about_point=axes.c2p(0, 0, 0),
+ )
+
+ # Add xy-plane
+ input_plane = self.get_surface(
+ axes, lambda x, t: 0
+ )
+ input_plane.set_style(
+ fill_opacity=0.3,
+ fill_color=PINK,
+ stroke_width=.2,
+ stroke_color=WHITE,
+ )
+
+ axes.input_plane = input_plane
+
+ self.region_corners=[
+ input_plane.get_corner(pos) for pos in (DL,DR,UR,UL)]
+
+ return axes
+
+
+ def setup_axes(self):
+ axes = self.get_three_d_axes(include_labels=True)
+ axes.add(axes.input_plane)
+ axes.scale(1)
+ # axes.center()
+ axes.shift(axes.axes_shift)
+
+ self.add(axes)
+ self.axes = axes
+
+ def add_axes_numbers(self, axes):
+ x_axis = axes.x_axis
+ y_axis = axes.y_axis
+ tex_vals_x = [
+ ("a", axes.a+.4),
+ ("b", axes.b),
+ ]
+ tex_vals_y=[
+ ("c", axes.c+.4),
+ ("d", axes.d)
+ ]
+ x_labels = VGroup()
+ y_labels = VGroup()
+ for tex, val in tex_vals_x:
+ label = TexMobject(tex)
+ label.scale(1)
+ label.next_to(x_axis.n2p(val), DOWN)
+ label.rotate(180 * DEGREES)
+ x_labels.add(label)
+ x_axis.add(x_labels)
+ x_axis.numbers = x_labels
+
+ for tex, val in tex_vals_y:
+ label = TexMobject(tex)
+ label.scale(1)
+ label.next_to(y_axis.n2p(val), LEFT)
+ label.rotate(90 * DEGREES)
+ y_labels.add(label)
+
+ y_axis.add(y_labels)
+ y_axis.numbers = y_labels
+
+ return axes
+
+ def add_axes_labels(self, axes):
+ x_label = TexMobject("x")
+ x_label.next_to(axes.x_axis.get_end(), RIGHT)
+ axes.x_axis.label = x_label
+
+ y_label = TextMobject("y")
+ y_label.rotate(90 * DEGREES, OUT)
+ y_label.next_to(axes.y_axis.get_end(), UP)
+ axes.y_axis.label = y_label
+
+ z_label = TextMobject("z")
+ z_label.rotate(90 * DEGREES, LEFT)
+ z_label.next_to(axes.z_axis.get_zenith(), LEFT)
+ axes.z_axis.label = z_label
+ for axis in axes:
+ axis.add(axis.label)
+ return axes
+
+#uploaded by Somnath Pandit.FSF2020_Fubini's_Theorem
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file2_surface2.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file2_surface2.py
new file mode 100644
index 0000000..3160fdb
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file2_surface2.py
@@ -0,0 +1,290 @@
+from manimlib.imports import *
+
+class SurfacesAnimation(ThreeDScene):
+
+ CONFIG = {
+ "axes_config": {
+ "x_min": 0,
+ "x_max": 4,
+ "y_min": 0,
+ "y_max": 4,
+ "z_min": -2,
+ "z_max": 4,
+ "a":0 ,"b": 4, "c":0 , "d":4,
+ "axes_shift":IN+2*LEFT+2*DOWN,
+ "x_axis_config": {
+ "tick_frequency": 1,
+ "include_tip": False,
+ },
+ "y_axis_config": {
+ "tick_frequency": 1,
+ "include_tip": False,
+ },
+ "z_axis_config": {
+ "tick_frequency": 1,
+ # "include_tip": False,
+ },
+ "num_axis_pieces": 1,
+ },
+ "default_graph_style": {
+ "stroke_width": 2,
+ "stroke_color": WHITE,
+ },
+ "default_surface_config": {
+ "fill_opacity": 0.5,
+ "checkerboard_colors": [LIGHT_GREY],
+ "stroke_width": 0.5,
+ "stroke_color": WHITE,
+ "stroke_opacity": 0.5,
+ },
+ "Func": lambda x,y: x*y/4
+ }
+
+
+ def construct(self):
+
+ self.setup_axes()
+ self.set_camera_orientation(
+ distance=30,
+ phi=75 * DEGREES,
+ theta=20 * DEGREES,
+ )
+
+ fn_text=TextMobject("$z=xy$").set_color(BLUE).scale(1.5)
+ fn_text.to_corner(UR,buff=2)
+ self.add_fixed_in_frame_mobjects(fn_text)
+
+
+ #get the surface
+ surface= self.get_surface(
+ self.axes, lambda x , y:
+ self.Func(x,y)
+ )
+ surface.set_style(
+ fill_opacity=.5,
+ fill_color=BLUE_E,
+ stroke_width=0.4,
+ stroke_color=WHITE,
+ )
+ #get boundary curves
+ c1=self.get_curve(
+ self.axes, lambda x: x**2/4
+ )
+ c1_label=TextMobject("$y=x^2$").next_to(c1,IN+OUT).shift(DOWN+RIGHT)
+ c1_label.rotate(PI)
+ c1_group=VGroup(c1,c1_label).set_color(ORANGE)
+
+ c2=self.get_curve(
+ self.axes, lambda x: x
+ ).set_color(PINK)
+ c2_label=TextMobject("$y=x$").next_to(c2,IN+OUT)
+ c2_label.rotate(PI/2,about_point=(c2_label.get_corner(UL)))
+ c2_group=VGroup(c2,c2_label).set_color(YELLOW_E)
+
+
+
+ self.add(c1,c2,c1_label,c2_label)
+
+ self.begin_ambient_camera_rotation(rate=0.24)
+ self.get_region(self.axes,c1,c2)
+ self.play(Write(surface))
+ self.get_lines()
+ self.wait(3.5)
+ self.stop_ambient_camera_rotation()
+ self.wait(.5)
+ self.move_camera(
+ distance=20,
+ phi=10 * DEGREES,
+ theta=80 * DEGREES,
+ run_time=3
+ )
+ self.wait(2)
+
+
+
+ def get_curve(self,axes, func, **kwargs):
+ config = {
+ "t_min": axes.x_min,
+ "t_max": axes.x_max,
+ }
+ config.update(kwargs)
+ return ParametricFunction(
+ lambda x : axes.c2p(
+ x, func(x),0
+ ),
+ **config
+ )
+
+ def get_region(self,axes,curve1,curve2,**kwargs):
+ x_vals=np.arange(axes.x_min,axes.x_max,.1)
+ c1_points=[curve1.get_point_from_function(x) for x in x_vals]
+ c2_points=[curve2.get_point_from_function(x) for x in x_vals]
+ c2_points.reverse()
+ points=c1_points+c2_points
+ region=Polygon(*points,
+ stroke_width=0,
+ fill_color=PINK,
+ fill_opacity=.5
+ )
+ R=TextMobject("R").set_color(PINK).scale(2).rotate(180*DEGREES , OUT)
+ R.move_to(region,IN+RIGHT)
+
+ self.play(ShowCreation(region))
+ self.add(R)
+
+ def get_surface(self,axes, func, **kwargs):
+ config = {
+ "u_min": axes.x_max,
+ "u_max": axes.x_min,
+ "v_min": axes.y_max,
+ "v_max": axes.y_min,
+ "resolution": (10,10),
+ }
+
+ config.update(self.default_surface_config)
+ config.update(kwargs)
+ return ParametricSurface(
+ lambda x,y : axes.c2p(
+ x, y, func(x, y)
+ ),
+ **config
+ )
+
+ def get_lines(self):
+ axes = self.axes
+ labels=[axes.x_axis.n2p(axes.a), axes.x_axis.n2p(axes.b), axes.y_axis.n2p(axes.c),
+ axes.y_axis.n2p(axes.d)]
+
+
+ surface_corners=[]
+ for x,y,z in self.region_corners:
+ surface_corners.append([x,y,self.Func(x,y)])
+
+ lines=VGroup()
+ for start , end in zip(surface_corners,
+ self.region_corners):
+ lines.add(self.draw_lines(start,end,"YELLOW"))
+
+ for start , end in zip(labels,
+ self.region_corners):
+ # lines.add(self.draw_lines(start,end,"BLUE"))
+ # print (start,end)
+ pass
+ self.play(ShowCreation(lines))
+
+
+ def draw_lines(self,start,end,color):
+ start=self.axes.c2p(*start)
+ end=self.axes.c2p(*end)
+ line=DashedLine(start,end,color=color)
+
+ return line
+
+ #customize 3D axes
+ def get_three_d_axes(self, include_labels=True, include_numbers=True, **kwargs):
+ config = dict(self.axes_config)
+ config.update(kwargs)
+ axes = ThreeDAxes(**config)
+ axes.set_stroke(width=2)
+
+ if include_numbers:
+ self.add_axes_numbers(axes)
+
+ if include_labels:
+ self.add_axes_labels(axes)
+
+ # Adjust axis orientation
+ axes.x_axis.rotate(
+ 90 * DEGREES, LEFT,
+ about_point=axes.c2p(0, 0, 0),
+ )
+ axes.y_axis.rotate(
+ 90 * DEGREES, UP,
+ about_point=axes.c2p(0, 0, 0),
+ )
+
+ # Add xy-plane
+ input_plane = self.get_surface(
+ axes, lambda x, t: 0
+ )
+ input_plane.set_style(
+ fill_opacity=0.3,
+ fill_color=PINK,
+ stroke_width=.2,
+ stroke_color=WHITE,
+ )
+
+ axes.input_plane = input_plane
+
+ self.region_corners=[
+ input_plane.get_corner(pos) for pos in (DL,DR,UR,UL)]
+
+ return axes
+
+
+ def setup_axes(self):
+ axes = self.get_three_d_axes(include_labels=True)
+ # axes.add(axes.input_plane)
+ axes.scale(1)
+ # axes.center()
+ axes.shift(axes.axes_shift)
+
+ self.add(axes)
+ self.axes = axes
+
+ def add_axes_numbers(self, axes):
+ x_axis = axes.x_axis
+ y_axis = axes.y_axis
+ tex_vals_x = [
+ ("1", axes.b),
+ ]
+ tex_vals_y=[
+ ("1", axes.d)
+ ]
+ x_labels = VGroup()
+ y_labels = VGroup()
+ for tex, val in tex_vals_x:
+ label = TexMobject(tex)
+ label.scale(1)
+ label.next_to(x_axis.n2p(val), DOWN)
+ label.rotate(180 * DEGREES)
+ x_labels.add(label)
+ x_axis.add(x_labels)
+ x_axis.numbers = x_labels
+
+ for tex, val in tex_vals_y:
+ label = TexMobject(tex)
+ label.scale(1)
+ label.next_to(y_axis.n2p(val), LEFT)
+ label.rotate(90 * DEGREES)
+ y_labels.add(label)
+
+ y_axis.add(y_labels)
+ y_axis.numbers = y_labels
+
+ return axes
+
+ def add_axes_labels(self, axes):
+ x_label = TexMobject("x")
+ x_label.next_to(axes.x_axis.get_end(), RIGHT)
+ axes.x_axis.label = x_label
+
+ y_label = TextMobject("y")
+ y_label.rotate(90 * DEGREES, OUT)
+ y_label.next_to(axes.y_axis.get_end(), UP)
+ axes.y_axis.label = y_label
+
+ z_label = TextMobject("z")
+ z_label.rotate(90 * DEGREES, LEFT)
+ z_label.next_to(axes.z_axis.get_zenith(), LEFT)
+ axes.z_axis.label = z_label
+ for axis in axes:
+ axis.add(axis.label)
+ return axes
+
+ #uploaded by Somnath Pandit.FSF2020_Fubini's_Theorem
+
+
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file3.o_iteration_methods_checkpoint.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file3.o_iteration_methods_checkpoint.py
new file mode 100644
index 0000000..55f91d3
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file3.o_iteration_methods_checkpoint.py
@@ -0,0 +1,226 @@
+from manimlib.imports import *
+
+class IterationMethods(GraphScene):
+ CONFIG = {
+ "x_min" : 0,
+ "x_max" : 1,
+ "y_min" : 0,
+ "y_max" : 1,
+ "x_tick_frequency" : 1,
+ "y_tick_frequency" : 1,
+ "x_labeled_nums": list(np.arange(0,2)),
+ "y_labeled_nums": list(np.arange(0 ,2)),
+ "x_axis_width": 6,
+ "y_axis_height": 6,
+ "graph_origin": ORIGIN+4*LEFT+3*DOWN,
+ "area_color": PINK ,
+ "area_opacity": .6,
+ }
+
+ def construct(self):
+ X = RIGHT*self.x_axis_width/(self.x_max- self.x_min)
+ Y = UP*self.y_axis_height/(self.y_max- self.y_min)
+
+ # self.intro_scene()
+ self.setup_axes(animate=True)
+
+
+ curve1= self.get_graph(
+ lambda x : x**2 ,
+ x_min = 0,
+ x_max = 1,
+ color = ORANGE)
+ c1_eqn=self.get_graph_label(
+ curve1,
+ label="y=x^2",
+ x_val=.5,
+ direction=RIGHT,
+ buff=MED_LARGE_BUFF,
+ color=ORANGE,
+ )
+
+ curve2= self.get_graph(
+ lambda x : x ,
+ x_min = 0,
+ x_max = 1,
+ color = YELLOW)
+ c2_eqn=self.get_graph_label(
+ curve2,
+ label="y=x",
+ x_val=.5,
+ direction=LEFT,
+ buff=MED_LARGE_BUFF,
+ color=YELLOW,
+ )
+ self.curve1=curve1
+ self.curve2=curve2
+
+ caption_y_int=TextMobject(r"Observe the limits\\ of integration").to_corner(UR)
+ int_lim=TextMobject(
+ "$$\\int_0^1$$"
+ ).next_to(
+ caption_y_int,DOWN,buff=.5
+ ).align_to(
+ caption_y_int,LEFT
+ )
+
+ self.play(ShowCreation(VGroup(curve1,curve2)),Write(VGroup(c2_eqn,c1_eqn)))
+ rects=self.get_rects()
+
+ self.play(Write(caption_y_int))
+ self.show_integral_values_at_different_x()
+ self.wait(1)
+ self.add(int_lim)
+ self.play(FadeOut(self.brace_group))
+ self.play(ApplyMethod(
+ self.y_int.next_to,
+ int_lim,RIGHT,buff=0))
+
+ self.play(ApplyMethod(
+ self.dx_label.next_to,
+ self.y_int,RIGHT))
+
+ self.show_area()
+
+ self.wait(2)
+
+ ###################
+ def intro_scene(self):
+ text=TextMobject(r"How different orders of \textbf{iterated integral}\\ works over the same region ?" )
+ self.play(Write(text),run_time=4)
+ self.wait(2)
+ self.play(FadeOut(text))
+
+
+ def show_area(self):
+ area = self.bounded_riemann_rectangles(
+ self.curve1,
+ self.curve2,
+ x_min = 0,
+ x_max = 1,
+ dx =.001,
+ start_color = self.area_color,
+ end_color = self.area_color,
+ fill_opacity = 1,
+ stroke_width = 0,
+ )
+ self.play(ShowCreation(area))
+ # self.transform_between_riemann_rects(self.rects,area)
+ self.area = area
+
+ def get_rects(self):
+ rects = self.bounded_riemann_rectangles(
+ self.curve1,
+ self.curve2,
+ x_min = 0,
+ x_max = 1,
+ dx =.01,
+ start_color = self.area_color,
+ end_color = self.area_color,
+ fill_opacity =self.area_opacity,
+ stroke_width = 0,
+ )
+ # self.transform_between_riemann_rects(self.area,rects)
+ self.rects=rects
+ return rects
+
+ def show_integral_values_at_different_x(self):
+ rects=self.rects
+ rect = rects[len(rects)*1//10]
+ dx_brace = Brace(rect, DOWN, buff = 0)
+ dx_label = dx_brace.get_text("$dx$", buff = SMALL_BUFF)
+ dx_brace_group = VGroup(dx_brace,dx_label)
+ rp=int(len(rects)/10)
+ rects_subset = self.rects[4*rp:5*rp]
+
+ last_rect = None
+ for rect in rects_subset:
+ brace = Brace(rect, LEFT, buff =.1)
+ y_int = TexMobject("\\int_{x^2}^{x}dy")#.rotate(PI/2)
+ y_int.next_to(brace, LEFT, MED_SMALL_BUFF)
+ anims = [
+ rect.set_fill, self.area_color, 1,
+ dx_brace_group.next_to, rect, DOWN, SMALL_BUFF
+ ]
+ if last_rect is not None:
+ anims += [
+ last_rect.set_fill, None, 0,
+ # last_rect.set_fill, self.area_color, self.area_opacity,
+ ReplacementTransform(last_brace, brace),
+ ReplacementTransform(last_y_int, y_int),
+ ]
+ else:
+ anims += [
+ GrowFromCenter(brace),
+ Write(y_int)
+ ]
+ self.play(*anims)
+ # self.wait(.2)
+
+ last_rect = rect
+ last_brace = brace
+ last_y_int = y_int
+
+ y_int = last_y_int
+ y_brace = last_brace
+ self.brace_group=VGroup(y_brace,dx_brace,rect)
+ self.y_int=y_int
+ self.dx_label=dx_label
+
+
+ def bounded_riemann_rectangles(
+ self,
+ graph1,
+ graph2,
+ x_min=None,
+ x_max=None,
+ dx=0.01,
+ input_sample_type="center",
+ stroke_width=1,
+ stroke_color=BLACK,
+ fill_opacity=1,
+ start_color=None,
+ end_color=None,
+ show_signed_area=True,
+ width_scale_factor=1.001
+ ):
+ x_min = x_min if x_min is not None else self.x_min
+ x_max = x_max if x_max is not None else self.x_max
+ if start_color is None:
+ start_color = self.default_riemann_start_color
+ if end_color is None:
+ end_color = self.default_riemann_end_color
+ rectangles = VGroup()
+ x_range = np.arange(x_min, x_max, dx)
+ colors = color_gradient([start_color, end_color], len(x_range))
+ for x, color in zip(x_range, colors):
+ if input_sample_type == "left":
+ sample_input = x
+ elif input_sample_type == "right":
+ sample_input = x + dx
+ elif input_sample_type == "center":
+ sample_input = x + 0.5 * dx
+ else:
+ raise Exception("Invalid input sample type")
+ graph1_point = self.input_to_graph_point(sample_input, graph1)
+ graph1_point_dx= self.input_to_graph_point(sample_input + width_scale_factor * dx, graph1)
+ graph2_point = self.input_to_graph_point(sample_input, graph2)
+
+ points = VGroup(*list(map(VectorizedPoint, [
+ graph1_point,
+ graph1_point_dx,
+ graph2_point
+ ])))
+
+ rect = Rectangle()
+ rect.replace(points, stretch=True)
+ if graph1_point[1] < self.graph_origin[1] and show_signed_area:
+ fill_color = invert_color(color)
+ else:
+ fill_color = color
+ rect.set_fill(fill_color, opacity=fill_opacity)
+ rect.set_stroke(stroke_color, width=stroke_width)
+ rectangles.add(rect)
+ return rectangles
+
+#uploaded by Somnath Pandit.FSF2020_Fubini's_Theorem
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file3_iteration_methods.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file3_iteration_methods.py
new file mode 100644
index 0000000..ad78a0b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file3_iteration_methods.py
@@ -0,0 +1,429 @@
+from manimlib.imports import *
+
+class IterationMethods(GraphScene):
+ CONFIG = {
+ "x_min" : 0,
+ "x_max" : 1,
+ "y_min" : 0,
+ "y_max" : 1,
+ "x_tick_frequency" : 1,
+ "y_tick_frequency" : 1,
+ "x_labeled_nums": list(np.arange(0,2)),
+ "y_labeled_nums": list(np.arange(0 ,2)),
+ "x_axis_width": 6,
+ "y_axis_height": 6,
+ "graph_origin": ORIGIN+4.5*LEFT+3*DOWN,
+ "area_color": PINK ,
+ "area_opacity": .6,
+ }
+
+ def construct(self):
+ X = RIGHT*self.x_axis_width/(self.x_max- self.x_min)
+ Y = UP*self.y_axis_height/(self.y_max- self.y_min)
+
+ self.intro_scene()
+ self.setup_axes(animate=True)
+
+
+ curve1= self.get_graph(
+ lambda x : x**2 ,
+ x_min = 0,
+ x_max = 1,
+ color = ORANGE)
+ c1_eqn=self.get_graph_label(
+ curve1,
+ label="y=x^2",
+ x_val=.5,
+ direction=RIGHT,
+ buff=MED_LARGE_BUFF,
+ color=ORANGE,
+ )
+
+ curve2= self.get_graph(
+ lambda x : x ,
+ x_min = 0,
+ x_max = 1,
+ color = YELLOW)
+ c2_eqn=self.get_graph_label(
+ curve2,
+ label="y=x",
+ x_val=.7,
+ direction=LEFT,
+ buff=MED_LARGE_BUFF,
+ color=YELLOW,
+ )
+ self.curve1=curve1
+ self.curve2=curve2
+
+ caption_limit=TextMobject(r"Observe the limits\\ of integration").to_corner(UR)
+ int_lim=TextMobject(
+ "$$\\int_0^1$$"
+ ).next_to(
+ caption_limit,DOWN,buff=.5
+ ).align_to(
+ caption_limit,LEFT
+ )
+ self.int_lim=int_lim
+ self.play(ShowCreation(VGroup(curve1,curve2)),Write(VGroup(c2_eqn,c1_eqn)))
+
+ self.play(Write(caption_limit))
+ self.get_rects()
+ self.show_integral_values_at_different_x()
+ self.wait(1)
+ self.integral_setup(int_lim,first_y=True)
+
+
+ self.another_method_scene()
+ self.remove(self.area)
+ self.wait()
+
+ c1_eqn_y=self.get_graph_label(
+ curve1,
+ label="x=\sqrt y",
+ x_val=.6,
+ direction=RIGHT,
+ buff=MED_LARGE_BUFF,
+ color=ORANGE,
+ )
+ c2_eqn_y=self.get_graph_label(
+ curve2,
+ label="x=y",
+ x_val=.7,
+ direction=LEFT,
+ buff=MED_LARGE_BUFF,
+ color=YELLOW,
+ )
+ self.play(
+ ReplacementTransform(c1_eqn,c1_eqn_y),
+ ReplacementTransform(c2_eqn,c2_eqn_y)
+ )
+ self.get_rects(base_y=True)
+ self.show_integral_values_at_different_y()
+ self.wait(1)
+
+ int_lim_y=int_lim.copy()
+ int_lim_y.next_to(int_lim,DOWN)
+ self.int_lim_y=int_lim_y
+ equal=TextMobject("$$=$$").next_to(int_lim_y,LEFT)
+ self.add(equal)
+
+ self.integral_setup(int_lim_y,first_y=False)
+
+ self.wait(2)
+
+ ###################
+ def intro_scene(self):
+ text=TextMobject(r"How different orders of \textbf{iterated integral}\\ works over the same region ?" )
+ self.play(Write(text),run_time=4)
+ self.wait(2)
+ self.play(FadeOut(text))
+
+ def another_method_scene(self):
+ text=TextMobject(r"The other method\\ of iteration")
+ text.next_to(self.curve1,UP,buff=-1)
+ self.play(GrowFromCenter(text))
+ self.wait(2)
+ self.play(LaggedStart(FadeOut(text),lag_ratio=2))
+
+ def integral_setup(self,ref_object,first_y=True):
+ if first_y:
+ area=self.get_area()
+ self.area=area
+ self.play(FadeOut(self.brace_group))
+ self.play(ApplyMethod(
+ self.y_int.next_to,
+ ref_object,RIGHT,buff=0)
+ )
+
+ self.play(ApplyMethod(
+ self.dx_label.next_to,
+ self.y_int,RIGHT),
+ ShowCreation(area),
+ Write(self.int_lim),run_time=4
+ )
+ else:
+ area=self.get_area(base_y=True)
+ self.area=area
+ self.play(
+ FadeOut(self.y_brace_group),
+ Rotate(self.x_int,PI/2)
+ )
+ self.play(ApplyMethod(
+ self.x_int.next_to,
+ ref_object,RIGHT,buff=0)
+ )
+ self.play(ApplyMethod(
+ self.dy_label.next_to,
+ self.x_int,RIGHT),
+ ShowCreation(area),
+ Write(self.int_lim_y),run_time=4
+ )
+
+ def get_area(self,base_y=False):
+ if base_y:
+ area = self.bounded_riemann_rectangles_y(
+ lambda x: x,
+ lambda x: np.sqrt(x),
+ y_min = 0,
+ y_max = 1,
+ dy =.001,
+ start_color = self.area_color,
+ end_color = self.area_color,
+ fill_opacity =self.area_opacity,
+ stroke_width = 0,
+ )
+ self.y_area = area
+ else:
+ area = self.bounded_riemann_rectangles(
+ self.curve1,
+ self.curve2,
+ x_min = 0,
+ x_max = 1,
+ dx =.001,
+ start_color = self.area_color,
+ end_color = self.area_color,
+ fill_opacity =self.area_opacity,
+ stroke_width = 0,
+ )
+ self.area = area
+
+ # self.transform_between_riemann_rects(self.rects,area)
+ return area
+
+ def get_rects(self,base_y=False):
+ if base_y:
+ rects = self.bounded_riemann_rectangles_y(
+ lambda x: x,
+ lambda x: np.sqrt(x),
+ y_min = 0,
+ y_max = 1,
+ dy =.01,
+ start_color = self.area_color,
+ end_color = self.area_color,
+ fill_opacity =self.area_opacity,
+ stroke_width = 0,
+ )
+ self.y_rects=rects
+ else:
+ rects = self.bounded_riemann_rectangles(
+ self.curve1,
+ self.curve2,
+ x_min = 0,
+ x_max = 1,
+ dx =.01,
+ start_color = self.area_color,
+ end_color = self.area_color,
+ fill_opacity =self.area_opacity,
+ stroke_width = 0,
+ )
+ self.rects=rects
+ # self.transform_between_riemann_rects(self.area,rects)
+
+ return rects
+
+ def show_integral_values_at_different_x(self):
+ rects=self.rects
+ rect = rects[len(rects)*1//10]
+ dx_brace = Brace(rect, DOWN, buff = 0)
+ dx_label = dx_brace.get_text("$dx$", buff = SMALL_BUFF)
+ dx_brace_group = VGroup(dx_brace,dx_label)
+ rp=int(len(rects)/20)
+ rects_subset = rects[6*rp:7*rp]
+
+ last_rect = None
+ for rect in rects_subset:
+ brace = Brace(rect, LEFT, buff =.1)
+ y_int = TexMobject("\\int_{x^2}^{x}dy")#.rotate(PI/2)
+ y_int.next_to(brace, LEFT, MED_SMALL_BUFF)
+ anims = [
+ rect.set_fill, self.area_color, 1,
+ dx_brace_group.next_to, rect, DOWN, SMALL_BUFF
+ ]
+ if last_rect is not None:
+ anims += [
+ last_rect.set_fill, None, 0,
+ # last_rect.set_fill, self.area_color, self.area_opacity,
+ ReplacementTransform(last_brace, brace),
+ ReplacementTransform(last_y_int, y_int),
+ ]
+ else:
+ anims += [
+ GrowFromCenter(brace),
+ Write(y_int)
+ ]
+ self.play(*anims)
+ # self.wait(.2)
+
+ last_rect = rect
+ last_brace = brace
+ last_y_int = y_int
+
+ y_int = last_y_int
+ y_brace = last_brace
+ self.brace_group=VGroup(y_brace,dx_brace,rect)
+ self.y_int=y_int
+ self.dx_label=dx_label
+
+ def show_integral_values_at_different_y(self):
+ rects=self.y_rects
+ rect = rects[len(rects)*1//10]
+ dy_brace = Brace(rect, LEFT, buff = 0)
+ dy_label = dy_brace.get_text("$dy$", buff = SMALL_BUFF)
+ dy_brace_group = VGroup(dy_brace,dy_label)
+ rp=int(len(rects)/20)
+ rects_subset = rects[5*rp:6*rp]
+
+ last_rect = None
+ for rect in rects_subset:
+ brace = Brace(rect, DOWN, buff =.1)
+ x_int = TexMobject("\\int_{y}^{\sqrt y}dx").rotate(-PI/2)
+ x_int.next_to(brace, DOWN, SMALL_BUFF)
+ anims = [
+ rect.set_fill, self.area_color, 1,
+ dy_brace_group.next_to, rect, LEFT, SMALL_BUFF
+ ]
+ if last_rect is not None:
+ anims += [
+ last_rect.set_fill, None, 0,
+ # last_rect.set_fill, self.area_color, self.area_opacity,
+ ReplacementTransform(last_brace, brace),
+ ReplacementTransform(last_x_int, x_int),
+ ]
+ else:
+ anims += [
+ GrowFromCenter(brace),
+ Write(x_int)
+ ]
+ self.play(*anims)
+ # self.wait(.2)
+
+ last_rect = rect
+ last_brace = brace
+ last_x_int = x_int
+
+ x_int = last_x_int
+ y_brace = last_brace
+ self.y_brace_group=VGroup(y_brace,dy_brace,rect)
+ self.x_int=x_int
+ self.dy_label=dy_label
+
+
+ def bounded_riemann_rectangles(
+ self,
+ graph1,
+ graph2,
+ x_min=None,
+ x_max=None,
+ dx=0.01,
+ input_sample_type="center",
+ stroke_width=1,
+ stroke_color=BLACK,
+ fill_opacity=1,
+ start_color=None,
+ end_color=None,
+ show_signed_area=True,
+ width_scale_factor=1.001
+ ):
+ x_min = x_min if x_min is not None else self.x_min
+ x_max = x_max if x_max is not None else self.x_max
+ if start_color is None:
+ start_color = self.default_riemann_start_color
+ if end_color is None:
+ end_color = self.default_riemann_end_color
+ rectangles = VGroup()
+ x_range = np.arange(x_min, x_max, dx)
+ colors = color_gradient([start_color, end_color], len(x_range))
+ for x, color in zip(x_range, colors):
+ if input_sample_type == "left":
+ sample_input = x
+ elif input_sample_type == "right":
+ sample_input = x + dx
+ elif input_sample_type == "center":
+ sample_input = x + 0.5 * dx
+ else:
+ raise Exception("Invalid input sample type")
+ graph1_point = self.input_to_graph_point(sample_input, graph1)
+ graph1_point_dx= self.input_to_graph_point(sample_input + width_scale_factor * dx, graph1)
+ graph2_point = self.input_to_graph_point(sample_input, graph2)
+
+ points = VGroup(*list(map(VectorizedPoint, [
+ graph1_point,
+ graph1_point_dx,
+ graph2_point
+ ])))
+
+ rect = Rectangle()
+ rect.replace(points, stretch=True)
+ if graph1_point[1] < self.graph_origin[1] and show_signed_area:
+ fill_color = invert_color(color)
+ else:
+ fill_color = color
+ rect.set_fill(fill_color, opacity=fill_opacity)
+ rect.set_stroke(stroke_color, width=stroke_width)
+ rectangles.add(rect)
+ return rectangles
+
+ def bounded_riemann_rectangles_y(
+ self,
+ graph1,
+ graph2,
+ y_min=None,
+ y_max=None,
+ dy=0.01,
+ input_sample_type="center",
+ stroke_width=1,
+ stroke_color=BLACK,
+ fill_opacity=1,
+ start_color=None,
+ end_color=None,
+ show_signed_area=True,
+ width_scale_factor=1.001
+ ):
+ y_min = y_min if y_min is not None else self.y_min
+ y_max = y_max if y_max is not None else self.y_max
+ if start_color is None:
+ start_color = self.default_riemann_start_color
+ if end_color is None:
+ end_color = self.default_riemann_end_color
+ rectangles = VGroup()
+ y_range = np.arange(y_min, y_max, dy)
+ colors = color_gradient([start_color, end_color], len(y_range))
+ for y, color in zip(y_range, colors):
+ if input_sample_type == "left":
+ sample_input = y
+ elif input_sample_type == "right":
+ sample_input = y + dy
+ elif input_sample_type == "center":
+ sample_input = y + 0.5 * dy
+ else:
+ raise Exception("Invalid input sample type")
+ graph1_point = self.coords_to_point(
+ graph1(sample_input),sample_input
+ )
+ dy_input=sample_input + width_scale_factor * dy
+ graph1_point_dy= self.coords_to_point(
+ graph1(dy_input),dy_input
+ )
+ graph2_point = self.coords_to_point(
+ graph2(sample_input),sample_input
+ )
+
+ points = VGroup(*list(map(VectorizedPoint, [
+ graph1_point,
+ graph1_point_dy,
+ graph2_point
+ ])))
+
+ rect = Rectangle()
+ rect.replace(points, stretch=True)
+ if graph1_point[1] < self.graph_origin[1] and show_signed_area:
+ fill_color = invert_color(color)
+ else:
+ fill_color = color
+ rect.set_fill(fill_color, opacity=fill_opacity)
+ rect.set_stroke(stroke_color, width=stroke_width)
+ rectangles.add(rect)
+ return rectangles
+
+
+#uploaded by Somnath Pandit.FSF2020_Fubini's_Theorem
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file4_curvy_region.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file4_curvy_region.py
new file mode 100644
index 0000000..46134a7
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file4_curvy_region.py
@@ -0,0 +1,102 @@
+from manimlib.imports import *
+
+class CurvyRegion(GraphScene):
+ CONFIG = {
+ "x_min": 0,
+ "x_max": 8,
+ "y_min": 0,
+ "y_max": 6,
+ "graph_origin": ORIGIN+4.5*LEFT+3*DOWN,
+ "x_labeled_nums": np.arange(0, 9,2),
+ "y_labeled_nums": np.arange(0, 7,2),
+ "x_axis_width": 6,
+ "y_axis_height": 6,
+ }
+
+ def construct(self):
+ XD = self.x_axis_width/(self.x_max- self.x_min)
+ YD = self.y_axis_height/(self.y_max- self.y_min)
+ self.X=XD*RIGHT ;self.Y=YD*UP
+
+ sin_curve_points=[self.graph_origin+(2+.5*np.sin(2*y),y,0)
+ for y in np.arange(1,5,.005)]
+
+ cos_curve_points=[self.graph_origin+(
+ 5+.5*np.cos(2*y),y,0)
+ for y in np.arange(1,5,.005)]
+ cos_curve_points.reverse()
+
+ region=Polygon(
+ *sin_curve_points+cos_curve_points,
+ color=YELLOW,
+ stroke_width=1,
+ fill_color=BLUE_E,
+ fill_opacity=.75
+ )
+
+ line=Line((1,0,0),(1,6,0),color=RED)
+ line.move_to(self.graph_origin+2.5*self.X,DOWN)
+ self.line=line
+ self.setup_axes(animate = False)
+
+ self.add(region)
+ self.wait()
+ self.first_y_int_scene()
+ self.try_x_first_scene()
+
+
+ def first_y_int_scene(self):
+ talk=TextMobject(r"For doing the $y$ integration\\ first we need to set\\ proper $y$ limts").to_corner(UR,buff=LARGE_BUFF)
+ problem=TextMobject(r"But here we get\\ more than two $y$ values\\ for a single $x$ value" ).to_corner(UR,buff=LARGE_BUFF)
+ int_y=TextMobject("$$\\int_?^? dy$$").next_to(problem,DOWN,buff=.5)
+
+ self.play(Write(talk))
+ self.play(FadeIn(self.line))
+ self.wait(2)
+ self.play(ReplacementTransform(talk,problem))
+ self.play(
+ ApplyMethod(self.line.shift,3.7*self.X),
+ run_time=4
+ )
+ self.wait()
+ self.play(Write(int_y))
+ self.wait(3)
+ self.play(FadeOut(VGroup(problem,int_y,self.line)))
+
+ def try_x_first_scene(self):
+ try_text=TextMobject(r"But if we try to integrate\\ along $x$ first ...." ).to_corner(UR,buff=LARGE_BUFF)
+ good_limits=TextMobject(r"For one $y$ value we get\\ only \textbf{two} $x$ values $\dots$").to_corner(UR,buff=LARGE_BUFF)
+ limit_values= TextMobject(r"one Lower limit\\ one Upper limit ").next_to(good_limits,DOWN,buff=.5)
+ int_x=TextMobject("$$\\int_{f(y)}^{g(y)} dx$$").next_to(limit_values,DOWN)
+
+ self.setup_line()
+ self.play(Write(try_text))
+ self.play(FadeIn(self.line))
+ self.wait()
+ self.play(ReplacementTransform(try_text,good_limits))
+ self.wait()
+ self.play(
+ ApplyMethod(self.line.shift,3*self.Y),
+ run_time=4
+ )
+ self.play(Write(limit_values))
+ self.wait()
+ self.show_functions()
+ self.play(Write(int_x))
+ self.wait(3)
+
+ def setup_line(self):
+ line=self.line.rotate(PI/2)
+ line.move_to(self.graph_origin+.5*self.X+1.5*self.Y,LEFT)
+ self.line=line
+
+ def show_functions(self):
+ fy=TextMobject("$$f(y)$$")
+ gy=TextMobject("$$g(y)$$")
+ fy.move_to(self.graph_origin+2*self.X+3.3*self.Y)
+ gy.move_to(self.graph_origin+7*self.X+2*self.Y)
+ self.play(FadeIn(VGroup(fy,gy)))
+
+
+ #uploaded by Somnath Pandit.FSF2020_Fubini's_Theorem
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file1_surface1.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file1_surface1.gif
new file mode 100644
index 0000000..8c9fa0a
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file1_surface1.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file2_surface2.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file2_surface2.gif
new file mode 100644
index 0000000..37c4b1d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file2_surface2.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file3.o_iteration_methods_checkpoint.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file3.o_iteration_methods_checkpoint.gif
new file mode 100644
index 0000000..2e507f9
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file3.o_iteration_methods_checkpoint.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file3_iteration_methods.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file3_iteration_methods.gif
new file mode 100644
index 0000000..4e1611b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file3_iteration_methods.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file4_curvy_region.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file4_curvy_region.gif
new file mode 100644
index 0000000..b0620e5
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file4_curvy_region.gif
Binary files differ