summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FSF-2020/approximations-and-optimizations/Critical Points/example.py32
-rw-r--r--FSF-2020/approximations-and-optimizations/Critical Points/motivation.py30
-rw-r--r--FSF-2020/approximations-and-optimizations/Critical Points/theorem.py55
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/README.md38
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file1_Critical_Point_of_a_function.gifbin0 -> 8077401 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file1_Critical_Point_of_a_function.py77
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file2_Traces_and_Tangent.gifbin0 -> 2552938 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file2_Traces_and_Tangent.py88
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file3_Tangent_plane_at_extrema_of_a_function.gifbin0 -> 2198637 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file3_Tangent_plane_at_extrema_of_a_function.py73
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file4_Relative_Maximum_and_Relative_Minimum.gifbin0 -> 1587319 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file4_Relative_Maximum_and_Relative_Minimum.py51
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file5_Saddle_Point.gifbin0 -> 7136893 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file5_Saddle_Point.py71
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file6_f(x,y)=(y-x)(1-2x-3y).gifbin0 -> 1522415 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file6_f(x,y)=(y-x)(1-2x-3y).py29
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/README.md26
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file1_Extrema_over_g(x,y)=k.gifbin0 -> 602190 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file1_Extrema_over_g(x,y)=k.py45
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file2_Constraint_circle_with_contour_plot_of_the_surface_x^2+y^2+x^3-y^3.gifbin0 -> 1810502 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file2_Constraint_circle_with_contour_plot_of_the_surface_x^2+y^2+x^3-y^3.py72
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file3_Geometric_Proof.gifbin0 -> 286190 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file3_Geometric_Proof.py89
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file4_Constraints_g_and_h.gifbin0 -> 685176 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file4_Constraints_g_and_h.py52
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Critical_Points_mcq_questions.pdf (renamed from FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical_Points_mcq_questions.pdf)bin414750 -> 414750 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Lagrange_Multipliers_mcq_questions.pdfbin0 -> 422605 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Tangent_Plane_Approximations_mcq_questions.pdfbin0 -> 424626 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/The_Second_Derivative_Test_mcq_questions.pdf (renamed from FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The_Second_Derivative_Test_MCQ.pdf)bin646880 -> 646880 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Total_Differential_mcq_questions.pdfbin0 -> 426164 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/README.md26
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file1_Tangent_Plane.gifbin0 -> 827096 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file1_Tangent_Plane.py50
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file2_Tangent_plane_approximation_visualization.gifbin0 -> 979487 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file2_Tangent_plane_approximation_visualization.py85
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file3_Non_Differentiable_Function.gifbin0 -> 708466 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file3_Non_Differentiable_Function.py47
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file4_Tangent_plane_at_extrema_and_saddle_point.gifbin0 -> 1424279 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file4_Tangent_plane_at_extrema_and_saddle_point.py (renamed from FSF-2020/approximations-and-optimizations/Critical Points/types_of_cp.py)50
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/README.md27
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file1_Second_order_partial_derivatives.gifbin0 -> 3166332 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file1_Second_order_partial_derivatives.py78
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file2_Nondegenerate_Hessian_Matrix.gifbin0 -> 2047897 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file2_Nondegenerate_Hessian_Matrix.py158
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file3_Degenerate_Hessian_Matrix.gifbin0 -> 407350 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file3_Degenerate_Hessian_Matrix.py45
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file4_Contour_Diagram.gifbin0 -> 1140109 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file4_Contour_Diagram.py120
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/README.md34
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file1_Visualization_of_dz.gifbin0 -> 565199 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file1_Visualization_of_dz.py59
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file2_Differentials.gifbin0 -> 729982 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file2_Differentials.py77
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file3_Total_differential_of_z.gifbin0 -> 1444924 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file3_Total_differential_of_z.py100
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file4_total_differential_change.gifbin0 -> 300675 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file4_total_differential_change.py54
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file5_Total_differential_approximation.gifbin0 -> 423246 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file5_Total_differential_approximation.py52
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file1_paths-3d.gifbin0 -> 4409648 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file1_paths-3d.py41
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file2_line-int.gifbin0 -> 7935159 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file2_line-int.py132
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file3_path-independent.gifbin0 -> 2453243 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file3_path-independent.py131
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file4_path-dependent.gifbin0 -> 2476998 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file4_path-dependent.py130
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file5_closed-loop.gifbin0 -> 1154185 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file5_closed-loop.py63
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file6_potential-func.gifbin0 -> 3881592 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file6_potential-func.py33
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file10_gauss.pngbin0 -> 192422 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file10_gauss.py51
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file11_gravitational-field.pngbin0 -> 12102 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file11_gravitational-filed.ipynb119
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file12_ponder-curl.pngbin0 -> 34864 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file12_ponder-curl.py17
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file1_sources-and-sinks.gifbin0 -> 17712731 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file1_sources-and-sinks.py76
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file2_div-curl-types.py162
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file2_div_curl-types.gifbin0 -> 800 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file3_threed-vec-field.gifbin0 -> 3462931 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file3_threed-vec-field.ipynb67
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file4_output-curl.gifbin0 -> 1331084 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file4_output-curl.ipynb67
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file5_neg-div.gifbin0 -> 1583652 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file5_neg-div.ipynb6
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file6_macro-micro-curl.gifbin0 -> 2824993 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file6_macro-micro-curl.py42
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file7_div-formula.gifbin0 -> 1049376 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file7_div-formula.py225
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file8_curl-paddle.gifbin0 -> 29737449 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file8_curl-paddle.py55
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file9_formal-def.gifbin0 -> 28855629 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file9_formal-def.py82
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file1_closed-loop.gifbin0 -> 1154185 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file1_closed-loop.py63
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file2_curl-paddle.gifbin0 -> 29737449 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file2_curl-paddle.py55
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file3_measure-curl.gifbin0 -> 2952922 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file3_measure-curl.py82
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file4_vortex-streamplot.ipynb96
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file4_vortex-streamplot.pngbin0 -> 80705 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file5_connected-regions.gifbin0 -> 3364367 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file5_connected-regions.py54
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file6_not-connected-regions.gifbin0 -> 7740003 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file6_not-connected-regions.py54
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file1_analogy.gifbin0 -> 13662423 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file1_analogy.py77
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file2_input-output.gifbin0 -> 19704445 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file2_input-output.py136
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file3_input-output2.gifbin0 -> 17293502 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file3_input-output2.py136
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file4_why-partials.gifbin0 -> 17233549 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file4_why-partials.py66
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file5_contour-lines-and-map.ipynb104
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file5_contour-lines-and-map.pngbin0 -> 57290 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file6_surf-contour-plot.ipynb171
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file6_surf-contour-plot.pngbin0 -> 115964 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file7_missile.py45
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file7_missiles.gifbin0 -> 2121832 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file8_fluid-flow.gifbin0 -> 6466207 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file8_fluid-flow.py27
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file1_ftc-analogue.gifbin0 -> 1240392 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file1_ftc-analogue.py265
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file2_line-int.gifbin0 -> 7935159 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file2_line-int.py132
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file3_line-int-sum.gifbin0 -> 5780344 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file3_line-int-sum.py211
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file4_theorem-proof.gifbin0 -> 6082316 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file4_theorem-proof.py184
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/conservative-fields/README.md13
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/curl-and-div/README.md24
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/README.md19
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file1_missile-example.py37
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file2_gradient-example-1.py43
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file3_gradient-example-2.py39
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file4-multidimensional-gradient.py113
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file4_gradient-example-3.py40
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file5_steepest-ascent-analogy.py71
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file6-maximum.py39
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/greens-theorem/README.md8
-rw-r--r--FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/vec-f-is-conservative-implies-curl-f-is-0/README.md12
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/README.md9
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/README.md11
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file1_arc_length.gifbin0 -> 822369 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file1_arc_length.py123
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file2_simple_visualization.gifbin0 -> 675451 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file2_simple_visualization.py91
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file3_circle_curvature.gifbin0 -> 346667 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file3_circle_curvature.py27
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file4_curvature_interpretation.gifbin0 -> 700862 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file4_curvature_interpretation.py114
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file5_different_curvature_single_curve.gifbin0 -> 243868 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file5_different_curvature_single_curve.py76
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/README.md14
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file1_line_eqn.gifbin0 -> 4694940 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file1_line_eqn.py26
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file2_point_normal_form_plane.gifbin0 -> 430431 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file2_point_normal_form_plane.py39
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file3_intercept_form_plane.gifbin0 -> 2884416 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file3_intercept_form_plane.py29
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file4_3d_plane.gifbin0 -> 2037923 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file4_3d_plane.py49
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file5_vector_form_line.gifbin0 -> 536607 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file5_vector_form_line.py47
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/README.md11
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file1_parametric_circle.gifbin0 -> 327132 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file1_parametric_circle.py81
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file2_cycloid_manim.gifbin0 -> 1313411 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file2_cycloid_manim.py46
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file3_brachistochrone.gifbin0 -> 122838 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file3_brachistochrone.py13
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file4_helix_visualization.gifbin0 -> 3596680 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file4_helix_visualization.py31
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/README.md11
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file1_parametric_ellipse.gifbin0 -> 340180 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file1_parametric_ellipse.py78
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file2_parametric_helix.gifbin0 -> 389637 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file2_parametric_helix.py91
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file3_circletosphere.gifbin0 -> 1811911 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file3_circletosphere.py45
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file4_cone.gifbin0 -> 987693 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file4_cone.py33
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/README.md15
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file1_tnb_creation.gifbin0 -> 1708693 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file1_tnb_creation.py66
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file2_tnb_basic.gifbin0 -> 2002004 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file2_tnb_basic.py36
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file3_tnb_frame_manim.gifbin0 -> 886891 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file3_tnb_frame_manim.py218
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file4_fs1.py91
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file5_torsion_intuition.py119
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file6_fs2.py90
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file7_fs3.py194
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/README.md2
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file1_smooth_curves.gifbin0 -> 1541515 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file2_non_differentiable.py36
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file3_tangent_space_curve.gifbin0 -> 1317248 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file3_tangent_space_curve.py33
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/README.md13
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/README.md21
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file1_area_under_func.py (renamed from FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/area_under_func.py)0
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file2_volume_under_surface.py349
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file3_y_limit_dependent_on_x.py (renamed from FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/y_limit_dependent_on_x.py)2
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file4_non_rect_region.py (renamed from FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/non_rect_region.py)0
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file5_elementary_area.py (renamed from FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/elementary_area.py)0
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file6_doing_integration.py355
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file7_int_process_of_example.py366
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file1_area_under_func.gif (renamed from FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/area_Under_func.gif)bin1277788 -> 1277788 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file2_volume_under_surface.gifbin0 -> 6614909 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file3_y_limit_dependent_on_x.gifbin0 -> 1165354 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file4_non_rect_region.gif (renamed from FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/non_rect_region.gif)bin2529511 -> 2529511 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file5_elementary_area.gif (renamed from FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/elementary_area.gif)bin547368 -> 547368 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file6_doing_integration.gifbin0 -> 3349455 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file7_int_process_of_example.gifbin0 -> 3031924 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/surface.gifbin3365528 -> 0 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/y_limit_dependent_on_x.gifbin1170435 -> 0 bytes
-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.py (renamed from FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's_theorem/surface1.py)0
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file2_surface2.py (renamed from FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's_theorem/surface2.py)16
-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.gif (renamed from FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's_theorem/surface1.gif)bin3752052 -> 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
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's_theorem/surface2.gifbin2556585 -> 0 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/README.md9
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file1_grad_of_scalar_function.py317
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file2_line_int_independent_of_path.py174
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file3_line_int_example.py149
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file1_grad_of_scalar_function.gifbin0 -> 4058562 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file2_line_int_independent_of_path.gifbin0 -> 1409001 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file3_line_int_example.gifbin0 -> 1385308 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/README.md15
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file1_scalar_line_int_as_sum.py227
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file2_scalar_line_integral.py427
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file3_vector_line_int_as_sum.py326
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file4_vector_line_integral.py374
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file5_helix.py245
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file1_scalar_line_int_as_sum.gifbin0 -> 1058303 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file2_scalar_line_integral.gifbin0 -> 3301509 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file3_vector_line_int_as_sum.gifbin0 -> 1670998 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file4_vector_line_integral.gifbin0 -> 2243758 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file5_helix.gifbin0 -> 1237895 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/README.md11
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file1_vector_fields.py350
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file2_grad_of_scalar_function.py320
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file3_constructing_vector_field.py196
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file4_slope_field.py247
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file1_vector_fields.gifbin0 -> 5384744 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file2_grad_of_scalar_function.gifbin0 -> 6913246 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file3_constructing_vector_field.gifbin0 -> 3838142 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file4_slope_field.gifbin0 -> 1860382 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/README.md4
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file1_flux@_various_points.gifbin0 -> 4439959 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file1_flux@_various_points.py60
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file2_different_valuesof_Div.gifbin0 -> 595705 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file2_different_valuesof_Div.py91
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/README.md6
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file1_flux_through_circle.gifbin0 -> 3561130 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file1_flux_through_circle.py43
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file3_normal_vector.gifbin0 -> 24776215 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file3_normal_vector.py47
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file4_cube_surface.gifbin0 -> 14969816 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file4_cube_surface.py196
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/strokes-theorem/README.md0
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/README.md10
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/cube.gifbin0 -> 4624266 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file1_projection.py89
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file2_cube.py75
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file3_cube_sideC.py96
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file4_pauseandponder.py77
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file5_surface.gifbin0 -> 7241572 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file5_surface.py (renamed from FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/surface.py)37
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/pauseandponder.gifbin0 -> 1477023 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/projection.gifbin0 -> 4142689 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/sideC.gifbin0 -> 3483849 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/README.md6
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file1_3D_crossproduct.gifbin0 -> 9073424 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file1_3D_crossproduct.py120
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_cylindrical_coordinates.gifbin0 -> 6912988 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_cylindrical_coordinates.py164
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_spherical_coordinates.gifbin0 -> 7158240 bytes
-rw-r--r--FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_spherical_coordinates.py159
-rw-r--r--FSF-2020/calculus/intro-to-calculus/README.md8
-rw-r--r--FSF-2020/calculus/intro-to-calculus/fundamental-theorem-of-calculus/README.md3
-rw-r--r--FSF-2020/calculus/intro-to-calculus/fundamental-theorem-of-calculus/fundamental1.py72
-rw-r--r--FSF-2020/calculus/intro-to-calculus/gabriels-horn/README.md8
-rw-r--r--FSF-2020/calculus/intro-to-calculus/gabriels-horn/gabriel1.py65
-rw-r--r--FSF-2020/calculus/intro-to-calculus/gabriels-horn/gabriel2.py43
-rw-r--r--FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/README.md8
-rw-r--r--FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/convergence.py57
-rw-r--r--FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/divergence.py111
-rw-r--r--FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/taylorseries.py67
-rw-r--r--FSF-2020/calculus/intro-to-calculus/intro-to-derivative/README.md8
-rw-r--r--FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative1.py55
-rw-r--r--FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative2.py78
-rw-r--r--FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative3.py57
-rw-r--r--FSF-2020/calculus/intro-to-calculus/limit/README.md18
-rw-r--r--FSF-2020/calculus/intro-to-calculus/limit/Test1.py34
-rw-r--r--FSF-2020/calculus/intro-to-calculus/limit/Test2.py26
-rw-r--r--FSF-2020/calculus/intro-to-calculus/limit/limit1.py105
-rw-r--r--FSF-2020/calculus/intro-to-calculus/limit/limit3.py95
-rw-r--r--FSF-2020/calculus/intro-to-calculus/limit/limitfin1.py76
-rw-r--r--FSF-2020/calculus/intro-to-calculus/limit/limitfin2.py70
-rw-r--r--FSF-2020/calculus/intro-to-calculus/riemann-integrals/README.md18
-rw-r--r--FSF-2020/calculus/intro-to-calculus/riemann-integrals/RiemannRectanglesAnimation.py66
-rw-r--r--FSF-2020/calculus/intro-to-calculus/riemann-integrals/mimi.py53
-rw-r--r--FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect1.py31
-rw-r--r--FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect2.py31
-rw-r--r--FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect3.py31
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/README.md20
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file1.gifbin0 -> 828501 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file2a.gifbin0 -> 622617 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file2b.gifbin0 -> 635274 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file3.gifbin0 -> 955375 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file4.gifbin0 -> 660267 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file5.gifbin0 -> 177766 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file6.gifbin0 -> 955375 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file7.gifbin0 -> 793582 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/video1_DividingAToneIntoItsConstituents.py83
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/video2_ColorsAnalogyForFourierSeries.py146
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/video3_seriesVSTransform.py129
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/video4_FourierSeriesOfSquarePulse.py97
-rw-r--r--FSF-2020/calculus/series-and-transformations/Fourier Transform/video5_CoinsAnalogy.py225
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/README.md21
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/file1_laplaceTransformBasic.py67
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/file2_differentialEqSimplification.py78
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/file3_unitStepFunction.py168
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/file4_diracBasic.py61
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/file5_formationDiracDeltaFunction.py142
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/DiracFunction.gifbin0 -> 60841 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/DiracFunctionFormation.gifbin0 -> 315096 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/LtransformDiracFunction.gifbin0 -> 99703 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/LtransformUnitStepFunction.gifbin0 -> 151025 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/UnitStepFunctionExample.gifbin0 -> 192755 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/basicIntuition.gifbin0 -> 113203 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/solvingDEintuition.gifbin0 -> 196162 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/unitStepFunction.gifbin0 -> 56604 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/PowerSeriesQuestions.pdfbin112622 -> 118730 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/README.md14
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/gifs/file1_convergence_Intuition.gifbin0 -> 254804 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/gifs/file1a_convergence_Intuition.gifbin0 -> 123534 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/gifs/file2_convergence_of_a_function.gifbin0 -> 503569 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/gifs/file3_radius_and_intervalOfConvergence.gifbin0 -> 441251 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/gifs/file4_UniformConvergence.gifbin0 -> 261713 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/gifs/file4a_UniformConvergence.gifbin0 -> 476231 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/script1.py128
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/video1_convergence_Intuition.py (renamed from FSF-2020/calculus/series-and-transformations/Power Series/script2.py)37
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/video2_convergence_of_a_function.py (renamed from FSF-2020/calculus/series-and-transformations/Power Series/script3.py)9
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/video3_radius_and_intervalOfConvergence.py (renamed from FSF-2020/calculus/series-and-transformations/Power Series/script4.py)20
-rw-r--r--FSF-2020/calculus/series-and-transformations/Power Series/video4_UniformConvergence.py (renamed from FSF-2020/calculus/series-and-transformations/Power Series/script5.py)43
-rw-r--r--FSF-2020/calculus/series-and-transformations/README.md11
-rw-r--r--FSF-2020/calculus/series-and-transformations/Taylor Series/README.md11
-rw-r--r--FSF-2020/calculus/series-and-transformations/Taylor Series/TaylorSeriesQuestions.pdfbin119804 -> 125254 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file1_Example_TaylorExpansion.gifbin0 -> 667237 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file2_TaylorExpansionGeneralForm.gifbin0 -> 640160 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file2a_TaylorExpansionGeneralForm.gifbin0 -> 640160 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file3_radiusOfConvergence.gifbin0 -> 609653 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file4_DivergentRemainder.gifbin0 -> 400593 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Taylor Series/video1_Example_TaylorExpansion.py (renamed from FSF-2020/calculus/series-and-transformations/Taylor Series/script1.py)83
-rw-r--r--FSF-2020/calculus/series-and-transformations/Taylor Series/video2_TaylorExpansionGeneralForm.py (renamed from FSF-2020/calculus/series-and-transformations/Taylor Series/script2.py)107
-rw-r--r--FSF-2020/calculus/series-and-transformations/Taylor Series/video3_radiusOfConvergence.py (renamed from FSF-2020/calculus/series-and-transformations/Taylor Series/script3.py)22
-rw-r--r--FSF-2020/calculus/series-and-transformations/Taylor Series/video4_DivergentRemainder.py (renamed from FSF-2020/calculus/series-and-transformations/Taylor Series/script4.py)9
-rw-r--r--FSF-2020/calculus/series-and-transformations/Z-Transform/README.md9
-rw-r--r--FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file1.gifbin0 -> 408025 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file2.gifbin0 -> 643692 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file3.gifbin0 -> 585127 bytes
-rw-r--r--FSF-2020/calculus/series-and-transformations/Z-Transform/video1_Sampling.py81
-rw-r--r--FSF-2020/calculus/series-and-transformations/Z-Transform/video2_ZTransformOfDelta.py121
-rw-r--r--FSF-2020/calculus/series-and-transformations/Z-Transform/video3_RegionOfConvergence.py144
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/README.md18
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file1_introduction.py33
-rwxr-xr-xFSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file2_projections.py79
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file3_orthonormal.py335
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file4_Non_Standard_Basis.py69
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file5.gifbin0 -> 17680572 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file6.gifbin0 -> 6343293 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file7.gifbin0 -> 603223 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file8.gifbin0 -> 1027000 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/README.md30
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file10.gifbin0 -> 9471592 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file11.gifbin0 -> 52608896 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file12.gifbin0 -> 31583525 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file13.gifbin0 -> 3303032 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file14.gifbin0 -> 1389092 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file1_transformations.py73
-rwxr-xr-xFSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file2_before_matrix.py233
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file3_square.py246
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file4_Understand_Linear_Transformations_visually.py (renamed from FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file1_Understand_Linear_Transformations_visually.py)0
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file5_Uniform_Scaling.py (renamed from FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file2_Uniform_Scaling.py)0
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file6_Horizontal_Shear.py (renamed from FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file3_Horizontal_Shear.py)0
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file6_Horizontal_Shear_gif.gif (renamed from FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file3_Horizontal_Shear_gif.gif)bin1566999 -> 1566999 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file7_Vertical_Shear.py (renamed from FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file4_Vertical_Shear.py)0
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file7_Vertical_Shear_gif.gif (renamed from FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file4_Vertical_Shear_gif.gif)bin1347079 -> 1347079 bytes
-rwxr-xr-xFSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file8_linear_transformation.py27
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file9.gifbin0 -> 14973890 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/README.md15
-rwxr-xr-xFSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file1_orthogonal.py40
-rwxr-xr-xFSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file2_sum_of_projections_part1.py133
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file3_sum_of_projections_part2.py181
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file4.gifbin0 -> 1733367 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file5.gifbin0 -> 5430037 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file6.gifbin0 -> 21739496 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/README.md7
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/README.md30
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file10_Left_Null_Space_pSv8iio_d5Sy9qS.gifbin0 -> 1744023 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file11.gifbin0 -> 2669469 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file12.gifbin0 -> 14917563 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file13.gifbin0 -> 4257387 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file14.gifbin0 -> 28796385 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file15.gifbin0 -> 16130920 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file16.gifbin0 -> 15623398 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file17.gifbin0 -> 15546537 bytes
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file18_NOT_in_lecture_note_Column_Space.py30
-rwxr-xr-xFSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file1_Axb.py77
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file2_CSasImage.py169
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file3_solution.py77
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file4_null_space.py91
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file5_Row_Space_part_1.py68
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file6_Row_Space_part_2.py145
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file7_Row_space_Orthogonal_Complements.py150
-rwxr-xr-xFSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file8_Left_Null_Space.py26
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file9_left_null_space.py186
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/README.md9
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file.txt3
-rwxr-xr-xFSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file1_RN_Theorem.py97
-rw-r--r--FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file2.gifbin0 -> 34430418 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/README.md9
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Basis_of_a_dual_vector_space.py126
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Dual_Basis_Example.py97
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Dual_of_a_Cube.py38
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Duality_in_Sets.py25
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Linear_Functional.py29
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Basis_of_a_dual_vector_space.mp4bin0 -> 1001766 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Dual_Basis_Example.mp4bin0 -> 1075193 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Dual_of_a_Cube.mp4bin0 -> 1425728 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Duality_in_Sets.mp4bin0 -> 126824 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Linear_functional.mp4bin0 -> 261541 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Function_Scalar_Multiplication.py62
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Function_Space_Addition.py89
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Integral_Properties.py77
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Addition_of_Functions.gifbin0 -> 510988 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Function_Space_Example.gifbin0 -> 1783321 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Scalar_Multiplicaton_of_Functions.gifbin0 -> 350289 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Conjugate_Symmetry_and_Positivity_of_Inner_Product.py141
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Inner_Product_Example.py182
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Inner_product.py28
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Instances_of_Topological_Spaces.py36
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Interpretation_of_Norm_as_Length.py42
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Linearity_of_Inner_Product.py28
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Projection-in-3D-space.py31
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Vector_Projection.py43
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Conjugate_Symmetry_and_Positivity_of_Inner_Product.mp4bin0 -> 2989426 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/InnerProduct.gifbin0 -> 219685 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Inner_Product_Space_Example.mp4bin0 -> 3881235 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Instances_of_Topological_Spaces.gifbin0 -> 513000 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Interpretation_of_norm_as_length.gifbin0 -> 98767 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Linerity_of_Inner_Product.mp4bin0 -> 3600375 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Projection.gifbin0 -> 1093343 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Projection_of_vectors_in-3D_plane.mp4bin0 -> 361410 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Basis of a Vector Space and its Subspace.docxbin0 -> 13069 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Dual of a Space MCQ Questions.docxbin0 -> 13525 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Inner Product Space MCQ Questions.docxbin0 -> 13559 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Polynomial and Function Spaces MCQ Questions.docxbin0 -> 13345 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Vector Spaces MCQ Questions.docxbin0 -> 14568 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Basis.py174
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Intersection_of_Subspaces.py52
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Straight_Line_through_Origin.py48
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Subspace_Non_Example.py25
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Unit_Circle.py68
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Basis_generating_the_whole_2D_space.mp4bin0 -> 10252339 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Intersection_of_Subspaces.mp4bin0 -> 1112086 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Linear-Dependence-and-Independence.mp4bin0 -> 12080022 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Straight_Line_Through_Origin.gifbin0 -> 314823 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Subspace_Non_Example.mp4bin0 -> 818876 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Unit_Circle.gifbin0 -> 149852 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/linear_dependence_and_independence.py293
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/3D_Vector_Space.py14
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/Vector_Addition_and_Scalar_Multiplication.py177
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/Vector_Space_As_Functions.py62
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/3D_Vector_Space.gifbin0 -> 1976679 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/Function_Vector_Space_Example.gifbin0 -> 634786 bytes
-rw-r--r--FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/Vector_Addition_and_Scalar_Multiplication.mp4bin0 -> 2830120 bytes
488 files changed, 21597 insertions, 816 deletions
diff --git a/FSF-2020/approximations-and-optimizations/Critical Points/example.py b/FSF-2020/approximations-and-optimizations/Critical Points/example.py
deleted file mode 100644
index 3a41be7..0000000
--- a/FSF-2020/approximations-and-optimizations/Critical Points/example.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from manimlib.imports import*
-
-class ExampleAnimation(ThreeDScene):
- def construct(self):
- axes = ThreeDAxes()
-
- f_text = TextMobject("$f(x,y) = (y-x)(1-2x-3y)$").to_corner(UL)
- d = Dot(np.array([0,0,0]), color = '#800000') #---- Critical Point
- d_text = TextMobject("$(0.2,0.2)$",color = '#DC143C').scale(0.5).shift(0.2*UP) #----x = 0.2, y = 0.2
- r_text=TextMobject("Critical Point",color = '#00FFFF').shift(0.3*DOWN).scale(0.6)
-
- #----f(x,y) = (y-x)(1-2x-3y)
- f = ParametricSurface(
- lambda u, v: np.array([
- u,
- v,
- (v-u)*(1-2*u-3*v)
- ]),v_min = -1, v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [PURPLE_D, PURPLE_E],
- resolution=(20, 20)).scale(1)
-
- self.set_camera_orientation(phi = 75 * DEGREES)
- self.begin_ambient_camera_rotation(rate=0.5)
-
- self.add_fixed_in_frame_mobjects(f_text)
- self.wait(1)
- self.add(axes)
- self.play(Write(f),Write(d))
- self.wait(1)
- self.add_fixed_in_frame_mobjects(d_text)
- self.wait(1)
- self.add_fixed_in_frame_mobjects(r_text)
- self.wait(3)
diff --git a/FSF-2020/approximations-and-optimizations/Critical Points/motivation.py b/FSF-2020/approximations-and-optimizations/Critical Points/motivation.py
deleted file mode 100644
index 27354ef..0000000
--- a/FSF-2020/approximations-and-optimizations/Critical Points/motivation.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from manimlib.imports import*
-
-class MotivationAnimation(Scene):
- def construct(self):
-
- r = Rectangle(height = 7,breadth = 2,color = BLUE, fill_opacity = 0.3).scale(0.6) #----metal strip
- b = Brace(r,UP)
- r_text = TextMobject("$x$ metres",color = YELLOW).shift(3*UP)
- m_text = TextMobject("Metal Strip").shift(3*DOWN)
- a = Arc(radius=2).rotate(1).shift(LEFT+0.5*UP)
- a2 = Arc(radius=2).rotate(5).shift(0.7*LEFT+0.9*UP).scale(0.2)
- START = [1,0,0]
- END = [0,3,0]
- l = Line(START,END,color = RED).shift(0.9*DOWN)
- a2_text = TextMobject("$\\theta$",color = PINK).shift(1.6*UP+0.4*RIGHT)
-
- group1 = VGroup(r_text,b,a,l,a2,a2_text)
- f_text = TextMobject("$A = f(x,\\theta)$").shift(2*DOWN)
-
- ring = Annulus(inner_radius = 0.7, outer_radius = 1, color = BLUE) #--bent metal strip
-
- self.play(Write(r))
- self.wait(1)
- self.play(ShowCreation(m_text))
- self.wait(1)
- self.play(Write(group1))
- self.wait(2)
- self.play(FadeOut(group1))
- self.wait(1)
- self.play(ReplacementTransform(r,ring),ShowCreation(f_text))
diff --git a/FSF-2020/approximations-and-optimizations/Critical Points/theorem.py b/FSF-2020/approximations-and-optimizations/Critical Points/theorem.py
deleted file mode 100644
index 7c82aa9..0000000
--- a/FSF-2020/approximations-and-optimizations/Critical Points/theorem.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from manimlib.imports import*
-
-class TheoremAnimation(ThreeDScene):
- def construct(self):
-
- axes = ThreeDAxes()
-
- #----parabola: x**2+y**2
- parabola1 = ParametricSurface(
- lambda u, v: np.array([
- u,
- v,
- u**2+v**2
- ]),v_min = -1, v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [TEAL_E],
- resolution = (20, 20)).scale(1)
-
- #----parabola: -x**2-y**2
- parabola2 = ParametricSurface(
- lambda u, v: np.array([
- u,
- v,
- -u**2-v**2
- ]),v_min = -1, v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [PURPLE_E,PURPLE_E],
- resolution = (20, 20)).scale(1)
-
- self.set_camera_orientation(phi = 75 * DEGREES)
- self.begin_ambient_camera_rotation(rate = 0.4)
-
- d = Dot(np.array([0,0,0]), color = '#800000') #---- critical point
- r = Rectangle(fill_color = '#C0C0C0',fill_opacity = 0.3).move_to(ORIGIN) #----tangent plane
-
- parabola1_text = TextMobject("Maximum with horizontal tangent plane").scale(0.7).to_corner(UL)
-
- parabola2_text = TextMobject("Minimum with horizontal tangent plane").scale(0.7).to_corner(UL)
-
- self.add(axes)
- self.add_fixed_in_frame_mobjects(parabola2_text)
- self.wait(1)
- self.play(Write(parabola1))
- self.wait(1)
- self.play(ShowCreation(d))
- self.wait(1)
- self.play(ShowCreation(r))
- self.wait(2)
- self.play(FadeOut(parabola2_text),FadeOut(parabola1),FadeOut(r),FadeOut(d))
-
- self.wait(1)
- self.add_fixed_in_frame_mobjects(parabola1_text)
- self.wait(1)
- self.play(Write(parabola2))
- self.wait(1)
- self.play(ShowCreation(d))
- self.wait(1)
- self.play(ShowCreation(r))
- self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/README.md b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/README.md
new file mode 100644
index 0000000..857d298
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/README.md
@@ -0,0 +1,38 @@
+<h1><div align=”center”><b>SubTopic: Critical Points</b></h1></div>
+<br/></br>
+
+<tab>file1_Critical_Point_of_a_function
+
+![file1_Critical_Point_of_a_function](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file1_Critical_Point_of_a_function.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file2_Traces_and_Tangent
+
+![file2_Traces_and_Tangent](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file2_Traces_and_Tangent.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file3_Tangent_plane_at_extrema_of_a_function
+
+![file3_Tangent_plane_at_extrema_of_a_function](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file3_Tangent_plane_at_extrema_of_a_function.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file4_Relative_Maximum_and_Relative_Minimum
+
+![file4_Relative_Maxima_and_Relative_Minima](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file4_Relative_Maximum_and_Relative_Minimum.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file5_Saddle_Point
+
+![file5_Saddle_Point](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file5_Saddle_Point.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file6_f(x,y)=(y-x)(1-2x-3y)
+
+![file6_f(x,y)=(y-x)(1-2x-3y)](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file6_f(x%2Cy)%3D(y-x)(1-2x-3y).gif?raw=true)
+<br/></br>
+<br/></br>
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file1_Critical_Point_of_a_function.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file1_Critical_Point_of_a_function.gif
new file mode 100644
index 0000000..ca3989c
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file1_Critical_Point_of_a_function.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file1_Critical_Point_of_a_function.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file1_Critical_Point_of_a_function.py
new file mode 100644
index 0000000..e8cb08d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file1_Critical_Point_of_a_function.py
@@ -0,0 +1,77 @@
+from manimlib.imports import*
+import math as m
+
+#---- case 1: parial derivatives exist at critical point of the function
+class firstScene(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.5,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.5,5.5,0]).rotate(-4.5) #---- y axis
+
+ #---- f(x,y) = e^(-10x^2-10y^2)
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ m.exp(-10*u**2-10*v**2)
+ ]),u_min = -1, u_max = 1, v_min = -1, v_max = 1, checkerboard_colors = [TEAL_E,TEAL_D,TEAL_C,TEAL_B]).fade(0.6).scale(3.5).shift([0,0,1.5])
+
+ l1 = Line([0,0,3.75],[0,0,0],color = '#800000')
+
+ d = Dot([0,0,3.75],color = '#800000') #---- critical point
+
+ d_text = TextMobject("$\\frac{\\partial f}{\\partial x}=\\frac{\\partial f}{\\partial y} = 0$").scale(0.8).to_corner(UL)
+
+ f_text = TextMobject("Critical Point ",color = YELLOW).shift(3.4*UP).scale(0.5)
+
+ self.set_camera_orientation(phi = 45*DEGREES, theta = 40*DEGREES)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.add_fixed_in_frame_mobjects(d_text)
+ self.begin_ambient_camera_rotation(rate = 0.2)
+ self.play(Write(surface))
+ self.wait(1)
+ self.play(Write(l1))
+ self.play(Write(d))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(f_text)
+ self.wait(3)
+ self.play(FadeOut(f_text),FadeOut(surface),FadeOut(axes),FadeOut(d_text),FadeOut(d),FadeOut(l1),FadeOut(label_x),FadeOut(label_y))
+
+
+#---- case 2: parial derivatives do not exist at critical point of the function
+class secondScene(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.5,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.5,5.5,0]).rotate(-4.5) #---- y axis
+
+ #---- g(x,y)= |x|+|y|
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ abs(u)+abs(v)
+ ]),u_min = -1.5, u_max = 1.5, v_min = -1.5, v_max = 1.5, checkerboard_colors = [TEAL_E,TEAL_D,TEAL_C,TEAL_B])
+
+ d2 = Dot([0,0,0],color = '#800000') #---- critical point
+
+ d2_text = TextMobject("$\\frac{\\partial f}{\\partial x}$ and/or $\\frac{\\partial f}{\\partial y}$ does not exist").scale(0.7).to_corner(UL)
+
+ g_text = TextMobject("Critical Point",color = YELLOW).shift(1.2*RIGHT).scale(0.6)
+
+ self.set_camera_orientation(phi = 60*DEGREES, theta = 40*DEGREES)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.add_fixed_in_frame_mobjects(d2_text)
+ self.begin_ambient_camera_rotation(rate = 0.2)
+ self.wait(1)
+ self.play(Write(surface2))
+ self.wait(1)
+ self.play(Write(d2))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(g_text)
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file2_Traces_and_Tangent.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file2_Traces_and_Tangent.gif
new file mode 100644
index 0000000..84acf2e
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file2_Traces_and_Tangent.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file2_Traces_and_Tangent.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file2_Traces_and_Tangent.py
new file mode 100644
index 0000000..4b020e1
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file2_Traces_and_Tangent.py
@@ -0,0 +1,88 @@
+from manimlib.imports import*
+import math as m
+
+#---- tangent to the trace with x constant
+class firstScene(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes().scale(1)
+ label_x = TextMobject("$x$").shift([5.8,-0.5,0])
+ label_y = TextMobject("$y$").shift([-0.5,-5.6,0]).rotate(-4.5)
+
+ #---- graph of f(x,y) = -x^2-y^2
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ -u**2-v**2
+ ]),u_min=-1,u_max=1, v_min=-1,v_max=1,checkerboard_colors=[PURPLE_C,PURPLE_D,PURPLE_E,PURPLE_B]).scale(1.5).shift([0,0,2]).rotate(0.2)
+
+ #---- curve(trace) along y axis
+ curve = ParametricSurface(
+ lambda u, v: np.array([
+ u*0.4,
+ v,
+ -v**2
+ ]),v_min =-1 , v_max =1 , u_min = -0.1, u_max = 0.1).scale(1.6).shift([0.02,0.1,2.3]).set_color("#800000").rotate(0.1)
+
+ d = Dot(color =YELLOW).shift([-0.05,-0.2,2.3]) #---- critical point
+
+ x_text = TextMobject("Tangent to the trace with $x$ constant at critical point").shift(3*RIGHT+2*UP).scale(0.5).to_corner(UL)
+
+ tangent_line = Line([-0.05,-1.5,2.3],[-0.05,1.5,2.3],color = '#228B22')
+
+ self.add(axes)
+ self.set_camera_orientation(phi = 40 * DEGREES, theta = 55 * DEGREES)
+ self.begin_ambient_camera_rotation(rate = 0.1)
+ self.add(label_x)
+ self.add(label_y)
+ self.play(Write(surface))
+ self.add_fixed_in_frame_mobjects(x_text)
+ self.add(curve)
+ self.wait(1)
+ self.play(Write(tangent_line),Write(d))
+ self.wait(1)
+
+
+
+#---- tangent to the trace with y constant
+class secondScene(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes().scale(1)
+ label_x = TextMobject("$x$").shift([5.8,-0.5,0])
+ label_y = TextMobject("$y$").shift([-0.5,-5.6,0]).rotate(-4.5)
+
+ #---- graph of f(x,y) = -x^2-y^2
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ -u**2-v**2
+ ]),u_min = -1, u_max = 1, v_min = -1, v_max = 1, checkerboard_colors = [PURPLE_B,PURPLE_C,PURPLE_D,PURPLE_E]).scale(1.5).shift([0,0,2]).rotate(0.2)
+
+ #---- curve(trace) along x axis
+ curve = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v*0.4,
+ -u**2
+ ]),v_min = -0.1, v_max = 0.1, u_min = -1, u_max = 1).scale(1.6).shift([0.07,0.1,2.3]).set_color("#800000")
+
+ d = Dot(color = YELLOW).shift([0,-0.2,2.3]) #---- critical point
+
+ tangent_line = Line(color = '#228B22').scale(1).shift([0,-0.2,2.3]).rotate(m.radians(190),LEFT)
+
+ y_text = TextMobject("Tangent to the trace with $y$ constant at critical point").shift(3*RIGHT+2*UP).scale(0.5).to_corner(UL)
+
+ self.add(axes)
+ self.set_camera_orientation(phi = 40 * DEGREES, theta = 55 * DEGREES)
+ self.add(label_x)
+ self.add(label_y)
+ self.begin_ambient_camera_rotation(rate = 0.1)
+ self.play(Write(surface))
+ self.add_fixed_in_frame_mobjects(y_text)
+ self.add(curve)
+ self.wait(1.5)
+ self.play(Write(tangent_line),Write(d))
+ self.wait(0.5)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file3_Tangent_plane_at_extrema_of_a_function.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file3_Tangent_plane_at_extrema_of_a_function.gif
new file mode 100644
index 0000000..14fb318
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file3_Tangent_plane_at_extrema_of_a_function.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file3_Tangent_plane_at_extrema_of_a_function.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file3_Tangent_plane_at_extrema_of_a_function.py
new file mode 100644
index 0000000..e674113
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file3_Tangent_plane_at_extrema_of_a_function.py
@@ -0,0 +1,73 @@
+from manimlib.imports import*
+
+#---- tangent plane to minima of the function
+class firstScene(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.5,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.5,5.5,0]).rotate(-4.5) #---- y axis
+
+ #---- parabola: f(x,y) = x**2 + y**2
+ parabola = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ u**2+v**2
+ ]),v_min = -1, v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [GREEN_E,GREEN_D,GREEN_C,GREEN_B], resolution = (20, 20)).scale(1)
+
+ d = Dot(np.array([0,0,0]), color = '#800000') # ---- critical point
+
+ tangent_plane = Rectangle(fill_color = '#C0C0C0', fill_opacity = 0.3).move_to(ORIGIN).fade(0.7) # ----tangent plane
+
+ parabola_text = TextMobject("Minimum with horizontal tangent plane").scale(0.7).to_corner(UL)
+
+ self.set_camera_orientation(phi = 75 * DEGREES, theta = 45 * DEGREES)
+ self.begin_ambient_camera_rotation(rate = 0.2)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.add_fixed_in_frame_mobjects(parabola_text)
+ self.wait(1)
+ self.play(Write(parabola))
+ self.play(ShowCreation(d))
+ self.wait(1)
+ self.play(ShowCreation(tangent_plane))
+ self.wait(2)
+ self.play(FadeOut(parabola_text),FadeOut(parabola),FadeOut(tangent_plane),FadeOut(d),FadeOut(label_x),FadeOut(label_y),FadeOut(axes))
+
+
+#---- tangent plane to maxima of the function
+class secondScene(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.5,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.5,5.5,0]).rotate(-4.5) #---- y axis
+
+ #----parabola: g(x,y) = -x**2-y**2
+ parabola = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ -u**2-v**2
+ ]),v_min = -1, v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [BLUE_E,BLUE_D,BLUE_C,BLUE_B], resolution = (20, 20)).scale(1)
+
+ d = Dot(np.array([0,0,0]), color = '#800000') #---- critical point
+
+ tangent_plane = Rectangle(fill_color = '#C0C0C0',fill_opacity = 0.3).move_to(ORIGIN).fade(0.7) #---- tangent plane
+
+ parabola_text = TextMobject("Maximum with horizontal tangent plane").scale(0.7).to_corner(UL)
+
+ self.set_camera_orientation(phi = 75 * DEGREES, theta = 45 * DEGREES)
+ self.begin_ambient_camera_rotation(rate = 0.2)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.add_fixed_in_frame_mobjects(parabola_text)
+ self.wait(1)
+ self.play(Write(parabola))
+ self.play(ShowCreation(d))
+ self.wait(1)
+ self.play(ShowCreation(tangent_plane))
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file4_Relative_Maximum_and_Relative_Minimum.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file4_Relative_Maximum_and_Relative_Minimum.gif
new file mode 100644
index 0000000..6b93359
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file4_Relative_Maximum_and_Relative_Minimum.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file4_Relative_Maximum_and_Relative_Minimum.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file4_Relative_Maximum_and_Relative_Minimum.py
new file mode 100644
index 0000000..3bd810d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file4_Relative_Maximum_and_Relative_Minimum.py
@@ -0,0 +1,51 @@
+from manimlib.imports import*
+import math as m
+
+#---- locating extrema of a funtion using critical points
+class Extrema(ThreeDScene):
+ def construct(self):
+
+ h_text = TextMobject("Relative Maximum and Relative Minimum",color = GREEN)
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.3,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.3,5.5,0]).rotate(-4.5) #---- y axis
+
+ #---- f(x,y) = 5(x+y)e^(-x^2-y^2)
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ 5*(u+v)*m.exp(-u**2-v**2)
+ ]),u_min = -PI, u_max = PI, v_min = -PI, v_max = PI).set_color(TEAL).shift([0,0,0]).fade(0.4)
+
+ d1 = Dot(color = YELLOW).shift([0.5,0.5,3.02]) #---- critical point for maxima
+ l1 = Line([0.5,0.5,0.1],[0.5,0.5,3],color = YELLOW)
+
+ d2 = Dot(color = YELLOW).shift([-1.15,0,-2.98]) #---- critical point for minima
+ l2 = Line([-1.15,0,0],[-1.15,0,-2.98],color = YELLOW)
+
+ max_text = TextMobject("Relative Maximum").shift(3.1*UP+1.5*RIGHT).scale(0.5)
+ min_text = TextMobject("Relative Minimum").shift(3.1*DOWN+1.5*LEFT).scale(0.5)
+
+ self.add_fixed_in_frame_mobjects(h_text)
+ self.wait(1)
+ self.wait(1)
+ self.play(FadeOut(h_text))
+ self.wait(1)
+ self.set_camera_orientation(phi = 100*DEGREES, theta = -40*DEGREES)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.play(Write(surface))
+ self.wait(1)
+ self.play(Write(l1),Write(d1))
+ self.add_fixed_in_frame_mobjects(max_text)
+ self.wait(1)
+ self.play(Write(l2),Write(d2))
+ self.add_fixed_in_frame_mobjects(min_text)
+ self.wait(1)
+ self.wait(1)
+ self.play(FadeOut(l1),FadeOut(d1),FadeOut(l2),FadeOut(d2),FadeOut(max_text),FadeOut(min_text))
+ self.begin_ambient_camera_rotation(rate = 0.3)
+ self.wait(3)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file5_Saddle_Point.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file5_Saddle_Point.gif
new file mode 100644
index 0000000..7300f3a
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file5_Saddle_Point.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file5_Saddle_Point.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file5_Saddle_Point.py
new file mode 100644
index 0000000..67dbb18
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file5_Saddle_Point.py
@@ -0,0 +1,71 @@
+from manimlib.imports import*
+import math as m
+
+#---- saddle point of a function
+class SaddlePoint(ThreeDScene):
+ def construct(self):
+
+ h_text = TextMobject("Saddle Point",color = GREEN)
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.3,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.3,5.5,0]).rotate(-4.5) #---- y axis
+
+ #---- f(x,y) = -x^2-y^2
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ u**2-v**2
+ ]),u_min = -1, u_max = 1, v_min = -1, v_max = 1,checkerboard_colors = [BLUE_B,BLUE_C,BLUE_D,BLUE_E]).shift([0,0,0]).scale(3)
+
+ #---- curve(trace) along y axis
+ curve_x = ParametricSurface(
+ lambda u, v: np.array([
+ u*0.1,
+ v,
+ v**2
+ ]),v_min = -1, v_max = 1, u_min = -0.2, u_max = 0.2).shift([0,0,-2]).scale(3.1).set_color("#800000").rotate(m.radians(180),UP)
+
+ x_text = TextMobject("A dip at critical point along x axis").scale(0.5).to_corner(UL)
+
+ #---- curve(trace) along x axis
+ curve_y = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v*0.1,
+ -u**2
+ ]),v_min = -0.2, v_max = 0.2, u_min = -1, u_max = 1).scale(3).shift([0.1,0,2.2]).set_color("#800000").rotate(m.radians(182),DOWN)
+
+ y_text = TextMobject("A peak at critical point along y axis").scale(0.5).to_corner(UL)
+
+ d = Dot(color = YELLOW).shift([0,-0.22,0]) #---- critical point(saddle point)
+
+ self.add_fixed_in_frame_mobjects(h_text)
+ self.wait(1)
+ self.play(FadeOut(h_text))
+ self.wait(1)
+ self.set_camera_orientation(phi = 75*DEGREES, theta = 40*DEGREES)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.play(Write(surface))
+ self.wait(1)
+ self.move_camera(phi = 45*DEGREES, theta = 70*DEGREES)
+ self.add(curve_y)
+ self.play(Write(d))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(x_text)
+ self.wait(1)
+ self.wait(1)
+ self.play(FadeOut(curve_y),FadeOut(d),FadeOut(x_text))
+ self.wait(1)
+ self.move_camera(phi = 40*DEGREES, theta = 30*DEGREES)
+ self.add(curve_x)
+ self.play(Write(d))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(y_text)
+ self.begin_ambient_camera_rotation(rate = 0.3)
+ self.wait(3)
+ self.play(FadeOut(curve_x),FadeOut(d),FadeOut(y_text))
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file6_f(x,y)=(y-x)(1-2x-3y).gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file6_f(x,y)=(y-x)(1-2x-3y).gif
new file mode 100644
index 0000000..4bc92f8
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file6_f(x,y)=(y-x)(1-2x-3y).gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file6_f(x,y)=(y-x)(1-2x-3y).py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file6_f(x,y)=(y-x)(1-2x-3y).py
new file mode 100644
index 0000000..41c3b61
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical-Points/file6_f(x,y)=(y-x)(1-2x-3y).py
@@ -0,0 +1,29 @@
+from manimlib.imports import*
+
+#---- visualization of the function
+class ExampleAnimation(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.5,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.5,5.5,0]).rotate(-4.5) #---- y axis
+
+ #---- f(x,y) = (y-x)(1-2x-3y)
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ (v-u)*(1-2*u-3*v)
+ ]),v_min = -1, v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [PURPLE_B,PURPLE_C,PURPLE_D, PURPLE_E]).scale(1).fade(0.2).shift([0.2,0.2,0])
+
+ f_text = TextMobject("$f(x,y) = (y-x)(1-2x-3y)$").to_corner(UL)
+
+ self.set_camera_orientation(phi = 60 * DEGREES, theta = 75 * DEGREES)
+ self.begin_ambient_camera_rotation(rate=0.1)
+ self.add_fixed_in_frame_mobjects(f_text)
+ self.wait(1)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.wait(1)
+ self.play(Write(f))
+ self.wait(4)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/README.md b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/README.md
new file mode 100644
index 0000000..903eaed
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/README.md
@@ -0,0 +1,26 @@
+<h1><div align=”center”><b>SubTopic: Lagrange Multipliers</b></h1></div>
+<br/></br>
+
+<tab>file1_Extrema_over_g(x,y)
+
+![file1_Extrema_over_g(x,y)](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file1_Extrema_over_g(x%2Cy)%3Dk.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file2_Constraint_circle_with_contour_plot_of_the_surface_x^2+y^2+x^3-y^3
+
+![file2_Constraint_circle_with_contour_plot_of_the_surface_x^2+y^2+x^3-y^3](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file2_Constraint_circle_with_contour_plot_of_the_surface_x%5E2%2By%5E2%2Bx%5E3-y%5E3.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file3_Geometric_Proof
+
+![file3_Geometric_Proof](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file3_Geometric_Proof.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file4_Constraints_g_and_h
+
+![file4_Constraints_g_and_h](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file4_Constraints_g_and_h.gif?raw=true)
+<br/></br>
+<br/></br>
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file1_Extrema_over_g(x,y)=k.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file1_Extrema_over_g(x,y)=k.gif
new file mode 100644
index 0000000..9a9042f
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file1_Extrema_over_g(x,y)=k.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file1_Extrema_over_g(x,y)=k.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file1_Extrema_over_g(x,y)=k.py
new file mode 100644
index 0000000..b7adcc7
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file1_Extrema_over_g(x,y)=k.py
@@ -0,0 +1,45 @@
+from manimlib.imports import*
+import math as m
+
+#---- optimizing funtion f(x,y) w.r.t to g(x,y)
+class ConstrainedExtrema(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes().scale(0.7).rotate(math.radians(180))
+ label_x = TextMobject("$x$").shift(4*LEFT).fade(0.4) #---- x axis
+ label_y = TextMobject("$y$").shift(3.2*DOWN+0.2*RIGHT).rotate(math.radians(180)).fade(0.4) #---- y axis
+
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ u**2+v**2+u**3-v**3
+ ]),u_min=-0.5,u_max=0.5, v_min=-0.5,v_max=0.5).scale(5).shift([0,1,2.5]).set_color(TEAL).fade(0.2)
+
+ c = Circle(color='#FF00FF',fill_opacity=0.3).shift([-0.4,0,1.5]).rotate(1.9,UP).scale(0.7)
+
+ minima = Dot(color = '#4169E1').shift([-0.5,0.5,1]).rotate(1.571,UP)
+ maxima = Dot(color = '#4169E1').shift([0.1,0,2.2]).rotate(1.571,UP)
+
+ max_text = TextMobject("maximum over $g(x,y)=k$",color = '#FFA074').scale(0.6).shift(2.3*UP+2*LEFT)
+ min_text = TextMobject("minimum over $g(x,y)=k$",color = '#FFA074').shift([2.5,0.5,1]).scale(0.6).shift(0.5*UP)
+ label_f = TextMobject("$z=f(x,y)$",color=TEAL).scale(0.8).shift(3*UP+3*RIGHT)
+ label_g = TextMobject("g(x,y)=k",color = PURPLE).scale(0.5).shift(1.5*UP+0.8*LEFT)
+
+
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.set_camera_orientation(phi=75*DEGREES,theta=45*DEGREES)
+ self.play(Write(surface))
+ self.add_fixed_in_frame_mobjects(label_f)
+ self.wait(2)
+ self.play(Write(c))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(label_g)
+ self.wait(1)
+ self.play(Write(maxima))
+ self.add_fixed_in_frame_mobjects(max_text)
+ self.wait(1)
+ self.play(Write(minima))
+ self.add_fixed_in_frame_mobjects(min_text)
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file2_Constraint_circle_with_contour_plot_of_the_surface_x^2+y^2+x^3-y^3.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file2_Constraint_circle_with_contour_plot_of_the_surface_x^2+y^2+x^3-y^3.gif
new file mode 100644
index 0000000..d8e03fd
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file2_Constraint_circle_with_contour_plot_of_the_surface_x^2+y^2+x^3-y^3.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file2_Constraint_circle_with_contour_plot_of_the_surface_x^2+y^2+x^3-y^3.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file2_Constraint_circle_with_contour_plot_of_the_surface_x^2+y^2+x^3-y^3.py
new file mode 100644
index 0000000..bbbf238
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file2_Constraint_circle_with_contour_plot_of_the_surface_x^2+y^2+x^3-y^3.py
@@ -0,0 +1,72 @@
+from manimlib.imports import*
+import math as m
+
+#---- contour plot of the surface with constraint circle
+class ContourScene(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes().scale(0.7).rotate(m.radians(180)).fade(0.6)
+ label_x = TextMobject("$x$").shift(4*LEFT).fade(0.4) #---- x axis
+ label_y = TextMobject("$y$").shift(3.2*DOWN+0.2*RIGHT).rotate(m.radians(180)).fade(0.4) #---- y axis
+
+ #---- surface of the function f(x,y) = x^2+y^2+x^3-y^3
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ u**2+v**2+u**3-v**3
+ ]),u_min=-0.5,u_max=0.5, v_min=-0.5,v_max=0.5).scale(5).shift([0,-0.5,2.5]).set_color(TEAL).fade(0.5)
+
+
+ #---- contour plots of the surface of the function
+
+ c0 = Circle(color = '#800000').scale(0.5).shift([0,-0.5,0])
+ c1 = Circle(color = '#800000').scale(1).shift([0,-0.5,0])
+ c2 = Circle(color = '#800000').scale(1.5).shift([0,-0.5,0])
+ c3 = Circle(color = '#800000').scale(2).shift([0,-0.5,0])
+ c4 = Circle(color = '#800000').scale(2.5).shift([0,-0.5,0])
+
+ #---- constraint circle
+ circle = Circle(color='#FF00FF',fill_opacity=0.3).shift([-0.5,-1.2,1.5]).rotate(1.9,UP).scale(0.8)
+ circle2 = Circle(color='#FF00FF',fill_opacity=0.3).shift([0.74,0.95,1.5]).rotate(1.9,UP).scale(0.8)
+
+ maxima = Dot(color = '#4169E1').shift([0.7,0.15,1.5]) #---- point of maxima
+ minima = Dot(color = '#4169E1').shift([0.8,1.7,1.5]) #---- point of minima
+
+ min_text = TextMobject("minimum over $g(x,y)=k$",color = '#FFA074').scale(0.6).shift([-2,0.16,1.5])
+ max_text = TextMobject("maximum over $g(x,y)=k$",color = '#FFA074').shift([-2.3,-2.6,1.5]).scale(0.6).shift(0.5*UP)
+
+
+ #---- labelling contour curves
+ label_c0 = TextMobject("1",color = '#FFA074').shift([0.2,0.1,0.5]).scale(0.5)
+ label_c1 = TextMobject("2",color = '#FFA074').shift([0.2,-0.6,0.5]).scale(0.5)
+ label_c2 = TextMobject("3",color = '#FFA074').shift([0.2,-1.1,0.5]).scale(0.5)
+ label_c3 = TextMobject("4",color = '#FFA074').shift([0.2,-1.6,0.5]).scale(0.5)
+ label_c4 = TextMobject("5",color = '#FFA074').shift([0.2,-2.1,0.5]).scale(0.5)
+
+
+ self.set_camera_orientation(phi=75 * DEGREES, theta = 45*DEGREES)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.wait(1)
+ self.play(Write(surface))
+ self.play(Write(circle))
+ self.wait(1)
+ self.play(FadeOut(circle))
+ self.wait(1)
+ self.move_camera(phi=0 * DEGREES, theta = 90*DEGREES)
+ self.wait(1)
+ self.play(Write(c0),Write(c1),Write(c2),Write(c3),Write(c4))
+ self.play(FadeOut(surface))
+ self.add_fixed_in_frame_mobjects(label_c0)
+ self.add_fixed_in_frame_mobjects(label_c1)
+ self.add_fixed_in_frame_mobjects(label_c2)
+ self.add_fixed_in_frame_mobjects(label_c3)
+ self.add_fixed_in_frame_mobjects(label_c4)
+ self.wait(1)
+ self.play(Write(circle2))
+ self.wait(1)
+ self.play(Write(minima),Write(maxima))
+ self.add_fixed_in_frame_mobjects(max_text)
+ self.add_fixed_in_frame_mobjects(min_text)
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file3_Geometric_Proof.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file3_Geometric_Proof.gif
new file mode 100644
index 0000000..e028a81
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file3_Geometric_Proof.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file3_Geometric_Proof.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file3_Geometric_Proof.py
new file mode 100644
index 0000000..2c1d668
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file3_Geometric_Proof.py
@@ -0,0 +1,89 @@
+from manimlib.imports import*
+
+#---- visualization of geometric proof of Lagrange multiplier
+class firstScene(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes().scale(0.7).rotate(math.radians(180))
+ label_x = TextMobject("$x$").shift(4*RIGHT).fade(0.4) #---- x axis
+ label_y = TextMobject("$y$").shift(3.2*DOWN+0.2*RIGHT).rotate(math.radians(180)).fade(0.4) #---- y axis
+
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ 1*np.sin(u)*np.cos(v),
+ 1*np.sin(u)*np.sin(v),
+ -1*np.sin(u)*np.sin(u)+2
+ ]),u_min=0,u_max=PI/2,v_min=0,v_max=2*PI).set_color(GREEN).scale(1).shift([-1.5,-1.5,0])
+
+ d = Dot([-2,-2.55,0],color = '#800000')
+ a_df = Arrow(color = '#00FFFF').rotate(-2).shift(3.2*DOWN+2.3*LEFT) #---- f parallel to g
+ a_dg = Arrow(color = '#FF00FF').scale(0.8).shift(3.2*DOWN+2.3*LEFT).rotate(-2) #---- f parallel to g
+
+ b_dg = Arrow(color = '#00FFFF').rotate(1.1).shift(0.82*LEFT+0.15*UP) #---- f parallel to g
+ b_df = Arrow(color = '#FF00FF').scale(0.6).rotate(-2).shift(1.43*LEFT+1.1*DOWN) #---- f parallel to g
+
+
+ qd = Dot(color = '#800000').shift(1.2*LEFT+0.6*DOWN)
+
+ l1 = Line([-1,-3.1,0],[-4,-3.1,0],color = PINK).rotate(-0.3).fade(0.6)
+ l2 = Line([-0.9,-2.9,0],[-4,-2.9,0],color = PINK).rotate(-0.3).fade(0.6)
+ l3= Line([-0.8,-2.7,0],[-4,-2.7,0],color = PINK).rotate(-0.3).fade(0.6)
+ l4= Line([-0.7,-2.45,0],[-4,-2.45,0],color = PINK).rotate(-0.3).fade(0.6)
+ l5= Line([-0.6,-2.2,0],[-4,-2.25,0],color = PINK).rotate(-0.3).fade(0.6)
+ l6 = Line([-0.5,-2,0],[-4,-2,0],color = PINK).rotate(-0.3).fade(0.6)
+ l7 = Line([-0.4,-1.8,0],[-4,-1.8,0],color = PINK).rotate(-0.3).fade(0.6)
+ l8 = Line([-0.3,-1.6,0],[-4,-1.6,0],color = PINK).rotate(-0.3).fade(0.6)
+ l9= Line([-0.2,-1.4,0],[-4,-1.4,0],color = PINK).rotate(-0.3).fade(0.6)
+ l10= Line([-0.1,-1.2,0],[-4,-1.2,0],color = PINK).rotate(-0.3).fade(0.6)
+ l11 = Line([-0,-1,0],[-4,-1,0],color = PINK).rotate(-0.3).fade(0.6)
+ l12 = Line([-0,-0.8,0],[-4,-0.8,0],color = PINK).rotate(-0.3).fade(0.6)
+ l13= Line([-0,-0.55,0],[-4,-0.55,0],color = PINK).rotate(-0.3).fade(0.6)
+ l14= Line([-0,-0.35,0],[-4,-0.35,0],color = PINK).rotate(-0.3).fade(0.6)
+ l15= Line([-0.,-0.15,0],[-4,-0.15,0],color = PINK).rotate(-0.3).fade(0.6)
+
+ rel_text = TextMobject("$\\nabla f = \\lambda \\nabla g$",color = TEAL).shift([3,3.2,0]).scale(0.5)
+
+ f_text = TextMobject("$\\nabla f$",color = '#800000').shift([1,1,0]).scale(0.5)
+ g_text = TextMobject("$\\nabla g$").shift([1.2,-0.8,0]).scale(0.5)
+
+ p_text= TextMobject("$P$").shift([1.8,2.6,0]).scale(0.5)
+
+ l1_text = TextMobject("$w=$ 17").rotate(math.radians(180)).scale(0.4).shift(2.7*DOWN+4.36*LEFT)
+ l2_text = TextMobject("$w=$ 16").rotate(math.radians(180)).scale(0.4).shift(2.46*DOWN+4.36*LEFT)
+ l3_text = TextMobject("$w=$ 15").rotate(math.radians(180)).scale(0.4).shift(2.2*DOWN+4.36*LEFT)
+ l4_text = TextMobject("$w=$ 14").rotate(math.radians(180)).scale(0.4).shift(1.97*DOWN+4.36*LEFT)
+ l5_text = TextMobject("$w=$ 13").rotate(math.radians(180)).scale(0.4).shift(1.74*DOWN+4.36*LEFT)
+ l6_text = TextMobject("$w=$ 12").rotate(math.radians(180)).scale(0.4).shift(1.5*DOWN+4.36*LEFT)
+ l7_text = TextMobject("$w=$ 11").rotate(math.radians(180)).scale(0.4).shift(1.26*DOWN+4.36*LEFT)
+ l8_text = TextMobject("$w=$ 10").rotate(math.radians(180)).scale(0.4).shift(1.05*DOWN+4.36*LEFT)
+ l9_text = TextMobject("$w=$ 9").rotate(math.radians(180)).scale(0.4).shift(0.8*DOWN+4.32*LEFT)
+ l10_text = TextMobject("$w=$ 8").rotate(math.radians(180)).scale(0.4).shift(0.6*DOWN+4.32*LEFT)
+ l11_text = TextMobject("$w=$ 7").rotate(math.radians(180)).scale(0.4).shift(0.4*DOWN+4.32*LEFT)
+ l12_text = TextMobject("$w=$ 6").rotate(math.radians(180)).scale(0.4).shift(0.2*DOWN+4.32*LEFT)
+ l13_text = TextMobject("$w=$ 5").rotate(math.radians(180)).scale(0.4).shift(-0.02*DOWN+4.32*LEFT)
+ l14_text = TextMobject("$w=$ 4").rotate(math.radians(180)).scale(0.4).shift(-0.23*DOWN+4.32*LEFT)
+ l15_text = TextMobject("$w=$ 3").rotate(math.radians(180)).scale(0.4).shift(-0.44*DOWN+4.32*LEFT)
+
+ level_Curve = VGroup(l1,l1_text,l2,l2_text,l3,l3_text,l4,l4_text,l5,l5_text,l6,l6_text,l7,l7_text,l8,l8_text,l9,l9_text,l10,l10_text,l11,l11_text,l12,l12_text,l13,l13_text,l14,l14_text,l15,l15_text)
+
+ self.set_camera_orientation(phi=0 * DEGREES, theta = 90*DEGREES)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.wait(1)
+ self.add(surface)
+ self.wait(1)
+ self.play(ShowCreation(level_Curve))
+ self.wait(1)
+ self.play(ShowCreation(a_df),ShowCreation(a_dg),Write(d))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(rel_text)
+ self.add_fixed_in_frame_mobjects(p_text)
+ self.wait(1)
+ self.play(Write(qd))
+ self.wait(1)
+ self.play(ShowCreation(b_df))
+ self.add_fixed_in_frame_mobjects(f_text)
+ self.wait(1)
+ self.play(ShowCreation(b_dg))
+ self.add_fixed_in_frame_mobjects(g_text)
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file4_Constraints_g_and_h.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file4_Constraints_g_and_h.gif
new file mode 100644
index 0000000..f1f7974
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file4_Constraints_g_and_h.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file4_Constraints_g_and_h.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file4_Constraints_g_and_h.py
new file mode 100644
index 0000000..a1396fc
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Lagrange-Multipliers/file4_Constraints_g_and_h.py
@@ -0,0 +1,52 @@
+from manimlib.imports import*
+import math as m
+
+ class Constraints(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes().rotate(m.radians(75))
+ label_x = TextMobject("$x$").shift([-5.5,1,0]).fade(0.4) #---- x axis
+ label_y = TextMobject("$y$").shift([1,5.5,0]).rotate(-4.5).fade(0.4) #---- y axis
+
+ cylinder = ParametricSurface(
+ lambda u, v: np.array([
+ np.cos(TAU * u),
+ np.sin(TAU * u),
+ 2 * (1-1.5*v)
+ ]),checkerboard_colors=[YELLOW_C,YELLOW_D,YELLOW_E]).shift([0.5,0.5,-0.13]).scale(1)
+
+ plane = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ u+v
+ ]),checkerboard_colors=[TEAL_C,TEAL_D,TEAL_E]).shift([0,0,0]).rotate(m.radians(-40),RIGHT).scale(4).fade(0.3)
+
+ c = Circle(color='#FF00FF',fill_opacity=0.3).shift([0.7,-1.3,0.4]).rotate(2.5,UP).scale(1.32)
+
+ f_text = TextMobject("$f(x,y)=x^2+y^2+z^2$",color = '#FFA074').scale(0.6).to_corner(UL)
+ g_text = TextMobject("$g(x,y)=x^2+y^2+1$",color = '#FFA074').scale(0.6).to_corner(UL)
+ h_text = TextMobject("$h(x,y)=x+y-z=1$",color = '#FFA074').scale(0.6).to_corner(UL)
+
+
+
+ self.set_camera_orientation(phi=65*DEGREES,theta=95*DEGREES)
+
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(f_text)
+ self.play(Write(c))
+ self.wait(1)
+ self.play(FadeOut(f_text))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(g_text)
+ self.play(Write(cylinder))
+ self.wait(1)
+ self.play(FadeOut(g_text))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(h_text)
+ self.play(Write(plane))
+ self.wait(1)
+ self.play(FadeOut(h_text))
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical_Points_mcq_questions.pdf b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Critical_Points_mcq_questions.pdf
index 25c4e4d..25c4e4d 100644
--- a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Critical_Points_mcq_questions.pdf
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Critical_Points_mcq_questions.pdf
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Lagrange_Multipliers_mcq_questions.pdf b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Lagrange_Multipliers_mcq_questions.pdf
new file mode 100644
index 0000000..3ba7d1c
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Lagrange_Multipliers_mcq_questions.pdf
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Tangent_Plane_Approximations_mcq_questions.pdf b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Tangent_Plane_Approximations_mcq_questions.pdf
new file mode 100644
index 0000000..2a77b15
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Tangent_Plane_Approximations_mcq_questions.pdf
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The_Second_Derivative_Test_MCQ.pdf b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/The_Second_Derivative_Test_mcq_questions.pdf
index ca60cbf..ca60cbf 100644
--- a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The_Second_Derivative_Test_MCQ.pdf
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/The_Second_Derivative_Test_mcq_questions.pdf
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Total_Differential_mcq_questions.pdf b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Total_Differential_mcq_questions.pdf
new file mode 100644
index 0000000..b1a679d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/MCQ-Questions/Total_Differential_mcq_questions.pdf
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/README.md b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/README.md
new file mode 100644
index 0000000..2a274d0
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/README.md
@@ -0,0 +1,26 @@
+<h1><div align=”center”><b>SubTopic: Tangent Plane Approximations</b></h1></div>
+<br/></br>
+
+<tab>file1_Tangent_Plane
+
+![file1_Tangent_Plane](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file1_Tangent_Plane.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file2_Tangent_plane_approximation_visualization
+
+![file2_Tangent_plane_approximation_visualization](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file2_Tangent_plane_approximation_visualization.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file3_Non_Differentiable_Function
+
+![file3_Non_Differentiable_Function](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file3_Non_Differentiable_Function.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file4_Tangent_plane_at_extrema_and_saddle_point
+
+![file4_Tangent_plane_at_extrema_and_saddle_point](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file4_Tangent_plane_at_extrema_and_saddle_point.gif?raw=true)
+<br/></br>
+<br/></br>
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file1_Tangent_Plane.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file1_Tangent_Plane.gif
new file mode 100644
index 0000000..2b8bf5f
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file1_Tangent_Plane.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file1_Tangent_Plane.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file1_Tangent_Plane.py
new file mode 100644
index 0000000..8efdbd2
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file1_Tangent_Plane.py
@@ -0,0 +1,50 @@
+from manimlib.imports import*
+
+#---- tangent plane is parallel to the surface of the funtion at a point
+class tangentplane(ThreeDScene):
+ def construct(self):
+
+ s1_text=TextMobject("Suppose, the point $(x,y)$ lies on the surface of the function.").scale(0.5).shift(2*UP)
+ s2_text=TextMobject("When zooming on that point, the surface would appear more and more like a plane.").scale(0.5).shift(1*UP)
+ s3_text=TextMobject("This plane is called the tangent plane.").scale(0.5)
+
+ #---- graph of function f(x,y) = -x^2-y^2
+
+ f = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ -u**2-v**2
+ ]),v_min = -1, v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [YELLOW_B,YELLOW_C,YELLOW_D, YELLOW_E]).shift([0,0,0]).scale(1)
+
+
+ d = Dot([0,0,0],color = '#800000') #---- critical point
+
+ r = Rectangle(color = PURPLE,fill_opacity=0.2).shift([0.1,0,0]).scale(0.3) #---- tangent plane
+
+ s = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ -u**2-v**2
+ ]),v_min = -1, v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [YELLOW_B,YELLOW_C,YELLOW_D, YELLOW_E]).shift([0,0,0]).scale(3.5)
+
+ d2 = Dot([0,0,2.5],color = '#800000') #---- changing position of critical point
+
+ r2 = Rectangle(color = PURPLE,fill_opacity=0.5).shift([0.1,0,2.5]).scale(0.3) #---- changing position of tangent plane
+
+ self.set_camera_orientation(phi = 50 * DEGREES, theta = 45 * DEGREES)
+ self.add_fixed_in_frame_mobjects(s1_text)
+ self.add_fixed_in_frame_mobjects(s2_text)
+ self.add_fixed_in_frame_mobjects(s3_text)
+ self.wait(2)
+ self.play(FadeOut(s1_text))
+ self.play(FadeOut(s2_text))
+ self.play(FadeOut(s3_text))
+ self.wait(1)
+ self.play(Write(f))
+ self.play(Write(d))
+ self.play(Write(r))
+ self.wait(2)
+ self.play(ReplacementTransform(f,s),ReplacementTransform(d,d2),ReplacementTransform(r,r2))
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file2_Tangent_plane_approximation_visualization.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file2_Tangent_plane_approximation_visualization.gif
new file mode 100644
index 0000000..6d5a67a
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file2_Tangent_plane_approximation_visualization.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file2_Tangent_plane_approximation_visualization.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file2_Tangent_plane_approximation_visualization.py
new file mode 100644
index 0000000..02576d9
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file2_Tangent_plane_approximation_visualization.py
@@ -0,0 +1,85 @@
+from manimlib.imports import*
+import math as m
+
+#---- tangent plane approximation visualization
+class ApproximationScene(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes().scale(1.2).fade(0.7)
+ label_x= TextMobject("$x$").shift([5.4,-0.5,0]).fade(0.7) #---- x axis
+ label_y= TextMobject("$y$").shift([-0.5,5.2,0]).rotate(-4.5).fade(0.7) #---- y axis
+
+ #---- graph of the function
+ s = ParametricSurface(
+ lambda u, v: np.array([
+ 1.5*np.cos(u)*np.cos(v),
+ 1.5*np.cos(u)*np.sin(v),
+ 1.5*np.sin(u)
+ ]),u_min=0,u_max=PI,v_min=PI,v_max=2*PI,checkerboard_colors=[BLUE_B,BLUE_C,BLUE_D,BLUE_E]).shift([0,1,2.4]).scale(1.3)
+
+ d1 = Dot([0.2,2.01,2.24],color = '#800000').rotate(1.1,LEFT) #---- point(x_0,y_0)
+ d1_copy = Dot([0.2,2.01,0],color = '#800000') #---- projection of point(x_0,y_0) on x-y plane
+
+ d1_text = TextMobject("$f(x_0,y_0)$",color=ORANGE).scale(0.5).shift([0.2,2.01,2.3])
+ d1_copy_text = TextMobject("$(x_0,y_0)$",color=ORANGE).scale(0.5).shift([0.2,2.01,0],4.1*DOWN)
+
+ d2 = Dot([2,2.6,3.5],color = '#800000').rotate(1,LEFT) #---- point(x,y)
+ d2_copy = Dot([2,2.6,0],color = '#800000') #---- projection of point(x,y) on x-y plane
+
+ d2_text = TextMobject("$f(x,y)$",color=ORANGE).scale(0.5).shift([0.8,1.4,1.5])
+ d2_copy_text = TextMobject("$(x,y)$",color=ORANGE).scale(0.5).shift([0.8,1.4,0],2.4*DOWN)
+
+ l1 = Line([0.2,2.01,2.21],[0.2,2.01,0],color= YELLOW).fade(0.2)
+ l2 = Line([2,2.6,3.4],[2,2.6,0],color= YELLOW).fade(0.2)
+
+ t_plane = Rectangle(color = PURPLE, fill_opacity=0.3).scale(0.6).rotate(m.radians(45),LEFT).shift([1.1,2.5,3.1]) #---- tangent plane
+ t_text= TextMobject("Tangent Plane",color = PINK).scale(0.5).shift(0.3*RIGHT+2.6*UP).rotate(math.radians(5),LEFT)
+
+ a1 = Line([0.2,2.01,0],[2,2.6,0],color ="#00FF7F")
+ a_x = Line([0.2,2.01,0],[2,2.01,0],color ="#9400D3")
+ a_y = Line([0.2,2.01,0],[0.2,2.6,0],color ="#8B4513")
+ a2 = Line([2,2.01,0],[2,2.6,0])
+ a3 = Line([0.2,2.6,0],[2,2.6,0])
+
+ ax_text = TextMobject("$f_x (x_0 , y_0 )(x – x_0 ) $").scale(0.5).shift(DOWN+0.8*LEFT).rotate(0.4)
+ ay_text = TextMobject("$ f_y (x_0 , y_0 )(y – y_0 ) $").scale(0.5).shift(0.8*DOWN+2.7*RIGHT).rotate(-0.6)
+ a1_text = TextMobject("$f_x (x_0 , y_0 )(x – x_0 ) + f_y (x_0 , y_0 )(y – y_0 )$ ").scale(0.4).rotate(0.7).shift(1.7*DOWN+0.6*RIGHT)
+
+ lines = VGroup(a1,a_y,a_x,a2,a3,d1_copy,d2_copy)
+
+
+ self.set_camera_orientation(phi = 60 * DEGREES, theta = 55 * DEGREES)
+ self.wait(1)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.play(Write(s))
+ self.wait(1)
+ self.play(Write(d2))
+ self.add_fixed_in_frame_mobjects(d1_text)
+ self.wait(1)
+ self.play(Write(t_plane))
+ self.add_fixed_in_frame_mobjects(t_text)
+ self.wait(1)
+ self.play(Write(d1))
+ self.add_fixed_in_frame_mobjects(d2_text)
+ self.wait(1)
+ self.play(Write(l1),Write(d1_copy))
+ self.add_fixed_in_frame_mobjects(d2_copy_text)
+ self.wait(1)
+ self.play(Write(l2),Write(d2_copy))
+ self.add_fixed_in_frame_mobjects(d1_copy_text)
+ self.wait(2)
+ self.play(FadeOut(d1_text),FadeOut(d1_copy_text),FadeOut(d2_text),FadeOut(d2_copy_text),FadeOut(t_text))
+ self.wait(1)
+ self.play(Write(a1),Write(a_x),Write(a_y),Write(a2),Write(a3))
+ self.wait(1)
+ self.play(FadeOut(s),FadeOut(d1),FadeOut(d2),FadeOut(l1),FadeOut(l2),FadeOut(t_plane),FadeOut(label_x),FadeOut(label_y))
+ self.wait(1)
+ lines.scale(2)
+ axes.scale(1.5)
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(ax_text)
+ self.add_fixed_in_frame_mobjects(ay_text)
+ self.add_fixed_in_frame_mobjects(a1_text)
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file3_Non_Differentiable_Function.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file3_Non_Differentiable_Function.gif
new file mode 100644
index 0000000..7581a33
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file3_Non_Differentiable_Function.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file3_Non_Differentiable_Function.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file3_Non_Differentiable_Function.py
new file mode 100644
index 0000000..79d0948
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file3_Non_Differentiable_Function.py
@@ -0,0 +1,47 @@
+from manimlib.imports import*
+import math
+
+#---- tangent plane does not exists for f(x,y): sqrt(x**2+y**2) at origin
+
+class TangenttoSurface(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes().rotate(2.3)
+ axes2 = ThreeDAxes().scale(2).rotate(2.3).shift([0,0,1.3])
+
+ #----f(x,y): sqrt(x**2+y**2)
+ p = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ -math.sqrt(u**2+v**2)
+ ]),v_min = -1,v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [RED_C,TEAL_D],
+ resolution = (20, 20)).scale(1)
+
+ #----size increased of f(x,y): sqrt(x**2+y**2)
+ p2 = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ -math.sqrt(u**2+v**2)
+ ]),v_min = -1,v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [RED_C,TEAL_D],
+ resolution = (20, 20)).scale(3).shift([0,0,0])
+
+ self.set_camera_orientation(phi = 75 * DEGREES,theta = 40*DEGREES)
+
+ d = Dot([0,0,0],color = '#800000') #---- critical point
+ d2 = Dot([0,0,1.5],color = '#800000').scale(2) #---- size increased of critical point
+
+ f_text = TextMobject("$f$ is not differentiable at origin,because the surface").scale(0.5).to_corner(UL)
+ f2_text = TextMobject("is not flat when zoomed in at the origin.").scale(0.5).to_corner(UL).shift(0.5*DOWN)
+
+ self.add(axes)
+ self.wait(1)
+ self.play(Write(p),Write(d))
+ self.wait(1)
+ self.move_camera(phi = 50 * DEGREES,theta = 40*DEGREES)
+ self.wait(1)
+ self.play(ReplacementTransform(axes,axes2),ReplacementTransform(p,p2),ReplacementTransform(d,d2))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(f_text)
+ self.add_fixed_in_frame_mobjects(f2_text)
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file4_Tangent_plane_at_extrema_and_saddle_point.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file4_Tangent_plane_at_extrema_and_saddle_point.gif
new file mode 100644
index 0000000..3fe7992
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file4_Tangent_plane_at_extrema_and_saddle_point.gif
Binary files differ
diff --git a/FSF-2020/approximations-and-optimizations/Critical Points/types_of_cp.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file4_Tangent_plane_at_extrema_and_saddle_point.py
index f9055e6..d129213 100644
--- a/FSF-2020/approximations-and-optimizations/Critical Points/types_of_cp.py
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Tangent-Plane-Approximations/file4_Tangent_plane_at_extrema_and_saddle_point.py
@@ -1,12 +1,9 @@
-from manimlib.imports import *
+from manimlib.imports import*
-class TypescpAnimation(ThreeDScene):
+class TangenttoSurface(ThreeDScene):
def construct(self):
- axes = ThreeDAxes()
+ axes = ThreeDAxes()
- r_text = TextMobject("Relative Maximum at ORIGIN",color ='#87CEFA')
- f_text = TextMobject("$f(x,y) = -x^2-y^2$").to_corner(UL)
-
#----graph of first function f(x,y) = -x**2-y**2
f = ParametricSurface(
lambda u, v: np.array([
@@ -15,9 +12,7 @@ class TypescpAnimation(ThreeDScene):
-u**2-v**2
]),v_min = -1, v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [YELLOW_D, YELLOW_E],
resolution = (20, 20)).scale(1)
-
- r2_text = TextMobject("Saddle Point at ORIGIN",color ='#87CEFA')
- f2_text = TextMobject("$f(x,y) = -x^2+y^2$").to_corner(UL)
+ f_text = TextMobject("Tangent plane at relative maxima").to_corner(UL).scale(0.5)
#----graph of second function f(x,y) = -x**2+y**2
f2 = ParametricSurface(
@@ -27,9 +22,7 @@ class TypescpAnimation(ThreeDScene):
-u**2+v**2
]),v_min = -1, v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [RED_D, RED_E],
resolution = (20, 20)).scale(1)
-
- r3_text = TextMobject("Relative Minimum at ORIGIN",color ='#87CEFA')
- f3_text = TextMobject("$f(x,y) = x^2+y^2$").to_corner(UL)
+ f2_text = TextMobject("Tangent plane at saddle point").to_corner(UL).scale(0.5)
#----graph of third function f(x,y) = x**2+y**2
f3 = ParametricSurface(
@@ -39,32 +32,31 @@ class TypescpAnimation(ThreeDScene):
u**2+v**2
]),v_min = -1, v_max = 1, u_min = -1, u_max = 1, checkerboard_colors = [GREEN_D, GREEN_E],
resolution = (20, 20)).scale(1)
+ f3_text = TextMobject("Tangent plane at relative minima").to_corner(UL).scale(0.5)
self.set_camera_orientation(phi = 75 * DEGREES, theta = -45 * DEGREES )
- d = Dot(np.array([0,0,0]), color = '#800000') #---- critical point
+ d = Dot(np.array([0,0,0]), color = '#800000') #---- critical point
- self.add_fixed_in_frame_mobjects(r_text)
- self.wait(1)
- self.play(FadeOut(r_text))
+ r = Rectangle(height = 2,breadth = 1,color = PURPLE).scale(0.5)
+
+ self.begin_ambient_camera_rotation(rate = 0.3)
self.add(axes)
self.play(Write(f),Write(d))
+ self.wait(1)
self.add_fixed_in_frame_mobjects(f_text)
- self.wait(2)
- self.play(FadeOut(axes),FadeOut(f),FadeOut(f_text),FadeOut(d))
-
- self.add_fixed_in_frame_mobjects(r2_text)
+ self.play(ShowCreation(r))
+ self.wait(1)
+ self.play(FadeOut(r),FadeOut(f),FadeOut(d),FadeOut(f_text))
self.wait(1)
- self.play(FadeOut(r2_text))
- self.add(axes)
self.play(Write(f2),Write(d))
+ self.wait(1)
self.add_fixed_in_frame_mobjects(f2_text)
- self.wait(2)
- self.play(FadeOut(axes),FadeOut(f2),FadeOut(f2_text),FadeOut(d))
-
- self.add_fixed_in_frame_mobjects(r3_text)
+ self.play(ShowCreation(r))
+ self.wait(1)
+ self.play(FadeOut(r),FadeOut(f2),FadeOut(d),FadeOut(f2_text))
self.wait(1)
- self.play(FadeOut(r3_text))
- self.add(axes)
self.play(Write(f3),Write(d))
+ self.wait(1)
self.add_fixed_in_frame_mobjects(f3_text)
- self.wait(2)
+ self.play(ShowCreation(r))
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/README.md b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/README.md
new file mode 100644
index 0000000..96b32bf
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/README.md
@@ -0,0 +1,27 @@
+<h1><div align=”center”><b>SubTopic: The Second Derivative Test</b></h1></div>
+<br/></br>
+
+<tab>file1_Second_order_partial_derivatives
+
+![file1_Second_order_partial_derivatives](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file1_Second_order_partial_derivatives.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file2_Nondegenerate_Hessian_Matrix
+
+![file2_Nondegenerate_Hessian_Matrix](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file2_Nondegenerate_Hessian_Matrix.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file3_Degenerate_Hessian_Matrix
+
+![file3_Degenerate_Hessian_Matrix](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file3_Degenerate_Hessian_Matrix.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file4_Contour_Diagram
+
+![file4_Contour_Diagram](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file4_Contour_Diagram.gif?raw=true)
+<br/></br>
+<br/></br>
+
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file1_Second_order_partial_derivatives.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file1_Second_order_partial_derivatives.gif
new file mode 100644
index 0000000..3471e4d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file1_Second_order_partial_derivatives.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file1_Second_order_partial_derivatives.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file1_Second_order_partial_derivatives.py
new file mode 100644
index 0000000..84052cc
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file1_Second_order_partial_derivatives.py
@@ -0,0 +1,78 @@
+from manimlib.imports import*
+
+#---- graphs of second-order partial derivatives of a function
+class SurfacesAnimation(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes()
+ x_label = TextMobject('$x$').shift([5,0.5,0]) #---- x axis
+ y_label = TextMobject('$y$').shift([0.5,4,0]).rotate(-4.5) #---- y axis
+
+ #---- surface of function: f(x,y) = (x^2+y^2)^2
+ surface_f = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ ((u**2)+(v**2))**2
+ ]),v_min=-1,v_max=1,u_min=-1,u_max=1,checkerboard_colors=[GREEN_D, GREEN_E]).scale(1)
+
+ #---- surface of second-order partial derivative f_xx
+ surface_fxx = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ (3*u**2)+(v**2)
+ ]),v_min=-1,v_max=1,u_min=-1,u_max=1,checkerboard_colors=[YELLOW_D, YELLOW_E]).shift([0,0,0]).scale(0.6)
+
+ #---- surface of second-order partial derivative f_yy
+ surface_fyy = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ (u**2)+(3*v**2)
+ ]),v_min=-1,v_max=1,u_min=-1,u_max=1,checkerboard_colors=[PURPLE_D, PURPLE_E]).scale(0.6).shift([0,0,0])
+
+ #---- surface of second-order partial derivative f_xy = f_yx
+ surface_fxy = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ 8*u*v
+ ]),v_min=-1,v_max=1,u_min=-1,u_max=1,checkerboard_colors=[TEAL_D, TEAL_E]).scale(0.6)
+
+ f_text= TextMobject("$f(x,y) = (x^2+y^2)^2$",color = GREEN).scale(0.7).to_corner(UL)
+
+ fxx_text= TextMobject("$f_{xx} = 12x^2+4y^2$ (Concavity along x axis)",color = YELLOW).scale(0.5).to_corner(UL)
+
+ fyy_text= TextMobject("$f_{yy} = 4x^2+12y^2$(Concavity along y axis)",color = PURPLE).scale(0.5).to_corner(UL)
+
+ fxy_text= TextMobject("$f_{xy} = f_{yx} = 8xy$ (Twisting of the function)",color = TEAL).scale(0.5).to_corner(UL)
+
+
+ self.set_camera_orientation(phi = 40 * DEGREES, theta = 45 * DEGREES)
+ self.begin_ambient_camera_rotation(rate = 0.1)
+ self.add_fixed_in_frame_mobjects(f_text)
+ self.add(axes)
+ self.add(x_label)
+ self.add(y_label)
+ self.wait(1)
+ self.play(Write(surface_f))
+ self.wait(2)
+ self.play(FadeOut(f_text))
+
+
+ self.play(ReplacementTransform(surface_f,surface_fxx))
+
+ self.add_fixed_in_frame_mobjects(fxx_text)
+ self.wait(2)
+ self.play(FadeOut(fxx_text))
+
+ self.play(ReplacementTransform(surface_fxx,surface_fyy))
+ self.add_fixed_in_frame_mobjects(fyy_text)
+ self.wait(2)
+ self.play(FadeOut(fyy_text))
+
+ self.play(ReplacementTransform(surface_fyy,surface_fxy))
+ self.move_camera(phi = 35 * DEGREES, theta = 80 * DEGREES)
+ self.add_fixed_in_frame_mobjects(fxy_text)
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file2_Nondegenerate_Hessian_Matrix.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file2_Nondegenerate_Hessian_Matrix.gif
new file mode 100644
index 0000000..0d58b4f
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file2_Nondegenerate_Hessian_Matrix.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file2_Nondegenerate_Hessian_Matrix.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file2_Nondegenerate_Hessian_Matrix.py
new file mode 100644
index 0000000..32c1559
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file2_Nondegenerate_Hessian_Matrix.py
@@ -0,0 +1,158 @@
+from manimlib.imports import*
+import math as m
+
+class Minima(ThreeDScene):
+ def construct(self):
+
+ heading = TextMobject("Nondegenerate Hessian Matrix",color = BLUE)
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.3,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.3,5.5,0]).rotate(-4.5) #---- y axis
+
+ h_text = TextMobject("Case 1: $\\frac{\\partial^2 f}{\\partial x^2}>0$ and $\\frac{\\partial^2 f}{\\partial y^2}>0$").scale(1)
+
+ #---- determiniant of Hessian Matrix
+ hessian_surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ -0.5*m.exp(-u**2-v**2)
+ ]),u_min = -PI, u_max = PI, v_min = -PI, v_max =PI).set_color(TEAL).shift([0,0,0]).scale(1).fade(0.2)
+
+ det_text= TextMobject("$det \\hspace{1mm} H = (\\frac{\\partial^2 f}{\\partial x^2})(\\frac{\\partial^2 f}{\\partial y^2})-(\\frac{\\partial^2 f}{\\partial x \\partial y})^2 $").to_corner(UL).scale(0.7)
+
+ #---- function f(x,y)
+ f_surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ u**2+v**2
+ ]),u_min = -1.3, u_max = 1.3, v_min = -1.3, v_max = 1.3).set_color(TEAL).shift([0,0,-0.5])
+
+ f_text= TextMobject("surface of the function").to_corner(UL).scale(0.8)
+
+ d = Dot(color = "#800000").shift([0,0,-0.52]) #---- critical point
+
+ self.set_camera_orientation(phi = 75*DEGREES, theta = 40*DEGREES)
+ self.add_fixed_in_frame_mobjects(heading)
+ self.wait(1)
+ self.play(FadeOut(heading))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(h_text)
+ self.wait(1)
+ self.play(FadeOut(h_text))
+ self.wait(1)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.play(Write(hessian_surface))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(det_text)
+ self.move_camera(phi = 90*DEGREES, theta= 60*DEGREES)
+ self.play(Write(d))
+ self.wait(1)
+ self.play(FadeOut(det_text),ReplacementTransform(hessian_surface,f_surface))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(f_text)
+ self.wait(1)
+ self.play(FadeOut(f_text),FadeOut(f_surface),FadeOut(axes),FadeOut(label_x),FadeOut(label_y),FadeOut(d))
+
+class Maxima(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.3,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.3,5.5,0]).rotate(-4.5) #---- y axis
+
+ h_text = TextMobject("Case 2: $\\frac{\\partial^2 f}{\\partial x^2}<0$ and $\\frac{\\partial^2 f}{\\partial y^2}<0$").scale(1)
+
+ #---- determiniant of Hessian Matrix
+ hessian_surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ 0.5*m.exp(-u**2-v**2)
+ ]),u_min = -PI, u_max = PI, v_min = -PI, v_max =PI).set_color(TEAL).shift([0,0,0]).scale(1).fade(0.2)
+
+ det_text= TextMobject("$det \\hspace{1mm} H = (\\frac{\\partial^2 f}{\\partial x^2})(\\frac{\\partial^2 f}{\\partial y^2})-(\\frac{\\partial^2 f}{\\partial x \\partial y})^2 $").to_corner(UL).scale(0.7)
+
+ #---- function g(x,y)
+ g_surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ -u**2-v**2
+ ]),u_min = -1.3, u_max = 1.3, v_min = -1.3, v_max = 1.3).set_color(TEAL).shift([0,0,0.5])
+
+ g_text= TextMobject("surface of the function").to_corner(UL).scale(0.8)
+
+ d = Dot(color = "#800000").shift([0,0,0.5]) #---- critical point
+
+ self.set_camera_orientation(phi = 75*DEGREES, theta = 40*DEGREES)
+ self.add_fixed_in_frame_mobjects(h_text)
+ self.wait(1)
+ self.play(FadeOut(h_text))
+ self.wait(1)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.play(Write(hessian_surface))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(det_text)
+ self.play(Write(d))
+ self.wait(1)
+ self.play(FadeOut(det_text),ReplacementTransform(hessian_surface,g_surface))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(g_text)
+ self.wait(1)
+ self.play(FadeOut(g_text),FadeOut(g_surface),FadeOut(axes),FadeOut(label_x),FadeOut(label_y),FadeOut(d))
+
+class SaddlePoint(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.3,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.3,5.5,0]).rotate(-4.5) #---- y axis
+
+ h_text = TextMobject("Case 3: $\\frac{\\partial^2 f}{\\partial x^2}$ and $\\frac{\\partial^2 f}{\\partial y^2}$ have opposite signs").scale(1)
+
+ #---- determiniant of Hessian Matrix
+ hessian_surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ m.exp(0.5*u**2-0.5*v**2)
+ ]),u_min = -1.2, u_max = 1.2, v_min = -2.5, v_max = 2.5).set_color(TEAL).shift([0,0,-1]).scale(1).fade(0.2)
+
+ det_text= TextMobject("$det \\hspace{1mm} H = (\\frac{\\partial^2 f}{\\partial x^2})(\\frac{\\partial^2 f}{\\partial y^2})-(\\frac{\\partial^2 f}{\\partial x \\partial y})^2 $").to_corner(UL).scale(0.7)
+
+ #---- function p(x,y)
+ p_surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ u**2-v**2
+ ]),u_min = -1, u_max = 1, v_min = -1, v_max =1).set_color(TEAL).shift([0,0,0]).scale(2)
+
+ p_text= TextMobject("surface of the function").to_corner(UL).scale(0.8)
+
+ d = Dot(color = "#800000").shift([0,0,0]) #---- critical point
+
+ self.set_camera_orientation(phi = 80*DEGREES, theta = 60*DEGREES)
+ self.add_fixed_in_frame_mobjects(h_text)
+ self.wait(1)
+ self.play(FadeOut(h_text))
+ self.wait(1)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.wait(1)
+ self.play(Write(hessian_surface))
+ self.play(Write(d))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(det_text)
+ self.wait(2)
+ self.play(FadeOut(det_text),ReplacementTransform(hessian_surface,p_surface))
+ self.add_fixed_in_frame_mobjects(p_text)
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file3_Degenerate_Hessian_Matrix.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file3_Degenerate_Hessian_Matrix.gif
new file mode 100644
index 0000000..5aae300
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file3_Degenerate_Hessian_Matrix.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file3_Degenerate_Hessian_Matrix.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file3_Degenerate_Hessian_Matrix.py
new file mode 100644
index 0000000..9310553
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file3_Degenerate_Hessian_Matrix.py
@@ -0,0 +1,45 @@
+from manimlib.imports import*
+import math as m
+
+class DegenerateHessian(ThreeDScene):
+ def construct(self):
+
+ heading = TextMobject("Degenerate Hessian Matrix",color = BLUE)
+
+ h_text = TextMobject("For $det \\hspace{1mm} H = 0$, the surface of the function at the critical point would be flat.").scale(0.7)
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.3,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.3,5.5,0]).rotate(-4.5) #---- y axis
+
+ #---- function f(x,y)
+ f_surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ -u**4-v**4
+ ]),u_min = -0.8, u_max = 0.8, v_min = -0.8, v_max = 0.8).set_color(TEAL).shift([0,0,-0.5]).scale(2)
+
+ f_text= TextMobject("surface of the function").to_corner(UL).scale(0.5)
+
+ d = Dot(color = "#800000").shift([0,0,-0.5]) #---- critical point
+ plane = Square(color = YELLOW,fill_opacity= 0.2).shift([0,0,-0.5]).scale(1.3)
+
+ self.set_camera_orientation(phi = 70*DEGREES, theta = 45*DEGREES)
+ self.add_fixed_in_frame_mobjects(heading)
+ self.wait(1)
+ self.play(FadeOut(heading))
+ self.add_fixed_in_frame_mobjects(h_text)
+ self.wait(2)
+ self.play(FadeOut(h_text))
+ self.wait(1)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.play(Write(f_surface))
+ self.add_fixed_in_frame_mobjects(f_text)
+ self.wait(1)
+ self.play(Write(d))
+ self.wait(1)
+ self.play(Write(plane))
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file4_Contour_Diagram.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file4_Contour_Diagram.gif
new file mode 100644
index 0000000..41068e2
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file4_Contour_Diagram.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file4_Contour_Diagram.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file4_Contour_Diagram.py
new file mode 100644
index 0000000..d3084e2
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/The-Second-Derivative-Test/file4_Contour_Diagram.py
@@ -0,0 +1,120 @@
+from manimlib.imports import*
+
+#---- contour diagram animation
+class ContourDiagram(ThreeDScene):
+ def construct(self):
+
+ heading = TextMobject("CONTOUR DIAGRAM", color = YELLOW).scale(1)
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.5,0]) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.5,5.5,0]).rotate(-4.5) #---- y axis
+
+ #---- surface of a paraboloid
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ np.cos(v)*u,
+ np.sin(v)*u,
+ u**2
+ ]),v_min = -2, v_max = 2, u_min = -2, u_max = 2, checkerboard_colors = [GREEN_B,GREEN_C,GREEN_D,GREEN_E]).shift([0,0,0]).scale(0.5)
+
+ #---- first contour projection
+ contour1 = ParametricSurface(
+ lambda u, v: np.array([
+ np.cos(TAU * v),
+ np.sin(TAU * v),
+ 2*(1 - 2.5*u)
+ ])).fade(0.5).scale(0.21).shift([0,0,1.01])
+
+ #---- first contour line
+ c_1 = Circle(color = BLUE).scale(0.21).shift([0,0,0]).rotate(0.1,DOWN)
+
+ #-------------------------------------------------
+
+ #---- second contour projection
+ contour2 = ParametricSurface(
+ lambda u, v: np.array([
+ np.cos(TAU * v),
+ np.sin(TAU * v),
+ 2*(1 - 1.6*u)
+ ])).fade(0.5).scale(0.41).shift([0,0,0.3]).set_color(RED)
+
+ #---- second contour line
+ c_2 = Circle(color = RED).scale(0.41).shift([0,0,0]).rotate(0.1,DOWN)
+
+ #-------------------------------------------------
+
+ #---- third contour projection
+ contour3 = ParametricSurface(
+ lambda u, v: np.array([
+ np.cos(TAU * v),
+ np.sin(TAU * v),
+ 2*(1 - 1.5*u)
+ ])).fade(0.5).scale(0.61).shift([0,0,0.4]).set_color(YELLOW)
+
+ #---- third contour line
+ c_3 = Circle(color = YELLOW).scale(0.61).shift([0,0,0])
+
+ #-------------------------------------------------
+
+ #---- fourth contour projection
+ contour4 = ParametricSurface(
+ lambda u, v: np.array([
+ np.cos(TAU * v),
+ np.sin(TAU * v),
+ 2*(1 - 1.5*u)
+ ])).fade(0.7).scale(0.81).shift([0,0,0.7]).set_color(PINK)
+
+ #---- fourth contour line
+ c_4 = Circle(color = PINK).scale(0.81).shift([0,0,0])
+
+ #-------------------------------------------------
+
+ #---- fifth contour projection
+ contour5 = ParametricSurface(
+ lambda u, v: np.array([
+ np.cos(TAU * v),
+ np.sin(TAU * v),
+ 2*(1 - 1.5*u)
+ ])).fade(0.7).scale(1.01).shift([0,0,1]).set_color(PURPLE)
+
+ #---- fifth contour line
+ c_5 = Circle(color = PURPLE).scale(1.01).shift([0,0,0])
+
+ c_text= TextMobject("Contour Lines").scale(0.5).shift(2*DOWN)
+ s = Square().scale(1.3)
+
+ self.set_camera_orientation(phi = 75 * DEGREES, theta = 10 * DEGREES)
+ self.add_fixed_in_frame_mobjects(heading)
+ self.wait(1)
+ self.play(FadeOut(heading))
+ self.wait(1)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.play(Write(surface))
+ self.wait(1)
+ self.add(contour1)
+ self.wait(1)
+ self.play(Write(c_1))
+ self.play(ReplacementTransform(contour1,contour2))
+ self.wait(1)
+ self.play(Write(c_2))
+ self.play(ReplacementTransform(contour2,contour3))
+ self.wait(1)
+ self.play(Write(c_3))
+ self.play(ReplacementTransform(contour3,contour4))
+ self.wait(1)
+ self.play(Write(c_4))
+ self.play(ReplacementTransform(contour4,contour5))
+ self.wait(1)
+ self.play(Write(c_5))
+ self.wait(1)
+ self.play(FadeOut(contour5),FadeOut(axes),FadeOut(label_x),FadeOut(label_y),FadeOut(surface),FadeOut(contour5),FadeOut(contour4),FadeOut(contour3),FadeOut(contour2),FadeOut(contour1))
+ self.wait(1)
+ self.move_camera(phi=0 * DEGREES,theta= 90*DEGREES)
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(c_text)
+ self.wait(1)
+ self.play(ShowCreation(s),FadeOut(c_text))
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/README.md b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/README.md
new file mode 100644
index 0000000..ce4da11
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/README.md
@@ -0,0 +1,34 @@
+<h1><div align=”center”><b>SubTopic: Total Differential</b></h1></div>
+<br/></br>
+
+<tab>file1_Visualization_of_dz
+
+![file1_Visualization_of_dz](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file1_Visualization_of_dz.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file2_Differentials
+
+![file2_Differentials](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file2_Differentials.gif?raw=true)
+
+<br/></br>
+<br/></br>
+
+<tab>file3_Total_differential_of_z
+
+![file3_Total_differential_of_z](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file3_Total_differential_of_z.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file4_total_differential_change
+
+![file4_total_differential_change](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file4_total_differential_change.gif?raw=true)
+<br/></br>
+<br/></br>
+
+<tab>file5_Total_differential_approximation
+
+ ![file5_Total_differential_approximation](https://github.com/vnb09/FSF-mathematics-python-code-archive/blob/fsf_tasks/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file5_Total_differential_approximation.gif?raw=true)
+
+<br/></br>
+<br/></br>
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file1_Visualization_of_dz.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file1_Visualization_of_dz.gif
new file mode 100644
index 0000000..2e148af
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file1_Visualization_of_dz.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file1_Visualization_of_dz.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file1_Visualization_of_dz.py
new file mode 100644
index 0000000..1fdd0b9
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file1_Visualization_of_dz.py
@@ -0,0 +1,59 @@
+from manimlib.imports import*
+
+#---- visualization of total differential dz between two points lying on the surface of the function
+class differentialdz(ThreeDScene):
+
+ def construct(self):
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.5,0]).fade(0.4) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.5,5.5,0]).rotate(-4.5).fade(0.4) #---- y axis
+
+ #---- surface of the funtion f(x,y)
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ u**2+v**2
+ ]),u_min=-1,u_max=1, v_min=-1,v_max=1).set_color("#FF69B4").fade(0.6).scale(2).shift(3*UP+1*LEFT)
+
+ d = Dot([1.4,1.75,1],color = '#00FFFF').rotate(1.571,UP) #---- point on the surface
+ d2 = Dot([2,2,1],color = '#00FFFF').rotate(1.571,UP) #---- point on the surface
+
+ p1 = TextMobject("$P_1$",color ='#ADFF2F').scale(0.6).shift(2*RIGHT+1*UP)
+ p2 = TextMobject("$P_2$",color = '#ADFF2F').scale(0.6).shift(2.6*RIGHT+0.9*UP)
+
+ l = DashedLine(color = '#800000').rotate(1.571,UP).scale(1).shift(1.7*UP+1.6*RIGHT)
+ l2 = DashedLine(color = '#800000').rotate(1.571,UP).scale(0.8).shift(2.26*UP+1.2*RIGHT)
+
+ l_text = TextMobject("$(x_1,y_1)$",color = '#ADFF2F').scale(0.6).shift(2*RIGHT+1.6*DOWN)
+ l2_text = TextMobject("$(x_2,y_2)$",color = '#ADFF2F').scale(0.6).shift(2.7*RIGHT+1.2*DOWN)
+
+ a = Arrow(color = '#FFFACD').scale(0.7).rotate(1.38,RIGHT).shift(2.5*LEFT+3.1*UP)
+
+ a_text = TextMobject("$dz$",color='#800000').scale(0.5).shift(2.3*RIGHT+0.5*UP)
+
+ plane = Rectangle(color = '#E6E6FA',fill_opacity = 1).scale(3).shift(1*RIGHT+3*UP).fade(0.9)
+
+ label = TextMobject("$z = f(x,y)$").scale(0.6).shift(3.5*RIGHT+1.8*UP)
+
+ self.set_camera_orientation(phi=75*DEGREES,theta=-10*DEGREES)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.wait(1)
+ self.play(Write(plane))
+ self.play(Write(surface))
+ self.add_fixed_in_frame_mobjects(label)
+ self.wait(1)
+ self.play(ShowCreation(l),ShowCreation(l2),Write(d),Write(d2))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(p1)
+ self.add_fixed_in_frame_mobjects(p2)
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(l_text)
+ self.add_fixed_in_frame_mobjects(l2_text)
+ self.play(ShowCreation(a))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(a_text)
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file2_Differentials.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file2_Differentials.gif
new file mode 100644
index 0000000..6baf271
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file2_Differentials.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file2_Differentials.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file2_Differentials.py
new file mode 100644
index 0000000..1025210
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file2_Differentials.py
@@ -0,0 +1,77 @@
+from manimlib.imports import*
+
+#---- visualization of the differentials along the axes
+class differentials(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.3,0]).fade(0.4) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.5,5.5,0]).rotate(-4.5).fade(0.4) #---- y axis
+
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ u**2+v**2
+ ]),u_min=-1,u_max=1, v_min=-1,v_max=1).set_color("#FF69B4").shift([0,2.5,0.3]).scale(1.2) #----surface z = f(x,y)
+
+
+
+ plane = Rectangle(color = '#E6E6FA',fill_opacity = 1).scale(3).shift(-1*RIGHT+3*UP).fade(0.9)
+
+ d = Dot([1,2,1],color = '#9400D3').rotate(1.571,UP)
+ d2 = Dot([2,2.9,1],color = '#9400D3').rotate(1.571,UP)
+
+ p1 = TextMobject("$P_1$",color ='#ADFF2F').scale(0.6).shift(2*RIGHT+1*UP)
+ p2 = TextMobject("$P_2$",color = '#ADFF2F').scale(0.6).shift(2.6*RIGHT+0.4*UP)
+
+
+ l1 = DashedLine(color = '#00BFFF').scale(1.6).shift(3.5*UP+3.25*LEFT).rotate(1.571)
+ l2 = DashedLine(color = '#00BFFF').scale(1).shift(4*UP+2*LEFT).rotate(1.571)
+
+ label_dz= TextMobject("$dz$").scale(0.4).shift(5.3*RIGHT+0.4*UP)
+
+
+ l3 = Line(color = '#FFDAB9').scale(0.8).shift(1.95*UP+0.7*RIGHT).rotate(1.571,DOWN).fade(0.2)
+ l4 = Line(color = '#FFDAB9').scale(0.6).shift(2.86*UP+0.9*RIGHT).rotate(1.571,DOWN).fade(0.2)
+
+ line_y1 = DashedLine(color = '#00BFFF').scale(1.3).shift(0.82*UP+3.25*RIGHT).rotate(1.571)
+ line_y2 = DashedLine(color = '#00BFFF').scale(1.7).shift(1.2*UP+2.8*RIGHT).rotate(1.571)
+
+ label_dy= TextMobject("$dy$").scale(0.6).shift(3*RIGHT+0.8*DOWN).rotate(math.radians(90))
+
+ line_x1 = DashedLine(color = '#00BFFF').scale(1.5).shift(2.2*UP+1.6*RIGHT).rotate(1.571,RIGHT)
+ line_x2 = DashedLine(color = '#00BFFF').scale(1.2).shift(2.9*UP+1.6*RIGHT).rotate(1.571,RIGHT)
+
+ label_dx= TextMobject("$dx$").scale(0.4).shift(-0.4*UP+2.5*RIGHT)
+
+ label = TextMobject("$f(x,y)$").scale(0.6).shift(4*RIGHT+3*UP)
+
+
+ self.set_camera_orientation(phi=75*DEGREES,theta=10*DEGREES)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.play(Write(plane))
+ self.play(Write(surface))
+ self.add_fixed_in_frame_mobjects(label)
+ self.wait(1)
+ self.play(Write(d),Write(d2))
+ self.add_fixed_in_frame_mobjects(p1)
+ self.add_fixed_in_frame_mobjects(p2)
+ self.wait(1)
+ self.play(Write(l1))
+ self.play(Write(l2))
+ self.add_fixed_in_frame_mobjects(label_dz)
+ self.wait(1)
+ self.play(Write(l3))
+ self.play(Write(l4))
+ self.wait(1)
+ self.play(Write(line_y1))
+ self.play(Write(line_y2))
+ self.play(ShowCreation(label_dy))
+ self.wait(1)
+ self.play(Write(line_x1))
+ self.play(Write(line_x2))
+ self.add_fixed_in_frame_mobjects(label_dx)
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file3_Total_differential_of_z.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file3_Total_differential_of_z.gif
new file mode 100644
index 0000000..a54d2da
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file3_Total_differential_of_z.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file3_Total_differential_of_z.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file3_Total_differential_of_z.py
new file mode 100644
index 0000000..b8d6f96
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file3_Total_differential_of_z.py
@@ -0,0 +1,100 @@
+from manimlib.imports import*
+
+#---- visualization of total differential definition
+class totaldifferential(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes().fade(0.5)
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ u**2+v**2
+ ]),u_min=-1,u_max=1, v_min=-1,v_max=1).set_color("#FF69B4").fade(0.6).shift([1,0.8,1.5]).scale(2)
+
+ plane = Rectangle(color = '#E6E6FA',fill_opacity = 1).scale(3).shift(-1*RIGHT+3*UP).fade(0.9)
+ label_x = TextMobject("$x$").shift(5*RIGHT+0.4*DOWN).rotate(1.571)
+ label_y = TextMobject("$y$").shift(0.3*DOWN+5.6*RIGHT).scale(0.5)
+ label_z = TextMobject("$z$").shift(3.5*UP+0.2*LEFT).scale(0.5)
+
+ s1 = Square(color = '#00FF00',fill_opacity=0.4).shift([1,1,0])
+ s2 = Square(color = '#00FF00',fill_opacity=0.4).shift([1,1,3]).scale(0.95)
+
+ l1 = Line([2,0,3],[2,0,0],color = '#FFFACD')
+ l2 = Line([0,2,3],[0,2,0],color = '#FFFACD')
+ l3 = Line([2,1.95,3],[2,2,0],color = '#FFFACD')
+
+ d1 = Dot([2,0,1.5],color = '#FFD700').rotate(1.571,UP)
+ d1_text = TextMobject("$P1$").scale(0.4).shift(1.2*LEFT+1.1*UP)
+
+ d2 = Dot([0,2,3],color = '#FFD700').rotate(1.571,UP)
+ d2_text = TextMobject("$P2$").scale(0.4).shift(2.3*RIGHT+3.1*UP)
+
+ d3 = Dot([2,2,2],color = '#FFD700').rotate(1.571,UP)
+ d3_text = TextMobject("$Q$").scale(0.4).shift([1.6,-1,0]+2.5*UP)
+
+ s3 = Square().shift([1,1,1.5]).scale(0.95)
+ s4 = Square().shift([1,1,2]).scale(0.95)
+
+ m1_line = DashedLine([2,0,1.5],[2,2,2],color = '#87CEEB')
+ m2_line = DashedLine([2,2,2],[0,2,3],color = '#87CEEB')
+
+ dx_line = Line([2,2,0],[4,2,0],color = '#00FF7F')
+ dy_line = Line([2,2,0],[2,4,0],color = '#00FF7F')
+
+ dx = DashedLine([3.5,0,0],[3.5,2,0],color = '#87CEEB')
+ dy = DashedLine([0,3.5,0],[2,3.5,0],color = '#87CEEB')
+
+ dx_text = TextMobject("$dx$").scale(0.8).shift([4,1,0]).rotate(1.571)
+ dy_text = TextMobject("$dy$").scale(0.8).shift([1,3.8,0]).rotate(math.radians(180))
+
+ parx_line = Line([0,2,1.5],[0,5,1.5],color = '#00FF7F')
+ parm_line = Line([0,2,2],[0,5,2],color = '#00FF7F')
+ pary_line = Line([0,2.1,3],[0,5,3],color = '#00FF7F')
+
+ delx = DashedLine([0,4,2],[0,4,1.5],color = '#F0F8FF')
+ dely = DashedLine([0,4,3],[0,4,2],color = '#FAEBD7')
+
+ dely_text = TextMobject("$\\frac{\\partial z}{\\partial y}dy$").shift(4.6*RIGHT+2.3*UP).scale(0.4)
+ delx_text = TextMobject("$\\frac{\\partial z}{\\partial x}dx$").shift(4.6*RIGHT+1.4*UP).scale(0.4)
+
+
+ self.set_camera_orientation(phi=75*DEGREES,theta=20*DEGREES)
+ self.add(axes)
+ self.play(Write(plane))
+ self.play(ShowCreation(label_x))
+ self.add_fixed_in_frame_mobjects(label_y)
+ self.add_fixed_in_frame_mobjects(label_z)
+ self.wait(1)
+ self.play(Write(surface))
+ self.play(ShowCreation(d1))
+ self.add_fixed_in_frame_mobjects(d1_text)
+ self.play(ShowCreation(d2))
+ self.add_fixed_in_frame_mobjects(d2_text)
+ self.wait(1)
+ self.play(Write(s2))
+ self.wait(1)
+ self.play(Write(l1),Write(l2),Write(l3))
+ self.wait(1)
+ self.play(Write(s1))
+ self.wait(1)
+ self.play(FadeOut(surface))
+ self.play(ShowCreation(d3))
+ self.add_fixed_in_frame_mobjects(d3_text)
+ self.play(ShowCreation(m1_line))
+ self.play(ShowCreation(m2_line))
+ self.wait(1)
+ self.play(ShowCreation(dx_line),ShowCreation(dx),ShowCreation(dx_text))
+ self.wait(1)
+ self.play(ShowCreation(dy_line),ShowCreation(dy),ShowCreation(dy_text))
+ self.wait(2)
+ self.play(Write(s3))
+ self.play(Write(s4))
+ self.wait(1)
+ self.play(ShowCreation(parx_line),ShowCreation(parm_line),ShowCreation(pary_line))
+ self.wait(1)
+ self.play(ShowCreation(dely))
+ self.add_fixed_in_frame_mobjects(dely_text)
+ self.wait(1)
+ self.play(ShowCreation(delx))
+ self.add_fixed_in_frame_mobjects(delx_text)
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file4_total_differential_change.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file4_total_differential_change.gif
new file mode 100644
index 0000000..f2227a8
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file4_total_differential_change.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file4_total_differential_change.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file4_total_differential_change.py
new file mode 100644
index 0000000..78e41a2
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file4_total_differential_change.py
@@ -0,0 +1,54 @@
+from manimlib.imports import*
+
+
+class firstScene(ThreeDScene):
+
+ def construct(self):
+
+ axes = ThreeDAxes()
+
+ s = Rectangle(color = '#F08080',fill_opacity=1).fade(0.7).shift(1.9*UP+5*LEFT).scale(0.9)#----surface z = f(x,y)
+
+ s2= Rectangle(color = '#F08080',fill_opacity=1).fade(0.7).shift(2.4*UP+3.1*RIGHT).scale(0.6) #----reflection of the surface on the x-y plane
+
+ l1 = DashedLine(color = '#AFEEEE').rotate(1.571,UP).scale(1).shift(1.53*UP+1.5*RIGHT)
+ l2 = DashedLine(color = '#AFEEEE').rotate(1.571,UP).scale(1).shift(2.9*UP+1.4*RIGHT)
+ l3 = DashedLine(color = '#AFEEEE').rotate(1.571,UP).scale(1).shift(1.5*UP-1.6*RIGHT)
+ l4 = DashedLine(color = '#AFEEEE').rotate(1.571,UP).scale(1).shift(2.9*UP-1.75*RIGHT)
+
+
+ l1_text = TextMobject("$(x+\\triangle x,y)$").shift(RIGHT+1.7*DOWN).scale(0.4)
+ l2_text = TextMobject("$(x+\\triangle x,y+\\triangle y)$").shift(3*RIGHT+1.8*DOWN).scale(0.4)
+ l3_text = TextMobject("$f(x,y)$").shift(1.6*RIGHT+1.5*UP).scale(0.4)
+ l4_text = TextMobject("$(x,y+\\triangle y)$").shift(3.5*RIGHT+0.7*DOWN).scale(0.4)
+
+ label_x = TextMobject("$x$").shift(5*RIGHT+0.4*DOWN)
+ label_y = TextMobject("$y$").shift(5*UP-0.6*RIGHT)
+
+ self.add(axes)
+ self.set_camera_orientation(phi=75*DEGREES,theta=10*DEGREES)
+ self.wait(1)
+ self.play(ShowCreation(label_x),ShowCreation(label_y))
+ self.play(Write(s))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(l3_text)
+ self.wait(1)
+ self.play(Write(l3))
+ self.wait(1)
+ self.play(Write(l1))
+ self.add_fixed_in_frame_mobjects(l1_text)
+ self.wait(1)
+ self.play(Write(l2))
+ self.add_fixed_in_frame_mobjects(l2_text)
+ self.wait(1)
+ self.play(Write(l4))
+ self.add_fixed_in_frame_mobjects(l4_text)
+ self.wait(1)
+ self.play(Write(s2))
+ self.wait(1)
+
+
+
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file5_Total_differential_approximation.gif b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file5_Total_differential_approximation.gif
new file mode 100644
index 0000000..ebbf240
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file5_Total_differential_approximation.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file5_Total_differential_approximation.py b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file5_Total_differential_approximation.py
new file mode 100644
index 0000000..e7b39bb
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/approximations-and-optimizations/Total-Differential/file5_Total_differential_approximation.py
@@ -0,0 +1,52 @@
+from manimlib.imports import*
+
+#---- approximation value of function between two points using total differentials
+class approximation(ThreeDScene):
+
+ def construct(self):
+
+ axes = ThreeDAxes()
+ label_x = TextMobject("$x$").shift([5.5,-0.3,0]).fade(0.4) #---- x axis
+ label_y = TextMobject("$y$").shift([-0.5,5.5,0]).rotate(-4.5).fade(0.4) #---- y axis
+
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ np.sin(u),
+ v,
+ -u**2-v
+ ]),u_min=-1,u_max=1, v_min=-1,v_max=1).set_color("#00008B").scale(2).shift(3.8*UP+2*LEFT)
+
+ d = Dot([1.4,1.75,1],color = '#00FFFF').rotate(1.571,UP)
+ d2 = Dot([2,2,1],color = '#00FFFF').rotate(1.571,UP)
+
+ l = DashedLine(color = '#800000').rotate(1.571,UP).scale(1).shift(1.7*UP+1.6*RIGHT)
+ l2 = DashedLine(color = '#800000').rotate(1.571,UP).scale(0.8).shift(2.26*UP+1.2*RIGHT)
+
+ l_text = TextMobject("$(x_1,y_1)$",color = '#ADFF2F').scale(0.6).shift(2*RIGHT+1.6*DOWN)
+ l2_text = TextMobject("$(x_2,y_2)$",color = '#ADFF2F').scale(0.6).shift(2.7*RIGHT+1.2*DOWN)
+
+ plane = Rectangle(color = '#E6E6FA',fill_opacity = 1).scale(3).shift(1*RIGHT+3*UP).fade(0.9)
+
+ tangentplane = Rectangle(color = '#E6E6FA',fill_opacity = 1).scale(1.1).shift(2*LEFT+3.4*UP).fade(0.5).rotate(0.8,RIGHT)
+ tangentplane_text = TextMobject("Tangent Plane").scale(0.4).shift(3*RIGHT+1*UP)
+
+ label = TextMobject("$z = f(x,y)$").scale(0.6).shift(4*RIGHT+3*UP)
+
+ self.set_camera_orientation(phi=75*DEGREES,theta=-10*DEGREES)
+ self.add(axes)
+ self.add(label_x)
+ self.add(label_y)
+ self.wait(1)
+ self.play(Write(plane))
+ self.wait(1)
+ self.play(Write(surface))
+ self.add_fixed_in_frame_mobjects(label)
+ self.wait(1.5)
+ self.play(ShowCreation(l),ShowCreation(l2),Write(d),Write(d2))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(l_text)
+ self.add_fixed_in_frame_mobjects(l2_text)
+ self.wait(1)
+ self.play(Write(tangentplane))
+ self.add_fixed_in_frame_mobjects(tangentplane_text)
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file1_paths-3d.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file1_paths-3d.gif
new file mode 100644
index 0000000..56c58b1
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file1_paths-3d.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file1_paths-3d.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file1_paths-3d.py
new file mode 100644
index 0000000..28b2bd4
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file1_paths-3d.py
@@ -0,0 +1,41 @@
+from manimlib.imports import *
+import numpy as np
+
+class routes(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes()
+ self.begin_ambient_camera_rotation(rate=0.08)
+ self.set_camera_orientation(phi=45 * DEGREES,theta=-65*DEGREES, distance = 45)
+ function = ParametricFunction(
+ lambda t: np.array([
+ 1.5*np.cos(t),
+ 1.5*np.sin(t),
+ t/4
+ ]), t_min = 0, t_max =3*PI).set_color("#0EB1D2")
+
+
+ line = Line(np.array([1.5, 0, 0]), np.array([-1.5, 0, 2.35619])).set_color("#F8F32B")
+
+ dot1 = Sphere(radius = 0.1).move_to(np.array([1.5,0,0])).set_color("#74226C")
+ dot2 = Sphere(radius = 0.1).move_to(np.array([1.5,0,0])).set_color("#74226C")
+
+ label1 = TexMobject(r"A").move_to(np.array([1.5,0,0])).set_color("#FCF7F8")
+ label2 = TexMobject(r"B").move_to(np.array([-1.5,0,2.42])).set_color("#FCF7F8")
+
+ title = TexMobject(r"\textit{Work done}",r"\textit{ against gravity is the}", r"\textit{ same for both paths}").set_color("#F1E3F3").move_to(np.array([0,-3,0]))
+ title[1].set_color("#F8F32B")
+
+ self.add(axes)
+ self.wait()
+ self.play(ShowCreation(function), ShowCreation(line), run_time = 2)
+ self.wait()
+ self.play(MoveAlongPath(dot1, function), run_time = 2)
+ self.wait()
+ self.play(MoveAlongPath(dot2, line), run_time = 1.2)
+ self.wait()
+ self.add_fixed_in_frame_mobjects(title)
+ self.play(Write(title))
+ self.wait()
+
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file2_line-int.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file2_line-int.gif
new file mode 100644
index 0000000..22d0509
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file2_line-int.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file2_line-int.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file2_line-int.py
new file mode 100644
index 0000000..704acf7
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file2_line-int.py
@@ -0,0 +1,132 @@
+from manimlib.imports import *
+
+def field_func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -x,
+ -y,
+ 0
+ ])
+
+
+class LineIntegral(MovingCameraScene, Scene):
+ def setup(self):
+ MovingCameraScene.setup(self)
+ Scene.setup(self)
+
+ def get_pending(self,path,proportion,dx=0.01):
+ if proportion < 1:
+ coord_i = path.point_from_proportion(proportion)
+ coord_f = path.point_from_proportion(proportion+dx)
+ else:
+ coord_i = path.point_from_proportion(proportion-dx)
+ coord_f = path.point_from_proportion(proportion)
+ line = Line(coord_i,coord_f)
+ angle = line.get_angle()
+ return angle
+
+ def construct(self):
+
+
+ # all the text
+ vec_f = TexMobject(r"\vec F",r" \textit{ is a vector field defined on the plane}").set_color("#EDF2EF")
+ c = TexMobject(r"C",r" \textit{ is a curve on the plane, oriented counter-clockwise.}").set_color("#EDF2EF")
+ dr = TexMobject(r"\vec dr", r"\textit{ gives the direction as we move along C}").set_color("#EDF2EF")
+
+ intg = TexMobject(r"\oint \vec F \cdot \vec dr", r"\textit{ gives the rotation along the curve}").shift(2.5*DOWN).scale(0.7).set_color("#EDF2EF")
+ text = VGroup(vec_f, c, dr).scale(0.6).set_stroke(width = 1.5)
+ text.arrange(DOWN, buff = 0.2)
+ text.shift(3.2*DOWN)
+
+ vec_f[0].set_color("#D1D646")
+ dr[0].set_color("#D1D646")
+ intg[0].set_color("#D1D646")
+
+
+
+
+ self.camera_frame.save_state()
+ vec_f_sym = TexMobject(r"\vec F")
+ c_sym = TexMobject(r"C").move_to(4.8*RIGHT+1.3*UP)
+ dr_sym = TexMobject(r"\vec dr").next_to(vec_f_sym, DOWN, buff = SMALL_BUFF)
+ dp_sym = TexMobject(r"\vec F \cdot \vec dr")
+ intg_sym = TexMobject(r"\oint \vec F \cdot \vec dr")
+
+ symbols = VGroup(vec_f_sym, dr_sym, dp_sym, intg_sym).shift(3*UP).set_color("#D1D646")
+
+
+
+
+ vector_field = VectorField(field_func, x_min = -15, x_max = 15, y_min = -15, y_max = 15).fade(0.5)
+ boundary = Ellipse(width = 9, height = 3).set_color("#32908F")
+ b2 = Ellipse(width = 9, height = 3).set_color(WHITE)
+
+ start_angle = self.get_pending(boundary, 0)
+
+ pointer = Triangle(fill_opacity = 1).set_height(0.25).set_color(WHITE)
+ pointer.set_fill(WHITE)
+ pointer.move_to(boundary.get_start())
+ pointer.rotate(- PI / 2)
+ pointer.save_state()
+ pointer.rotate(start_angle, about_point=pointer.get_center())
+ dp_sym_1 = TexMobject(r"\vec F \cdot \vec dr").next_to(pointer, RIGHT, buff = SMALL_BUFF).scale(0.5).set_color("#D1D646").add_background_rectangle()
+ intg_sym_1 = TexMobject(r"\oint \vec F \cdot \vec dr").next_to(pointer, RIGHT, buff = SMALL_BUFF).scale(0.5).set_color("#75485E").add_background_rectangle()
+ dp = TexMobject(r"\vec F \cdot \vec dr \textit{ measures whether } \vec F \textit{ and } \vec dr", r" \textit{ are oriented the same way }").next_to(dp_sym_1, DOWN, buff = SMALL_BUFF).scale(0.3).set_color("#EDF2EF")
+ dp[1].next_to(dp[0], DOWN, buff = SMALL_BUFF)
+
+
+ # groups according to animation
+ #one = VGroup( vec_f, vec_f_sym)
+ #two = VGroup(boundary, c_sym)
+ #three = VGroup(dr_sym, pointer)
+ #four = VGroup(dp, dp_sym) #this is when to zoom in
+ #five = VGroup(intg, intg_sym)
+
+ delete = VGroup(vec_f, vec_f_sym, c, dr, dr_sym)
+
+
+ self.play(ShowCreation(vec_f), ShowCreation(vec_f_sym))
+ self.wait()
+ self.play(ShowCreation(vector_field), Indicate(vec_f_sym))
+ self.wait(2)
+ self.play(ShowCreation(c))
+ self.wait()
+ self.play(ShowCreation(boundary), ShowCreation(c_sym), Indicate(c))
+ self.wait(2)
+ self.play(ShowCreation(dr))
+ self.wait(2)
+ self.play(ShowCreation(dr_sym), Indicate(dr), ShowCreation(pointer))
+
+ self.play(FadeOut(delete))
+ self.play(
+ self.camera_frame.scale,.25,
+ self.camera_frame.move_to,pointer
+ )
+ self.play(ShowCreation(dp_sym_1), ShowCreation(dp[0]), ShowCreation(dp[1]))
+ self.add(dp_sym)
+ self.wait(3)
+ self.play(Restore(self.camera_frame))
+ self.remove(dp[0], dp[1], dp_sym_1)
+ self.wait()
+ self.add(boundary, pointer, self.camera_frame)
+ def update_rotate_move(mob,alpha):
+ pointer.restore()
+
+ angle = self.get_pending(boundary,alpha)
+
+ pointer.move_to(boundary.point_from_proportion(alpha))
+ pointer.rotate(angle, about_point=pointer.get_center())
+
+
+
+ self.play(
+ #self.camera_frame.scale,.25,
+ UpdateFromAlphaFunc(pointer,update_rotate_move),
+ run_time=3,
+ )
+ self.play(Write(b2))
+ self.play(ReplacementTransform(dp_sym, intg_sym), ShowCreation(intg))
+ self.play(ReplacementTransform(b2, intg_sym))
+ self.play(Indicate(intg_sym))
+ self.wait(2)
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file3_path-independent.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file3_path-independent.gif
new file mode 100644
index 0000000..27035d8
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file3_path-independent.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file3_path-independent.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file3_path-independent.py
new file mode 100644
index 0000000..c662c31
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file3_path-independent.py
@@ -0,0 +1,131 @@
+from manimlib.imports import *
+import numpy as np
+
+def func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -2*x,
+ -2*y,
+ 0
+ ])
+
+
+
+
+class many_paths(GraphScene):
+ CONFIG = {
+ "x_min" : 0,
+ "x_max" : 8.5,
+ "x_axis_height": 8.5,
+ "y_min" : 0,
+ "y_max" : 8.5,
+ "y_axis_height": 8.5,
+ "graph_origin" : ORIGIN,
+ "function_color" : RED,
+
+ }
+ def construct(self):
+ self.setup_axes(animate=False)
+ self.remove(self.x_axis, self.y_axis)
+ background = VectorField(func,
+ x_min = 0, x_max = 8.5, y_min = 0, y_max = 8.5, colors = ["#DBD8AE"]
+ )
+
+ pointer = Dot(np.array([0, 1.5, 0])).scale(0.7).set_color_by_gradient(["#84732B", YELLOW_E])
+ start = np.array([0, 1.5, 0])
+ end = np.array([7.53, 5.043, 0])
+ path_one= self.get_graph(self.one, x_min = 0, x_max = 7.53)
+ path_two= self.get_graph(self.two, x_min = 0, x_max = 7.53)
+ path_three = self.get_graph(self.three, x_min = 0, x_max = 7.53)
+
+ group = VGroup(path_one, path_two, background, path_three).move_to(np.array([-3,0, 0])).scale(0.75)
+
+
+
+ path_one.set_color("#F6523C")
+ path_two.set_color("#80475E")
+ path_three.set_color("#0F7173")
+
+ # all the text
+ #function = TexMobject(r"f(x,y) = -(x^2 + y^2)").scale(0.6).set_color("#DBD8AE").shift(3.6*UP + 3*LEFT)
+ field = TexMobject(r"\vec F = -2x\hat i - 2y\hat j").set_color("#DBD8AE").shift(3.6*DOWN + 3*LEFT)
+ c1 = TexMobject(r"C_{1}: y = 6sin(\frac{x}{3} + 1.5)").scale(0.7).set_color("#0F7173").shift(3*UP + 4*RIGHT)
+ #c3 = TexMobject(r"C_{3}: y = 6sin(\frac{x}{3} + 1.5)").scale(0.7).set_color("#0F7173").next_to(li_path2, DOWN, buff = LARGE_BUFF)
+ li_path1 = TexMobject(r"\int_{C_{1}} \vec F \cdot \vec dr = ").set_color("#0F7173").next_to(c1, DOWN, buff = 0.2)
+ c2 = TexMobject(r"C_{2}: y = 0.47x + 1.5").scale(0.7).set_color("#80475E").next_to(li_path1, DOWN, buff = 0.4)
+ li_path2 = TexMobject(r"\int_{C_{2}} \vec F \cdot \vec dr = ").set_color("#80475E").next_to(c2, DOWN, buff = 0.2)
+ c3 = TexMobject(r"C_{3}: y = \frac{x^{16}}{2}+ 1.5").scale(0.7).set_color("#F6523C").next_to(li_path2, DOWN, buff = 0.4)
+ li_path3 = TexMobject(r"\int_{C_{3}} \vec F \cdot \vec dr = ").set_color("#F6523C").next_to(c3, DOWN, buff = 0.2)
+
+ cs = VGroup(c1, c2, c3)
+
+
+ c_1 = lambda x: c1_value.get_value()
+ c_2 = lambda x: c2_value.get_value()
+ c_3 = lambda x: c3_value.get_value()
+
+ c1_value = ValueTracker(0)
+ c2_value = ValueTracker(0)
+ c3_value = ValueTracker(0)
+
+ c1_tex = DecimalNumber(c1_value.get_value()).add_updater(lambda v: v.set_value(c1_value.get_value())).next_to(li_path1, RIGHT, buff = SMALL_BUFF).set_color("#0F7173")
+ c2_tex = DecimalNumber(c2_value.get_value()).add_updater(lambda v: v.set_value(c2_value.get_value())).next_to(li_path2, RIGHT, buff = SMALL_BUFF).set_color("#80475E")
+ c3_tex = DecimalNumber(c3_value.get_value()).add_updater(lambda v: v.set_value(c3_value.get_value())).next_to(li_path3, RIGHT, buff = SMALL_BUFF).set_color("#F6523C")
+
+
+ paths = VGroup(li_path1, li_path2, li_path3, c1_tex, c2_tex, c3_tex)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self.play(ShowCreation(field), ShowCreation(background))
+ self.wait()
+ self.play(ShowCreation(path_one), ShowCreation(path_two), ShowCreation(path_three), ShowCreation(cs))
+ self.wait(2)
+ self.add(c1_tex)
+ self.play(ShowCreation(li_path1))
+ self.play(MoveAlongPath(pointer, path_three), c1_value.set_value,-78.9,
+ rate_func=linear,
+ run_time=3
+ )
+ self.wait(2)
+ self.play(ShowCreation(li_path2))
+ self.add(c2_tex)
+ self.play(MoveAlongPath(pointer, path_two), c2_value.set_value,-78.9,
+ rate_func=linear,
+ run_time=3
+ )
+ self.play(ShowCreation(li_path3))
+ self.add(c3_tex)
+ self.play(MoveAlongPath(pointer, path_one), c3_value.set_value,-78.9,
+ rate_func=linear,
+ run_time=3
+ )
+ self.wait()
+ self.play(Indicate(paths))
+ self.wait()
+ #self.play(MoveAlongPath(pointer, path_three))
+ #self.wait(2)
+
+ def one(self,x):
+ return x**2/16 + 1.5
+
+ def three(self,x):
+ return 6*np.sin(x/3) + 1.5
+
+ def two(self,x):
+ return 0.4705*x + 1.5
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file4_path-dependent.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file4_path-dependent.gif
new file mode 100644
index 0000000..d96e1e1
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file4_path-dependent.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file4_path-dependent.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file4_path-dependent.py
new file mode 100644
index 0000000..cb951e7
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file4_path-dependent.py
@@ -0,0 +1,130 @@
+from manimlib.imports import *
+import numpy as np
+
+def func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ y,
+ -x,
+ 0
+ ])
+
+
+
+
+class many_paths(GraphScene):
+ CONFIG = {
+ "x_min" : 0,
+ "x_max" : 8.5,
+ "x_axis_height": 8.5,
+ "y_min" : 0,
+ "y_max" : 8.5,
+ "y_axis_height": 8.5,
+ "graph_origin" : ORIGIN,
+ "function_color" : RED,
+
+ }
+ def construct(self):
+ self.setup_axes(animate=False)
+ self.remove(self.x_axis, self.y_axis)
+ background = VectorField(func,
+ x_min = 0, x_max = 8.5, y_min = 0, y_max = 8.5, colors = ["#DBD8AE"]
+ )
+
+ pointer = Dot(np.array([0, 1.5, 0])).scale(0.7).set_color_by_gradient(["#84732B", YELLOW_E])
+ start = np.array([0, 1.5, 0])
+ end = np.array([7.53, 5.043, 0])
+ path_one= self.get_graph(self.one, x_min = 0, x_max = 7.53)
+ path_two= self.get_graph(self.two, x_min = 0, x_max = 7.53)
+ path_three = self.get_graph(self.three, x_min = 0, x_max = 7.53)
+
+ group = VGroup(path_one, path_two, background, path_three).move_to(np.array([-3,0, 0])).scale(0.75)
+
+
+
+ path_one.set_color("#F6523C")
+ path_two.set_color("#80475E")
+ path_three.set_color("#0F7173")
+
+ # all the text
+ #function = TexMobject(r"f(x,y) = -(x^2 + y^2)").scale(0.6).set_color("#DBD8AE").shift(3.6*UP + 3*LEFT)
+ field = TexMobject(r"\vec F = y\hat i - x\hat j").set_color("#DBD8AE").shift(3.6*DOWN + 3*LEFT)
+ c1 = TexMobject(r"C_{1}: y = 6sin(\frac{x}{3} + 1.5)").scale(0.7).set_color("#0F7173").shift(3*UP + 4*RIGHT)
+ #c3 = TexMobject(r"C_{3}: y = 6sin(\frac{x}{3} + 1.5)").scale(0.7).set_color("#0F7173").next_to(li_path2, DOWN, buff = LARGE_BUFF)
+ li_path1 = TexMobject(r"\int_{C_{1}} \vec F \cdot \vec dr = ").set_color("#0F7173").next_to(c1, DOWN, buff = 0.2)
+ c2 = TexMobject(r"C_{2}: y = 0.47x + 1.5").scale(0.7).set_color("#80475E").next_to(li_path1, DOWN, buff = 0.4)
+ li_path2 = TexMobject(r"\int_{C_{2}} \vec F \cdot \vec dr = ").set_color("#80475E").next_to(c2, DOWN, buff = 0.2)
+ c3 = TexMobject(r"C_{3}: y = \frac{x^{16}}{2} + 1.5").scale(0.7).set_color("#F6523C").next_to(li_path2, DOWN, buff = 0.4)
+ li_path3 = TexMobject(r"\int_{C_{3}} \vec F \cdot \vec dr = ").set_color("#F6523C").next_to(c3, DOWN, buff = 0.2)
+
+ cs = VGroup(c1, c2, c3)
+
+
+ c_1 = lambda x: c1_value.get_value()
+ c_2 = lambda x: c2_value.get_value()
+ c_3 = lambda x: c3_value.get_value()
+
+ c1_value = ValueTracker(0)
+ c2_value = ValueTracker(0)
+ c3_value = ValueTracker(0)
+
+ c1_tex = DecimalNumber(c1_value.get_value()).add_updater(lambda v: v.set_value(c1_value.get_value())).next_to(li_path1, RIGHT, buff = SMALL_BUFF).set_color("#0F7173")
+ c2_tex = DecimalNumber(c2_value.get_value()).add_updater(lambda v: v.set_value(c2_value.get_value())).next_to(li_path2, RIGHT, buff = SMALL_BUFF).set_color("#80475E")
+ c3_tex = DecimalNumber(c3_value.get_value()).add_updater(lambda v: v.set_value(c3_value.get_value())).next_to(li_path3, RIGHT, buff = SMALL_BUFF).set_color("#F6523C")
+
+
+ paths = VGroup(li_path1, li_path2, li_path3, c1_tex, c2_tex, c3_tex)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self.play(ShowCreation(field), ShowCreation(background))
+ self.wait()
+ self.play(ShowCreation(path_one), ShowCreation(path_two), ShowCreation(path_three), ShowCreation(cs))
+ self.wait(2)
+ self.add(c1_tex)
+ self.play(ShowCreation(li_path1))
+ self.play(MoveAlongPath(pointer, path_three), c1_value.set_value,-49.67,
+ rate_func=linear,
+ run_time=3
+ )
+ self.wait(2)
+ self.play(ShowCreation(li_path2))
+ self.add(c2_tex)
+ self.play(MoveAlongPath(pointer, path_two), c2_value.set_value,-11.3,
+ rate_func=linear,
+ run_time=3
+ )
+ self.play(ShowCreation(li_path3))
+ self.add(c3_tex)
+ self.play(MoveAlongPath(pointer, path_one), c3_value.set_value,-2.4,
+ rate_func=linear,
+ run_time=3
+ )
+ self.wait()
+ self.play(Indicate(paths))
+ self.wait()
+ #self.play(MoveAlongPath(pointer, path_three))
+ #self.wait(2)
+
+ def one(self,x):
+ return x**2/16 + 1.5
+
+ def three(self,x):
+ return 6*np.sin(x/3) + 1.5
+
+ def two(self,x):
+ return 0.4705*x + 1.5
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file5_closed-loop.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file5_closed-loop.gif
new file mode 100644
index 0000000..87e5dd5
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file5_closed-loop.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file5_closed-loop.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file5_closed-loop.py
new file mode 100644
index 0000000..9211f0d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file5_closed-loop.py
@@ -0,0 +1,63 @@
+from manimlib.imports import *
+import numpy as np
+
+def div(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ x,
+ y,
+ 0
+ ])
+
+
+class Loop(Scene):
+ def get_pending(self,path,proportion,dx=0.01):
+ if proportion < 1:
+ coord_i = path.point_from_proportion(proportion)
+ coord_f = path.point_from_proportion(proportion+dx)
+ else:
+ coord_i = path.point_from_proportion(proportion-dx)
+ coord_f = path.point_from_proportion(proportion)
+ line = Line(coord_i,coord_f)
+ angle = line.get_angle()
+ return angle
+ def construct(self):
+
+
+
+ boundary = VMobject(stroke_color = "#F4EDED")
+ boundary.set_points_smoothly([np.array([-2, 1.8,0]),np.array([-1.6, 0.5,0]),np.array([-3.2, -1.2,0]),np.array([2.6, -1.5,0]),np.array([1, 0,0]),np.array([3.5,2.3, 0]), np.array([-2,1.8, 0])])
+ #c = TexMobject(r"C").next_to(surf,RIGHT+UP).set_color("#F4EDED")
+
+
+ text = TexMobject(r"\oint \vec F \cdot \vec dr", r" = 0").shift(3*DOWN).set_stroke(width = 1.5)
+ vec_field = VectorField(div)
+
+ start_angle = self.get_pending(boundary, 0)
+
+ pointer = Triangle(fill_opacity = 1).set_height(0.25).set_color(WHITE)
+ pointer.set_fill(WHITE)
+ pointer.move_to(boundary.get_start())
+ pointer.rotate(- PI / 2)
+ pointer.save_state()
+ pointer.rotate(start_angle, about_point=pointer.get_center())
+
+
+ self.play(ShowCreation(boundary), ShowCreation(vec_field))
+ self.wait()
+ self.play(Write(text[0]))
+ def update_rotate_move(mob,alpha):
+ pointer.restore()
+
+ angle = self.get_pending(boundary,alpha)
+
+ pointer.move_to(boundary.point_from_proportion(alpha))
+ pointer.rotate(angle, about_point=pointer.get_center())
+ self.play(
+ #self.camera_frame.scale,.25,
+ UpdateFromAlphaFunc(pointer,update_rotate_move),
+ run_time=3,
+ )
+ self.play(ShowCreation(text[1]))
+ self.play(Indicate(text))
+ self.wait()
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file6_potential-func.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file6_potential-func.gif
new file mode 100644
index 0000000..97a9500
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file6_potential-func.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file6_potential-func.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file6_potential-func.py
new file mode 100644
index 0000000..e52a03a
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Conservative fields/Conservative_file6_potential-func.py
@@ -0,0 +1,33 @@
+from manimlib.imports import *
+
+def field_func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ np.cos(x),
+ np.cos(y),
+ 0
+ ])
+
+class Potential(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+ self.set_camera_orientation(phi=0*DEGREES,theta=0*DEGREES,distance=40)
+ vec_field = VectorField(field_func, x_min =-3, x_max = 3, y_min =-3, y_max =3)
+ surf = ParametricSurface(lambda u,v: np.array([u,v,
+ np.sin(u) + np.sin(v)]),
+ u_min = -3, u_max = 3, v_min = -3, v_max = 3, stroke_color = PURPLE_E, checkerboard_colors = [PURPLE_E, PURPLE_E]).fade(0.5)
+
+ #text
+ vec = TexMobject(r"\vec F = \cos x \hat i + \cos y \hat j ").set_color(YELLOW_C).shift(3.8*UP+3.6*RIGHT).scale(0.7)
+ func = TexMobject(r"\textit{has a potential function }", r"f(x,y) = \sin x + \sin y").scale(0.7).next_to(vec, DOWN, buff = 0.2)
+ func[1].set_color(PURPLE_E)
+
+ self.play(ShowCreation(vec_field))
+ self.add_fixed_in_frame_mobjects(vec)
+ self.wait()
+ self.play(FadeIn(surf))
+ self.begin_ambient_camera_rotation()
+ self.move_camera(phi=45*DEGREES,theta=60*DEGREES)
+ self.add_fixed_in_frame_mobjects(func)
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file10_gauss.png b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file10_gauss.png
new file mode 100644
index 0000000..74e2723
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file10_gauss.png
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file10_gauss.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file10_gauss.py
new file mode 100644
index 0000000..d77f92e
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file10_gauss.py
@@ -0,0 +1,51 @@
+import sys
+import numpy as np
+import matplotlib.pyplot as plt
+from matplotlib.patches import Circle
+
+def E(q, r0, x, y):
+ """Return the electric field vector E=(Ex,Ey) due to charge q at r0."""
+ den = np.hypot(x-r0[0], y-r0[1])**3
+ return q * (x - r0[0]) / den, q * (y - r0[1]) / den
+
+# Grid of x, y points
+nx, ny = 64, 64
+x = np.linspace(-2, 2, nx)
+y = np.linspace(-2, 2, ny)
+X, Y = np.meshgrid(x, y)
+
+# Create a multipole with nq charges of alternating sign, equally spaced
+# on the unit circle.
+nq = 2**int(sys.argv[1])
+charges = []
+for i in range(nq):
+ q = i%2 * 2 - 1
+ charges.append((q, (np.cos(2*np.pi*i/nq), np.sin(2*np.pi*i/nq))))
+
+# Electric field vector, E=(Ex, Ey), as separate components
+Ex, Ey = np.zeros((ny, nx)), np.zeros((ny, nx))
+for charge in charges:
+ ex, ey = E(*charge, x=X, y=Y)
+ Ex += ex
+ Ey += ey
+
+fig = plt.figure()
+plt.rcParams['axes.facecolor'] = 'black'
+ax = fig.add_subplot(111)
+
+# Plot the streamlines with an appropriate colormap and arrow style
+color = 2 * np.log(np.hypot(Ex, Ey))
+ax.streamplot(x, y, Ex, Ey, color=color, linewidth=1, cmap=plt.cm.inferno,
+ density=2, arrowstyle='->', arrowsize=1.5)
+
+# Add filled circles for the charges themselves
+charge_colors = {True: '#aa0000', False: '#0000aa'}
+for q, pos in charges:
+ ax.add_artist(Circle(pos, 0.05, color=charge_colors[q>0]))
+
+ax.set_xlabel('$x$')
+ax.set_ylabel('$y$')
+ax.set_xlim(-2,2)
+ax.set_ylim(-2,2)
+ax.set_aspect('equal')
+plt.show()
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file11_gravitational-field.png b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file11_gravitational-field.png
new file mode 100644
index 0000000..129e51b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file11_gravitational-field.png
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file11_gravitational-filed.ipynb b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file11_gravitational-filed.ipynb
new file mode 100644
index 0000000..4ad8c27
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file11_gravitational-filed.ipynb
@@ -0,0 +1,119 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%gui qt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "from mayavi import mlab\n",
+ "import scipy\n",
+ "import time"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/padmapriya/mohyavi/lib/python3.6/site-packages/ipykernel_launcher.py:3: RuntimeWarning: invalid value encountered in true_divide\n",
+ " This is separate from the ipykernel package so we can avoid doing imports until\n",
+ "/home/padmapriya/mohyavi/lib/python3.6/site-packages/ipykernel_launcher.py:4: RuntimeWarning: invalid value encountered in true_divide\n",
+ " after removing the cwd from sys.path.\n",
+ "/home/padmapriya/mohyavi/lib/python3.6/site-packages/ipykernel_launcher.py:5: RuntimeWarning: invalid value encountered in true_divide\n",
+ " \"\"\"\n"
+ ]
+ }
+ ],
+ "source": [
+ "x, y, z = np.mgrid[-2:3, -2:3, -2:3]\n",
+ "r = np.sqrt(x**2 + y**2 + z**2)\n",
+ "u = x/r**3\n",
+ "v = y/r**3\n",
+ "w = z/r**3\n",
+ "\n",
+ "a = mlab.quiver3d(x, y, z, u, v, w)\n",
+ "mlab.axes(a)\n",
+ "mlab.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x, y, z = np.mgrid[-2:3, -2:3, -2:3]\n",
+ "u = y**3 - 9*y\n",
+ "v = x**3 - 9*x\n",
+ "w = x\n",
+ "\n",
+ "a = mlab.quiver3d(x, y, z, u, v, w, colormap = 'gist_earth')\n",
+ "mlab.fig(bgcolor = (0,0,0))\n",
+ "\n",
+ "for i in range(50):\n",
+ " mlab.view(65, -65)\n",
+ " mlab.view(azimuth= 3.6*i, elevation=-60, distance=10)\n",
+ " mlab.process_ui_events()\n",
+ " time.sleep = 0.005\n",
+ " mlab.savefig('curl_%02d.png' % i)\n",
+ " \n",
+ "\n",
+ "x, y, z = np.mgrid[-2:3, -2:3, -2:3]\n",
+ "p = x\n",
+ "q = y\n",
+ "r = 4.5*(x**2 - y**2)\n",
+ "\n",
+ "b = mlab.quiver3d(x, y, z, p, q, r, colormap = 'gist_earth')\n",
+ "for j in range(25):\n",
+ " mlab.view(65, -65)\n",
+ " mlab.view(azimuth= 3.6*j, elevation=-60, distance=10)\n",
+ " mlab.process_ui_events()\n",
+ " time.sleep = 0.005\n",
+ " mlab.savefig('curl2_%02d.png' % j)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file12_ponder-curl.png b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file12_ponder-curl.png
new file mode 100644
index 0000000..2e7fc79
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file12_ponder-curl.png
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file12_ponder-curl.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file12_ponder-curl.py
new file mode 100644
index 0000000..be8a17a
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file12_ponder-curl.py
@@ -0,0 +1,17 @@
+from manimlib.imports import *
+import numpy as np
+
+def curl(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ y,
+ 0,
+ 0
+ ])
+
+class Ponder_curl(Scene):
+ def construct(self):
+ vf = VectorField(curl)
+ self.add(vf)
+ self.wait()
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file1_sources-and-sinks.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file1_sources-and-sinks.gif
new file mode 100644
index 0000000..dcc0843
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file1_sources-and-sinks.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file1_sources-and-sinks.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file1_sources-and-sinks.py
new file mode 100644
index 0000000..d26525e
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file1_sources-and-sinks.py
@@ -0,0 +1,76 @@
+from manimlib.imports import *
+import numpy as np
+
+def divergence(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ np.sin(x),
+ np.cos(y),
+ 0
+ ])
+
+def curl(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ np.sin(y),
+ np.cos(x),
+ 0
+ ])
+
+class fluid_flow(Scene):
+ def construct(self):
+
+
+
+ ball_a = Dot().set_color_by_gradient(["#F87666", "#F53A23", PURPLE_E]).move_to(np.array([-6,-1,0])).fade(0.2).scale(1.2)
+ ball_b = Dot().set_color_by_gradient(["#F87666", "#F53A23", PURPLE_E]).move_to(np.array([0.1,3,0])).fade(0.2).scale(1.2)
+ ball_c = Dot().set_color_by_gradient(["#F87666", "#F53A23", PURPLE_E]).move_to(np.array([-0.5,-1, 0])).fade(0.2).scale(1.2)
+ ball_d = Dot().set_color_by_gradient(["#F87666", "#F53A23", PURPLE_E]).move_to(np.array([4.5,-1.2,0])).fade(0.2).scale(1.2)
+ ball2 = Dot().set_color_by_gradient(["#F87666", "#F53A23", PURPLE_E]).move_to(np.array([-0.5,0,0])).fade(0.2).scale(1.2)
+ ball3 = Dot().set_color_by_gradient(["#F87666", "#F53A23", PURPLE_E]).move_to(np.array([-1.5,1.2,0])).fade(0.2).scale(1.2)
+ ball4 = Dot().set_color_by_gradient(["#F87666", "#F53A23", PURPLE_E]).move_to(np.array([-1.5,-1.2,0])).fade(0.2).scale(1.2)
+ ball5 = Sphere(radius = 0.2, chekerboard_colors =["#F87666", "#F53A23", PURPLE_E]).set_color_by_gradient(["#F87666", "#F53A23", PURPLE_E]).fade(0.2).move_to(np.array([-4.7,0,0]))
+
+ flow_one = StreamLines(
+ divergence,
+ virtual_time=3,
+ min_magnitude=0,
+ max_magnitude=1,
+ ).set_color_by_gradient(["#003853", "#0478A1","#04AED9", WHITE])
+ flow_div =(AnimatedStreamLines(
+ flow_one,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ ))
+
+ flow_two = StreamLines(
+ curl,
+
+ virtual_time=3,
+ min_magnitude=0,
+ max_magnitude=1,
+ ).set_color_by_gradient(["#003853", "#0478A1","#04AED9", WHITE])
+ flow_curl =(AnimatedStreamLines(
+ flow_two,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ ))
+
+ label_div = TexMobject(r"\textit{Fluid flows out from }", r"\textit{sources }", r"\textit{and into }", r"\textit{sinks}" ).move_to(np.array([0,3.5, 0])).set_stroke(width = 1.5).scale(0.7)
+ label_div[1].set_color("#F87666")
+ label_div[3].set_color("#F87666")
+ title_div = TexMobject(r"Divergence").set_stroke(width = 1.5).move_to(3*DOWN).set_color("#F87666").scale(1.2)
+ label_curl = TexMobject(r"\textit{Fluid also rotates }", r"\textit{clockwise }", r"\textit{and }", r"\textit{counter-clockwise}" ).move_to(np.array([0,3.5, 0])).set_stroke(width = 1.5).scale(0.7)
+ label_curl[1].set_color("#F87666")
+ label_curl[3].set_color("#F87666")
+ title_curl = TexMobject(r"Curl").set_stroke(width = 1.5).move_to(3*DOWN).set_color("#F87666").scale(1.2)
+
+
+
+
+ self.add(flow_div, label_div)
+ self.play(Write(title_div))
+ self.wait(5)
+ self.remove(flow_div)
+ self.wait()
+ self.add(flow_curl)
+ self.play(ReplacementTransform(label_div, label_curl), ReplacementTransform(title_div, title_curl))
+ self.wait(6)
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file2_div-curl-types.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file2_div-curl-types.py
new file mode 100644
index 0000000..e8e1a83
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file2_div-curl-types.py
@@ -0,0 +1,162 @@
+from manimlib.imports import *
+import numpy as np
+
+def pos_div(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ x,
+ y,
+ 0
+ ])
+
+def neg_div(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -x,
+ -y,
+ 0
+ ])
+
+def zero_div(coordinate):
+ x,y = coordinate[:2]
+ y = 1.0
+ return np.array([
+ y,
+ 0,
+ 0
+ ])
+
+def curl_c(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ y,
+ -x,
+ 0
+ ])
+
+def curl_ac(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -y,
+ x,
+ 0
+ ])
+
+
+
+
+class Examples(Scene):
+ def construct(self):
+
+ vf1 = VectorField(pos_div, x_min = -1.5, x_max = 1.5, y_min = -1.5, y_max = 1.5).shift(2.5*UP, 4*LEFT)
+ vf3 = VectorField(neg_div, x_min = -1.5, x_max = 1.5, y_min = -1.5, y_max = 1.5).shift(2.5*UP, 4*RIGHT)
+ vf2 = VectorField(zero_div, x_min = -1.5, x_max = 1.5, y_min = -1.5, y_max = 1.5).move_to(np.array([0, 0.5, 0]))
+ vf4 = VectorField(curl_c, x_min = -1.5, x_max = 1.5, y_min = -1.5, y_max = 1.5).shift(2*DOWN, 4*RIGHT)
+ vf5 = VectorField(curl_ac, x_min = -1.5, x_max = 1.5, y_min = -1.5, y_max = 1.5).shift(2*DOWN, 4*LEFT)
+ dot = Dot().move_to(vf1.get_center())
+ label3 = TexMobject(r"\textit{Sink}", r"\textrm{div} F < 0").set_color(BLUE_E).scale(0.6).shift(3*DOWN + 0.7*RIGHT)
+ label1 = TexMobject(r"\textit{Source}", r"\textrm{div} F > 0").set_color(YELLOW_E).scale(0.6).shift(2.8*DOWN + 0.7*RIGHT)
+ label2 = TexMobject(r"\textrm{div} F =0", r"\textrm{ curl} F = 0").scale(0.6).shift(3*DOWN + 0.7*RIGHT)
+ label4 = TexMobject(r"\textit{Clockwise rotation}", r"\textrm{curl} F < 0").set_color(BLUE_E).scale(0.6).shift(3*DOWN + 0.7*RIGHT)
+ label5 = TexMobject(r"\textit{Counter-clockwise rotation}", r"\textrm{curl} F > 0").set_color(YELLOW_E).scale(0.6).shift(3*DOWN + 0.7*RIGHT)
+
+ label1[1].next_to(label1[0], DOWN, buff = SMALL_BUFF).set_color(WHITE)
+ label2[1].next_to(label2[0], DOWN, buff = SMALL_BUFF).set_color(WHITE)
+ label3[1].next_to(label3[0], DOWN, buff = SMALL_BUFF).set_color(WHITE)
+
+ label4[1].next_to(label4[0], DOWN, buff = SMALL_BUFF).set_color(WHITE)
+ label5[1].next_to(label5[0], DOWN, buff = SMALL_BUFF).set_color(WHITE)
+
+ lines_a = StreamLines(
+ pos_div,
+ virtual_time=1.5,
+ min_magnitude=0,
+ max_magnitude=1.5,
+ x_min = -1, x_max = 1, y_min = -1, y_max = 1
+ ).shift(2.5*UP, 4*LEFT)
+ lines1 = AnimatedStreamLines(
+ lines_a,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ )
+
+ lines_b = StreamLines(
+ zero_div,
+ virtual_time=1.5,
+ min_magnitude=0,
+ max_magnitude=1.5,
+ x_min = -0.5, x_max = 0.5, y_min = -0.5, y_max = 0.5
+ ).move_to(np.array([-0.2, 0.5, 0]))
+ lines2 = AnimatedStreamLines(
+ lines_b,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ )
+
+ lines_c = StreamLines(
+ neg_div,
+ virtual_time=1.5,
+ min_magnitude=0,
+ max_magnitude=1.5,
+ x_min = -1, x_max = 1, y_min = -1, y_max = 1
+ ).shift(2.5*UP, 4*RIGHT)
+ lines3 =(AnimatedStreamLines(
+ lines_c,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ ))
+
+ lines_d = StreamLines(
+ curl_c,
+ virtual_time=1.5,
+ min_magnitude=0,
+ max_magnitude=1.5,
+ x_min = -1, x_max = 1, y_min = -1, y_max = 1
+ ).shift(2*DOWN, 4*RIGHT)
+ lines4 =(AnimatedStreamLines(
+ lines_d,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ ))
+
+ lines_e = StreamLines(
+ curl_ac,
+ virtual_time=1.5,
+ min_magnitude=0,
+ max_magnitude=1.5,
+ x_min = -1, x_max = 1, y_min = -1, y_max = 1
+ ).shift(2*DOWN, 4*LEFT)
+ lines5 =(AnimatedStreamLines(
+ lines_e,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ ))
+ self.play(Write(vf1))
+ self.wait()
+ self.add(lines1)
+ self.play(ShowCreation(label1[0]), ShowCreation(label1[1]))
+ self.wait(4)
+ self.remove(lines1)
+ self.play(Write(vf2))
+ self.add(lines2)
+ self.play(ReplacementTransform(label1, label2))
+ self.play(Indicate(label2))
+ self.wait(4)
+ self.remove(lines2)
+ self.play(Write(vf3))
+ self.add(lines3)
+ self.play(ReplacementTransform(label2, label3))
+ self.play(Indicate(label3))
+ self.wait(4)
+ self.remove(lines3)
+ self.play(Write(vf4))
+ self.add(lines4)
+ self.play(ReplacementTransform(label3, label4))
+ self.play(Indicate(label4))
+ self.wait(4)
+ self.remove(lines4)
+ self.play(Write(vf5))
+ self.add(lines5)
+ self.play(ReplacementTransform(label4, label5))
+ self.play(Indicate(label5))
+ self.wait(4)
+ self.remove(lines5)
+ self.wait()
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file2_div_curl-types.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file2_div_curl-types.gif
new file mode 100644
index 0000000..9d60f45
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file2_div_curl-types.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file3_threed-vec-field.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file3_threed-vec-field.gif
new file mode 100644
index 0000000..ad331a3
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file3_threed-vec-field.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file3_threed-vec-field.ipynb b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file3_threed-vec-field.ipynb
new file mode 100644
index 0000000..8d41df4
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file3_threed-vec-field.ipynb
@@ -0,0 +1,67 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%gui qt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "from mayavi import mlab"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x, y, z = np.mgrid[-2:3, -2:3, -2:3]\n",
+ "u = y**3 - 9*y\n",
+ "v = x**3 - 9*x\n",
+ "w = x\n",
+ "\n",
+ "a = mlab.quiver3d(x, y, z, u, v, w)\n",
+ "mlab.axes(a)\n",
+ "mlab.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file4_output-curl.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file4_output-curl.gif
new file mode 100644
index 0000000..956458b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file4_output-curl.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file4_output-curl.ipynb b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file4_output-curl.ipynb
new file mode 100644
index 0000000..0f8b326
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file4_output-curl.ipynb
@@ -0,0 +1,67 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%gui qt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "from mayavi import mlab"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x, y, z = np.mgrid[-2:3, -2:3, -2:3]\n",
+ "u = x\n",
+ "v = y\n",
+ "w = 4.5*(x**2 - y**2)\n",
+ "\n",
+ "a = mlab.quiver3d(x, y, z, u, v, w)\n",
+ "mlab.axes(a)\n",
+ "mlab.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file5_neg-div.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file5_neg-div.gif
new file mode 100644
index 0000000..7634acf
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file5_neg-div.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file5_neg-div.ipynb b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file5_neg-div.ipynb
new file mode 100644
index 0000000..7fec515
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file5_neg-div.ipynb
@@ -0,0 +1,6 @@
+{
+ "cells": [],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file6_macro-micro-curl.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file6_macro-micro-curl.gif
new file mode 100644
index 0000000..9b30ce5
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file6_macro-micro-curl.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file6_macro-micro-curl.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file6_macro-micro-curl.py
new file mode 100644
index 0000000..02c75a3
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file6_macro-micro-curl.py
@@ -0,0 +1,42 @@
+from manimlib.imports import *
+import numpy as np
+
+def curl(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -y,
+ x,
+ 0
+ ])
+
+
+class Subtle(Scene):
+ def construct(self):
+ vf1 = VectorField(curl)
+ pinwheel = SVGMobject("geo").move_to(np.array([2, 0, 0])).scale(0.3).set_stroke(width = 0.3).set_color_by_gradient(["#adf802", YELLOW_C]).move_to(np.array([2.3, 0, 0]))
+ self.add(pinwheel)
+
+ label1 = TexMobject(r"\textit{Microscopic curl}").shift(3*DOWN).add_background_rectangle()
+ label2 = TexMobject(r"\textit{Macroscopic curl}").shift(3*DOWN)
+
+ ball1 = Dot(checkerboard_colors = [BLUE_E, PURPLE_E], resolution = [2,2], radius = 0.4).move_to(np.array([-1, -1, 0]))
+ ball2 = Sphere(checkerboard_colors = [BLUE_E, TEAL], resolution = [16, 16], radius = 0.3).move_to(np.array([2, 0, 0]))
+ circ = Circle(radius = 2)
+
+
+ self.add(vf1)
+ self.wait()
+ self.play(ShowCreation(pinwheel))
+ self.bring_to_front(pinwheel)
+ self.play(Rotating(pinwheel), ShowCreation(label1))
+ self.wait(2)
+ #self.add(ball1)
+ move_submobjects_along_vector_field(pinwheel, curl)
+ self.play(FadeOut(label1), ShowCreation(label2))
+ self.play(Indicate(label2))
+
+ self.wait(5)
+
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file7_div-formula.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file7_div-formula.gif
new file mode 100644
index 0000000..4910d2f
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file7_div-formula.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file7_div-formula.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file7_div-formula.py
new file mode 100644
index 0000000..4e1eab2
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file7_div-formula.py
@@ -0,0 +1,225 @@
+from manimlib.imports import *
+import numpy as np
+
+def div(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ x,
+ y,
+ 0
+ ])
+
+
+
+
+class Grid(VMobject):
+ CONFIG = {
+ "height": 6.0,
+ "width": 6.0,
+ }
+
+ def __init__(self, rows, columns, **kwargs):
+ digest_config(self, kwargs, locals())
+ VMobject.__init__(self, **kwargs)
+
+ def generate_points(self):
+ x_step = self.width / self.columns
+ y_step = self.height / self.rows
+
+ for x in np.arange(0, self.width + x_step, x_step):
+ self.add(Line(
+ [x - self.width / 2., -self.height / 2., 0],
+ [x - self.width / 2., self.height / 2., 0],
+ ))
+ for y in np.arange(0, self.height + y_step, y_step):
+ self.add(Line(
+ [-self.width / 2., y - self.height / 2., 0],
+ [self.width / 2., y - self.height / 2., 0]
+ ))
+
+
+class ScreenGrid(VGroup):
+ CONFIG = {
+ "rows":8,
+ "columns":14,
+ "height": FRAME_Y_RADIUS*2,
+ "width": 14,
+ "grid_stroke":0.5,
+ "grid_color":WHITE,
+ "axis_color":RED,
+ "axis_stroke":2,
+ "show_points":False,
+ "point_radius":0,
+ "labels_scale":0.5,
+ "labels_buff":0,
+ "number_decimals":2
+ }
+
+ def __init__(self,**kwargs):
+ VGroup.__init__(self,**kwargs)
+ rows=self.rows
+ columns=self.columns
+ grilla=Grid(width=self.width,height=self.height,rows=rows,columns=columns).set_stroke(self.grid_color,self.grid_stroke)
+
+ vector_ii=ORIGIN+np.array((-self.width/2,-self.height/2,0))
+ vector_id=ORIGIN+np.array((self.width/2,-self.height/2,0))
+ vector_si=ORIGIN+np.array((-self.width/2,self.height/2,0))
+ vector_sd=ORIGIN+np.array((self.width/2,self.height/2,0))
+
+ ejes_x=Line(LEFT*self.width/2,RIGHT*self.width/2)
+ ejes_y=Line(DOWN*self.height/2,UP*self.height/2)
+
+ ejes=VGroup(ejes_x,ejes_y).set_stroke(self.axis_color,self.axis_stroke)
+
+ divisiones_x=self.width/columns
+ divisiones_y=self.height/rows
+
+ direcciones_buff_x=[UP,DOWN]
+ direcciones_buff_y=[RIGHT,LEFT]
+ dd_buff=[direcciones_buff_x,direcciones_buff_y]
+ vectores_inicio_x=[vector_ii,vector_si]
+ vectores_inicio_y=[vector_si,vector_sd]
+ vectores_inicio=[vectores_inicio_x,vectores_inicio_y]
+ tam_buff=[0,0]
+ divisiones=[divisiones_x,divisiones_y]
+ orientaciones=[RIGHT,DOWN]
+ puntos=VGroup()
+ leyendas=VGroup()
+
+
+ for tipo,division,orientacion,coordenada,vi_c,d_buff in zip([columns,rows],divisiones,orientaciones,[0,1],vectores_inicio,dd_buff):
+ for i in range(1,tipo):
+ for v_i,direcciones_buff in zip(vi_c,d_buff):
+ ubicacion=v_i+orientacion*division*i
+ punto=Dot(ubicacion,radius=self.point_radius)
+ coord=round(punto.get_center()[coordenada],self.number_decimals)
+ leyenda=TextMobject("%s"%coord).scale(self.labels_scale)
+ leyenda.next_to(punto,direcciones_buff,buff=self.labels_buff)
+ puntos.add(punto)
+ leyendas.add(leyenda)
+
+ self.add(grilla,ejes,leyendas)
+ if self.show_points==True:
+ self.add(puntos)
+
+
+
+
+
+
+class ExpDiv(Scene):
+ def construct(self):
+
+ #all the text
+ field_text = TexMobject(r"\vec F = P\hat i + Q\hat j").shift(3*UP+5*RIGHT)
+ field_text_2 = TexMobject(r"\vec F = 2x\hat i + 2y\hat j").shift(3*UP+5*RIGHT)
+ p = TexMobject(r"P = 2x").scale(0.8)
+ q = TexMobject(r"Q = 2y").next_to(p, RIGHT).scale(0.8)
+ pq = VGroup(p, q)
+ pq.next_to(field_text_2, DOWN, buff = SMALL_BUFF)
+ dpq = TexMobject(r"\frac{\partial P}{\partial x}", r" \frac{\partial Q}{\partial y}").scale(0.8).next_to(pq, DOWN, buff = LARGE_BUFF)
+
+
+ dp_dq = TexMobject(r"\frac{\partial P}{\partial x} + \frac{\partial Q}{\partial y}", r" = \textrm{div} \vec F").scale(0.8).next_to(pq, DOWN, buff = LARGE_BUFF)
+ #dp_dq1 = TexMobject(r" = \textrm{div} \vec F").scale(0.8)
+ #dp_dq1.next_to(dp_dq[0], DOWN, buff = SMALL_BUFF)
+ dp_text = TexMobject(r"\frac{\partial P}{\partial x}\textit{: the rate of change of the horizontal component as x increases}").shift(3*DOWN).scale(0.8)
+ dq_text = TexMobject(r"\frac{\partial Q}{\partial y}\textit{: the rate of change of the vertical component as y increases}").shift(3*DOWN).scale(0.8)
+
+
+ vector_field = VectorField(div, x_min = -4, x_max = 4, y_min = -4, y_max = 4).shift(1.5*LEFT)
+
+ x_comps=VGroup()
+ y_comps=VGroup()
+ for vector in vector_field:
+ x = Vector(RIGHT, color = BLUE_E)
+ y = Vector(UP, color= YELLOW_E)
+ x.put_start_and_end_on(vector.points[0], np.array([vector.get_end()[0],vector.points[0][1],0]))
+ y.put_start_and_end_on(vector.points[0], np.array([vector.points[0][0],vector.get_end()[1],0]))
+ x_comps.add(x)
+ y_comps.add(y)
+
+ line1 = Arrow(4*LEFT, 4*RIGHT).shift(3.5*DOWN+1.5*LEFT)
+ line2 = Arrow(4*DOWN, 4*UP).shift(3*RIGHT)
+
+
+
+
+ # f(x) = x**2
+ fx = lambda x: x.get_value()/10
+ # ValueTrackers definition
+ x_value = ValueTracker(-4)
+ fx_value = ValueTracker(fx(x_value))
+ # DecimalNumber definition
+ x_tex = DecimalNumber(x_value.get_value()).add_updater(lambda v: v.set_value(x_value.get_value()))
+ fx_tex = DecimalNumber(fx_value.get_value()).add_updater(lambda v: v.set_value(fx(x_value)))
+ # TeX labels definition
+ x_label = TexMobject("x = ")
+ fx_label = TexMobject("P = ")
+ # Grouping of labels and numbers
+ group = VGroup(x_tex,fx_tex,x_label,fx_label).scale(0.8)
+ VGroup(x_tex, fx_tex).arrange_submobjects(DOWN,buff=0.3)
+ # Align labels and numbers
+ x_label.next_to(x_tex,LEFT, buff=0.1,aligned_edge=x_label.get_bottom())
+ fx_label.next_to(fx_tex,LEFT, buff=0.1,aligned_edge=fx_label.get_bottom())
+
+
+ fy = lambda y: y.get_value()/10
+ # ValueTrackers definition
+ y_value = ValueTracker(-4)
+ fy_value = ValueTracker(fy(y_value))
+ # DecimalNumber definition
+ y_tex = DecimalNumber(y_value.get_value()).add_updater(lambda v: v.set_value(y_value.get_value()))
+ fy_tex = DecimalNumber(fy_value.get_value()).add_updater(lambda v: v.set_value(fy(y_value)))
+ # Tey labels definition
+ y_label = TexMobject("y = ")
+ fy_label = TexMobject("Q = ")
+ # Grouping of labels and numbers
+ group_2 = VGroup(y_tex,fy_tex,y_label,fy_label).scale(0.8)
+ VGroup(y_tex, fy_tex).arrange_submobjects(DOWN,buff=0.3)
+ # Align labels and numbers
+ y_label.next_to(y_tex,LEFT, buff=0.1,aligned_edge=y_label.get_bottom())
+ fy_label.next_to(fy_tex,LEFT, buff=0.1,aligned_edge=fy_label.get_bottom())
+
+
+ self.play(ShowCreation(field_text))
+ self.wait()
+ self.play(ShowCreation(vector_field), ReplacementTransform(field_text, field_text_2))
+ self.wait()
+ self.play(ShowCreation(p), ShowCreation(q), FadeOut(vector_field))
+ self.wait()
+ self.play(ShowCreation(dpq[0]), ShowCreation(x_comps))
+ self.play(Indicate(dpq[0]))
+ self.wait()
+ self.play(ShowCreation(dp_text))
+ self.wait()
+ self.play(Uncreate(dp_text))
+
+ self.add(group.move_to(5*RIGHT+3*DOWN))
+ self.play(Write(line1),
+ x_value.set_value,4,
+ rate_func=linear,
+ run_time=3
+ )
+ self.wait(2)
+ self.play(FadeOut(group), FadeOut(line1), ApplyFunction(lambda a:a.fade(), x_comps))
+
+ self.play(ShowCreation(dpq[1]), ShowCreation(y_comps))
+ self.play(Indicate(dpq[1]))
+ self.wait(2)
+ self.play(ShowCreation(dq_text))
+ self.wait()
+ self.play(Uncreate(dq_text))
+
+ self.add(group_2.move_to(5*RIGHT+3*DOWN))
+ self.play(Write(line2),
+ y_value.set_value,4,
+ rate_func=linear,
+ run_time=3
+ )
+ self.wait(2)
+ self.play(ReplacementTransform(dpq, dp_dq), FadeOut(line2), ReplacementTransform(x_comps, vector_field), ReplacementTransform(y_comps, vector_field), FadeOut(group_2))
+
+ self.play(Indicate(dp_dq))
+ self.wait()
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file8_curl-paddle.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file8_curl-paddle.gif
new file mode 100644
index 0000000..41db451
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file8_curl-paddle.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file8_curl-paddle.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file8_curl-paddle.py
new file mode 100644
index 0000000..7a11992
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file8_curl-paddle.py
@@ -0,0 +1,55 @@
+from manimlib.imports import *
+
+def field_func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -y,
+ x,
+ 0
+ ])
+
+class Paddlewheel(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ #self.add(axes)
+ text = TextMobject("Insert the paddle into the flow of water").shift(3*DOWN).add_background_rectangle()
+ text_a = TextMobject("The rotation of the wheel is proportional to the component of curl in the direction of the axle").shift(3*DOWN).scale(0.7)
+
+ vec_field = VectorField(field_func, x_min =-4, x_max = 4, y_min =-4, y_max =4)
+
+ self.set_camera_orientation(phi=0*DEGREES,theta=0*DEGREES,distance=40)
+ lines_a = StreamLines(
+ field_func,
+ virtual_time=3,
+ min_magnitude=0,
+ max_magnitude=3,
+ ).set_color_by_gradient([WHITE, BLUE_E])
+ flow = AnimatedStreamLines(
+ lines_a,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ )
+
+ paddle = VGroup(Line(np.array([3, 0, 0]), np.array([-3, 0, 0])),
+ Line(np.array([0, 3, 0]), np.array([0, -3, 0]))).set_stroke(width = 8).set_color(YELLOW_E)
+ cylinder = ParametricSurface(
+ lambda u, v: np.array([
+ 0.1*np.cos(u),
+ 0.1*np.sin(u),
+ v,
+ ]),
+ u_min = 0, u_max = 2*np.pi, v_min = -0.2, v_max = 3.5, checkerboard_colors = [YELLOW_E, YELLOW_E]).fade(0.5)
+ plane = ParametricSurface(lambda u, v: np.array([u, v, 0]), checkerboard_colors = [WHITE, WHITE]).fade(0.9)
+
+ self.add(paddle, cylinder, flow)
+ self.add_fixed_in_frame_mobjects(text)
+ self.play(Rotating(paddle))
+ self.wait()
+ self.play(FadeIn(vec_field))
+ self.remove(flow, text)
+ self.bring_to_front(cylinder)
+ #self.play(Rotating(paddle))
+ self.wait()
+ self.add_fixed_in_frame_mobjects(text_a)
+ #self.play(ReplacementTransform(text, text_a))
+ self.move_camera(phi=60*DEGREES,theta=30*DEGREES)
+ self.wait()
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file9_formal-def.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file9_formal-def.gif
new file mode 100644
index 0000000..6247aea
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file9_formal-def.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file9_formal-def.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file9_formal-def.py
new file mode 100644
index 0000000..ecafca4
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and Div/DivCurl_file9_formal-def.py
@@ -0,0 +1,82 @@
+from manimlib.imports import *
+import numpy as np
+
+
+
+def func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ 1.9*np.cos(x+2*y),
+ 1.5*np.sin(x-2*y),
+ 0
+ ])
+
+def coord(x,y,z=0):
+ return np.array([x,y,z])
+
+class Instrument(Scene):
+ CONFIG = {
+ "x_coords": ([1, 2.2, 3.9, 3, -0, -0.2, 1]),
+ "y_coords": ([1.5, 1, -0.5, -2.0, -1.4, 0.5, 1.5]),
+ }
+
+ def setup(self):
+ self.tuples = list(zip(self.x_coords,self.y_coords))
+ dots = self.get_all_mobs()
+
+ def get_dots(self, coords):
+ dots = VGroup(*[Dot(coord(x,y)) for x,y in coords])
+ return dots
+
+ def get_all_mobs(self):
+ dots = self.get_dots(self.tuples)
+ return dots
+
+
+class Curl_one(MovingCameraScene, Instrument):
+ def setup(self):
+ MovingCameraScene.setup(self)
+ Instrument.setup(self)
+
+
+ def construct(self):
+ vec = VectorField(func)
+
+
+ frame_one = Circle(radius = 0.5).move_to(np.array([4, 2, 0]))
+ dot = Dot(frame_one.get_center()).scale(0.5)
+ surface = VMobject()
+ surface.set_points_smoothly([*[coord(x,y) for x,y in self.tuples]])
+ surface.move_to(dot.get_center()).set_stroke(width = 0.5)
+
+ label = TexMobject(r"A").scale(0.5).next_to(dot, LEFT+UP, buff = SMALL_BUFF)
+ #self.add(frame_one)
+ self.camera_frame.save_state()
+ self.play(
+ self.camera_frame.set_width,frame_one.get_width()*7.0,
+ self.camera_frame.move_to,frame_one)
+
+
+
+
+ self.add(vec, dot, label)
+ lines = StreamLines(
+ func,
+ virtual_time=7,
+ min_magnitude=0,
+ max_magnitude=8,
+ )
+ lines1 = AnimatedStreamLines(
+ lines,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ )
+
+ self.add(lines1)
+ self.wait(3)
+ self.play(Restore(self.camera_frame))
+ self.wait(2)
+ self.add(surface)
+ self.wait(3)
+ self.play(ApplyMethod(surface.scale, 0.01), run_time = 2)
+ self.remove(surface)
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file1_closed-loop.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file1_closed-loop.gif
new file mode 100644
index 0000000..87e5dd5
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file1_closed-loop.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file1_closed-loop.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file1_closed-loop.py
new file mode 100644
index 0000000..9211f0d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file1_closed-loop.py
@@ -0,0 +1,63 @@
+from manimlib.imports import *
+import numpy as np
+
+def div(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ x,
+ y,
+ 0
+ ])
+
+
+class Loop(Scene):
+ def get_pending(self,path,proportion,dx=0.01):
+ if proportion < 1:
+ coord_i = path.point_from_proportion(proportion)
+ coord_f = path.point_from_proportion(proportion+dx)
+ else:
+ coord_i = path.point_from_proportion(proportion-dx)
+ coord_f = path.point_from_proportion(proportion)
+ line = Line(coord_i,coord_f)
+ angle = line.get_angle()
+ return angle
+ def construct(self):
+
+
+
+ boundary = VMobject(stroke_color = "#F4EDED")
+ boundary.set_points_smoothly([np.array([-2, 1.8,0]),np.array([-1.6, 0.5,0]),np.array([-3.2, -1.2,0]),np.array([2.6, -1.5,0]),np.array([1, 0,0]),np.array([3.5,2.3, 0]), np.array([-2,1.8, 0])])
+ #c = TexMobject(r"C").next_to(surf,RIGHT+UP).set_color("#F4EDED")
+
+
+ text = TexMobject(r"\oint \vec F \cdot \vec dr", r" = 0").shift(3*DOWN).set_stroke(width = 1.5)
+ vec_field = VectorField(div)
+
+ start_angle = self.get_pending(boundary, 0)
+
+ pointer = Triangle(fill_opacity = 1).set_height(0.25).set_color(WHITE)
+ pointer.set_fill(WHITE)
+ pointer.move_to(boundary.get_start())
+ pointer.rotate(- PI / 2)
+ pointer.save_state()
+ pointer.rotate(start_angle, about_point=pointer.get_center())
+
+
+ self.play(ShowCreation(boundary), ShowCreation(vec_field))
+ self.wait()
+ self.play(Write(text[0]))
+ def update_rotate_move(mob,alpha):
+ pointer.restore()
+
+ angle = self.get_pending(boundary,alpha)
+
+ pointer.move_to(boundary.point_from_proportion(alpha))
+ pointer.rotate(angle, about_point=pointer.get_center())
+ self.play(
+ #self.camera_frame.scale,.25,
+ UpdateFromAlphaFunc(pointer,update_rotate_move),
+ run_time=3,
+ )
+ self.play(ShowCreation(text[1]))
+ self.play(Indicate(text))
+ self.wait()
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file2_curl-paddle.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file2_curl-paddle.gif
new file mode 100644
index 0000000..41db451
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file2_curl-paddle.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file2_curl-paddle.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file2_curl-paddle.py
new file mode 100644
index 0000000..7a11992
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file2_curl-paddle.py
@@ -0,0 +1,55 @@
+from manimlib.imports import *
+
+def field_func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -y,
+ x,
+ 0
+ ])
+
+class Paddlewheel(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ #self.add(axes)
+ text = TextMobject("Insert the paddle into the flow of water").shift(3*DOWN).add_background_rectangle()
+ text_a = TextMobject("The rotation of the wheel is proportional to the component of curl in the direction of the axle").shift(3*DOWN).scale(0.7)
+
+ vec_field = VectorField(field_func, x_min =-4, x_max = 4, y_min =-4, y_max =4)
+
+ self.set_camera_orientation(phi=0*DEGREES,theta=0*DEGREES,distance=40)
+ lines_a = StreamLines(
+ field_func,
+ virtual_time=3,
+ min_magnitude=0,
+ max_magnitude=3,
+ ).set_color_by_gradient([WHITE, BLUE_E])
+ flow = AnimatedStreamLines(
+ lines_a,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ )
+
+ paddle = VGroup(Line(np.array([3, 0, 0]), np.array([-3, 0, 0])),
+ Line(np.array([0, 3, 0]), np.array([0, -3, 0]))).set_stroke(width = 8).set_color(YELLOW_E)
+ cylinder = ParametricSurface(
+ lambda u, v: np.array([
+ 0.1*np.cos(u),
+ 0.1*np.sin(u),
+ v,
+ ]),
+ u_min = 0, u_max = 2*np.pi, v_min = -0.2, v_max = 3.5, checkerboard_colors = [YELLOW_E, YELLOW_E]).fade(0.5)
+ plane = ParametricSurface(lambda u, v: np.array([u, v, 0]), checkerboard_colors = [WHITE, WHITE]).fade(0.9)
+
+ self.add(paddle, cylinder, flow)
+ self.add_fixed_in_frame_mobjects(text)
+ self.play(Rotating(paddle))
+ self.wait()
+ self.play(FadeIn(vec_field))
+ self.remove(flow, text)
+ self.bring_to_front(cylinder)
+ #self.play(Rotating(paddle))
+ self.wait()
+ self.add_fixed_in_frame_mobjects(text_a)
+ #self.play(ReplacementTransform(text, text_a))
+ self.move_camera(phi=60*DEGREES,theta=30*DEGREES)
+ self.wait()
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file3_measure-curl.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file3_measure-curl.gif
new file mode 100644
index 0000000..4e6a7e8
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file3_measure-curl.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file3_measure-curl.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file3_measure-curl.py
new file mode 100644
index 0000000..e7a324d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file3_measure-curl.py
@@ -0,0 +1,82 @@
+from manimlib.imports import *
+
+def field_func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -y,
+ x,
+ 0
+ ])
+
+
+class LineIntegral(MovingCameraScene, Scene):
+ def setup(self):
+ MovingCameraScene.setup(self)
+ Scene.setup(self)
+
+ def get_pending(self,path,proportion,dx=0.01):
+ if proportion < 1:
+ coord_i = path.point_from_proportion(proportion)
+ coord_f = path.point_from_proportion(proportion+dx)
+ else:
+ coord_i = path.point_from_proportion(proportion-dx)
+ coord_f = path.point_from_proportion(proportion)
+ line = Line(coord_i,coord_f)
+ angle = line.get_angle()
+ return angle
+
+ def construct(self):
+
+ vector_field = VectorField(field_func)
+ vec_field_for_flow = VectorField(field_func, x_min = -1.5, x_max = 1.5, y_min = -1.5, y_max = 1.5)
+ flow_rep = StreamLines(
+ field_func,
+ virtual_time=4,
+ min_magnitude=0,
+ max_magnitude=2,
+ dt = 0.1,
+ x_min = -1, x_max = 1, y_min = -1, y_max = 1,
+ ).set_color_by_gradient([BLUE_E, TEAL, WHITE])
+ flow = AnimatedStreamLines(
+ flow_rep,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ )
+ boundary = Circle(radius = 2).set_color("#7FFF00")
+
+ start_angle = self.get_pending(boundary, 0)
+
+ pointer = Triangle(fill_opacity = 1).set_height(0.25).set_color("#ffff00")
+ pointer.set_fill("#ffff00")
+ pointer.move_to(boundary.get_start())
+ pointer.rotate(- PI / 2)
+ pointer.save_state()
+ pointer.rotate(start_angle, about_point=pointer.get_center())
+ sym_1 = TexMobject(r"\oint \vec F \cdot \vec dr").next_to(pointer, RIGHT, buff = SMALL_BUFF).scale(0.7).set_color("#ffff00").add_background_rectangle()
+ sym_2 = TexMobject(r"\nabla \times \vec F").scale(0.7).set_color(TEAL).add_background_rectangle()
+
+ self.play(ShowCreation(vector_field))
+ self.wait()
+ self.add(flow)
+ self.play(Write(boundary), Write(sym_2))
+ self.wait(2)
+ self.play(Write(pointer))
+ def update_rotate_move(mob,alpha):
+ pointer.restore()
+
+ angle = self.get_pending(boundary,alpha)
+
+ pointer.move_to(boundary.point_from_proportion(alpha))
+ pointer.rotate(angle, about_point=pointer.get_center())
+
+
+
+ self.play(
+ #self.camera_frame.scale,.25,
+ UpdateFromAlphaFunc(pointer,update_rotate_move),
+ run_time=3,
+ )
+ self.play(Write(sym_1))
+ self.wait()
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file4_vortex-streamplot.ipynb b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file4_vortex-streamplot.ipynb
new file mode 100644
index 0000000..81f17a5
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file4_vortex-streamplot.ipynb
@@ -0,0 +1,96 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/padmapriya/.local/lib/python3.6/site-packages/ipykernel_launcher.py:4: RuntimeWarning: invalid value encountered in true_divide\n",
+ " after removing the cwd from sys.path.\n",
+ "/home/padmapriya/.local/lib/python3.6/site-packages/ipykernel_launcher.py:5: RuntimeWarning: invalid value encountered in true_divide\n",
+ " \"\"\"\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 432x288 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "Y,X = np.mgrid[-10:10:.01, -10:10:.01]\n",
+ "U = -Y/(X**2 + Y**2)\n",
+ "V = X/(X**2 + Y**2)\n",
+ "plt.streamplot(X,Y, U,V, density=1)\n",
+ "plt.savefig('vortex_streamplot.png')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/padmapriya/.local/lib/python3.6/site-packages/ipykernel_launcher.py:4: RuntimeWarning: invalid value encountered in true_divide\n",
+ " after removing the cwd from sys.path.\n",
+ "/home/padmapriya/.local/lib/python3.6/site-packages/ipykernel_launcher.py:5: RuntimeWarning: invalid value encountered in true_divide\n",
+ " \"\"\"\n"
+ ]
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "Y,X = np.mgrid[-10:10:.01, -10:10:.01]\n",
+ "U = -Y/(X**2 + Y**2)\n",
+ "V = X/(X**2 + Y**2)\n",
+ "plt.quiver(X,Y, U,V)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file4_vortex-streamplot.png b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file4_vortex-streamplot.png
new file mode 100644
index 0000000..2a77f2d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file4_vortex-streamplot.png
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file5_connected-regions.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file5_connected-regions.gif
new file mode 100644
index 0000000..c7e5970
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file5_connected-regions.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file5_connected-regions.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file5_connected-regions.py
new file mode 100644
index 0000000..20972ee
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file5_connected-regions.py
@@ -0,0 +1,54 @@
+from manimlib.imports import *
+
+class Connected(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+
+ connected2D = Circle(radius = 2, fill_color = BLUE_E, fill_opacity = 0.8).set_color(BLUE_E)
+ connected2D_label = TextMobject("Two dimensional, simply connected").move_to(np.array([0, -3, 0])).set_color(YELLOW_E)
+
+ connected3D = Sphere(radius = 2, checkerboard_colors = [BLUE_E, BLUE_E], stroke_color = BLUE_E).fade(0.5)
+ connected3D_label = TextMobject("Three dimensional, simply connected").move_to(np.array([0, -3, 0])).set_color(YELLOW_E)
+
+ self.set_camera_orientation(phi = 0, theta = 0, distance = 40)
+
+ self.add(connected2D)
+ self.add_fixed_in_frame_mobjects(connected2D_label)
+ self.wait(2)
+ self.play(FadeOut(connected2D), FadeIn(connected3D))
+ self.play(FadeOut(connected2D_label))
+ self.add_fixed_in_frame_mobjects(connected3D_label)
+ self.move_camera(phi = 45*DEGREES, theta = 45*DEGREES)
+ self.begin_ambient_camera_rotation(rate=.2)
+ self.wait(2)
+
+
+
+class NotConnected(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+
+ Nconnected2D = Annulus(fill_color = BLUE_E, fill_opacity = 0.8).set_color(BLUE_E)
+ Nconnected2D_label = TextMobject("Two dimensional, not simply connected").move_to(np.array([0, -3, 0])).set_color(YELLOW_E)
+
+ Nconnected3D = ParametricSurface(lambda u, v: np.array([(2.5 + np.cos(v))*np.cos(u),
+ (2.5 + np.cos(v))*np.sin(u),
+ np.sin(v)]),
+ u_min = 0, u_max = 2*np.pi, v_min = 0, v_max = 2*np.pi,
+ checkerboard_colors = [BLUE_E, BLUE_E], stroke_color = BLUE_E).fade(0.5)
+ Nconnected3D_label = TextMobject("Three dimensional, not simply connected").move_to(np.array([0, -3, 0])).set_color(YELLOW_E)
+
+ self.set_camera_orientation(phi = 0, theta = 0, distance = 40)
+
+ self.play(ShowCreation(Nconnected2D))
+ self.add_fixed_in_frame_mobjects(Nconnected2D_label)
+ self.wait(2)
+ self.play(FadeOut(Nconnected2D), FadeIn(Nconnected3D))
+ self.play(FadeOut(Nconnected2D_label))
+ self.add_fixed_in_frame_mobjects(Nconnected3D_label)
+ self.move_camera(phi = 45*DEGREES, theta = 45*DEGREES)
+ self.begin_ambient_camera_rotation(rate=.2)
+ self.wait(2)
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file6_not-connected-regions.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file6_not-connected-regions.gif
new file mode 100644
index 0000000..db4c3d0
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file6_not-connected-regions.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file6_not-connected-regions.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file6_not-connected-regions.py
new file mode 100644
index 0000000..20972ee
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Curl and conservative fields/CurlTheorem_file6_not-connected-regions.py
@@ -0,0 +1,54 @@
+from manimlib.imports import *
+
+class Connected(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+
+ connected2D = Circle(radius = 2, fill_color = BLUE_E, fill_opacity = 0.8).set_color(BLUE_E)
+ connected2D_label = TextMobject("Two dimensional, simply connected").move_to(np.array([0, -3, 0])).set_color(YELLOW_E)
+
+ connected3D = Sphere(radius = 2, checkerboard_colors = [BLUE_E, BLUE_E], stroke_color = BLUE_E).fade(0.5)
+ connected3D_label = TextMobject("Three dimensional, simply connected").move_to(np.array([0, -3, 0])).set_color(YELLOW_E)
+
+ self.set_camera_orientation(phi = 0, theta = 0, distance = 40)
+
+ self.add(connected2D)
+ self.add_fixed_in_frame_mobjects(connected2D_label)
+ self.wait(2)
+ self.play(FadeOut(connected2D), FadeIn(connected3D))
+ self.play(FadeOut(connected2D_label))
+ self.add_fixed_in_frame_mobjects(connected3D_label)
+ self.move_camera(phi = 45*DEGREES, theta = 45*DEGREES)
+ self.begin_ambient_camera_rotation(rate=.2)
+ self.wait(2)
+
+
+
+class NotConnected(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+
+ Nconnected2D = Annulus(fill_color = BLUE_E, fill_opacity = 0.8).set_color(BLUE_E)
+ Nconnected2D_label = TextMobject("Two dimensional, not simply connected").move_to(np.array([0, -3, 0])).set_color(YELLOW_E)
+
+ Nconnected3D = ParametricSurface(lambda u, v: np.array([(2.5 + np.cos(v))*np.cos(u),
+ (2.5 + np.cos(v))*np.sin(u),
+ np.sin(v)]),
+ u_min = 0, u_max = 2*np.pi, v_min = 0, v_max = 2*np.pi,
+ checkerboard_colors = [BLUE_E, BLUE_E], stroke_color = BLUE_E).fade(0.5)
+ Nconnected3D_label = TextMobject("Three dimensional, not simply connected").move_to(np.array([0, -3, 0])).set_color(YELLOW_E)
+
+ self.set_camera_orientation(phi = 0, theta = 0, distance = 40)
+
+ self.play(ShowCreation(Nconnected2D))
+ self.add_fixed_in_frame_mobjects(Nconnected2D_label)
+ self.wait(2)
+ self.play(FadeOut(Nconnected2D), FadeIn(Nconnected3D))
+ self.play(FadeOut(Nconnected2D_label))
+ self.add_fixed_in_frame_mobjects(Nconnected3D_label)
+ self.move_camera(phi = 45*DEGREES, theta = 45*DEGREES)
+ self.begin_ambient_camera_rotation(rate=.2)
+ self.wait(2)
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file1_analogy.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file1_analogy.gif
new file mode 100644
index 0000000..6023f9f
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file1_analogy.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file1_analogy.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file1_analogy.py
new file mode 100644
index 0000000..78bffa9
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file1_analogy.py
@@ -0,0 +1,77 @@
+from manimlib.imports import *
+import numpy as np
+# granny smith apple
+#misty moss
+
+class Analogue(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes().set_color("#EBF2FA")
+
+ hills_2D = ParametricFunction(
+ lambda t: np.array([
+ 0,
+ t,
+ -((1/1.02)*t**2)
+ ]),t_min= -2.5,t_max=2.5).set_color("#679436")
+
+ hills_2D_a = ParametricFunction(
+ lambda t: np.array([
+ 0,
+ t,
+ -((1/1.02)*t**2)
+ ]),t_min= 0,t_max=2.5).set_color("#679436")
+
+
+ hills_3D = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ -(u**2 + v**2)
+ ]),u_min=-2.5,u_max=2.5, v_min=-2.5,v_max=2.5, checkerboard_colors = ["#679436", "#679436"], stroke_color = "#679436").fade(0.7)
+
+ hills_2D_b = ParametricFunction(
+ lambda t: np.array([
+ t,
+ 0,
+ -((1/1.02)*t**2)
+ ]),t_min= 0,t_max=2.5).set_color("#FFCAB1")
+
+
+ hills = VGroup(hills_2D_a, hills_3D, hills_2D_b, hills_2D).move_to(np.array([0,0,-3.8]))
+ ball = Sphere(radius = 0.08).set_color("#28666E")
+
+
+ path_one = DashedVMobject(hills_2D_a).set_stroke(width = 0.9).set_color("#F0C808")
+ path_two = DashedVMobject(hills_2D_b).set_stroke(width = 0.9).set_color("#F0C808")
+
+ text_a = TexMobject(r"\textit{In the case of a one dimensional hill, }" ,r"\textit{the ball moves along a single path}").set_color("#EBF2FA").scale(0.5).move_to(np.array([-1.5, 2.7, 0]))
+ text_b = TexMobject(r"\textit{In higher dimensions,}", r"\textit{ there is more than one direction}", r"\textit{the ball can roll in}").set_color("#EBF2FA").scale(0.5).move_to(np.array([-1.5, 2.6, 0]))
+ text_a[1].next_to(text_a[0], DOWN, buff = SMALL_BUFF)
+ text_b[1].next_to(text_b[0], DOWN, buff = SMALL_BUFF)
+ text_b[2].next_to(text_b[1], DOWN, buff = SMALL_BUFF)
+ text_b[0].set_color("#28666E")
+
+
+
+
+
+
+
+
+
+
+
+ self.set_camera_orientation(phi=90*DEGREES,theta=180*DEGREES,distance=40)
+ self.add(axes)
+ self.add_fixed_in_frame_mobjects(text_a)
+ self.play(ShowCreation(hills_2D), ShowCreation(text_a))
+ self.play(MoveAlongPath(ball,hills_2D_a),run_time = 2.5)
+ self.wait()
+ self.play(FadeIn(hills_3D), FadeOut(hills_2D), FadeOut(text_a))
+ self.move_camera(phi=45*DEGREES,theta=45*DEGREES)
+ self.add_fixed_in_frame_mobjects(text_b)
+ self.begin_ambient_camera_rotation(rate=0.05)
+ self.play(MoveAlongPath(ball, hills_2D_a), ShowCreation(path_one), run_time = 2.5)
+ self.wait()
+ self.play(FadeOut(path_one), MoveAlongPath(ball, hills_2D_b), ShowCreation(path_two), run_time = 2.5)
+ self.wait() \ No newline at end of file
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file2_input-output.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file2_input-output.gif
new file mode 100644
index 0000000..1304929
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file2_input-output.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file2_input-output.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file2_input-output.py
new file mode 100644
index 0000000..b02e60b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file2_input-output.py
@@ -0,0 +1,136 @@
+from manimlib.imports import *
+import numpy as np
+
+
+def function(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ 0.4*(-x*np.sin((x**2+y**2)))/1*(x**2 + y**2),
+ 0.4*(-y*np.sin((x**2+y**2)))/1*(x**2 + y**2),
+ 0,
+ ])
+
+
+def function_two(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ 6*x*y/(x**2+y**2+1)**2,
+ -3*(x**2 -y**2 +1)/(x**2+y**2+1)**2,
+ 0,
+ ])
+
+def function_three(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ np.exp(x)*np.cos(y),
+ -np.exp(x)*np.sin(y),
+ 0,
+ ])
+
+
+class Second(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+ self.set_camera_orientation(phi=45*DEGREES,theta=60*DEGREES,distance=40)
+ self.begin_ambient_camera_rotation(rate=0.05)
+
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ 0.4*u,
+ 0.4*v,
+ 0.4*np.cos(np.sqrt((u**2)+(v**2)))
+ ]),u_min=-10,u_max=10, v_min=-10,v_max=10, checkerboard_colors = (["#1C6E8C", "#1C6E8C"]), stroke_color = "#1C6E8C").fade(0.7)
+
+ text_func = TexMobject(r"\textbf{Input: Function}").shift(4.4*LEFT+3.3*UP).scale(0.7).set_stroke(width = 1.2)
+ text_field = TexMobject(r"\textbf{Output: Vector Field}").shift(4.4*LEFT+3.3*UP).scale(0.7).set_stroke(width = 1.2)
+ field = VectorField(function, x_min = -4, x_max = 4, y_min = -4, y_max = 4, colors = (["#CC2936", "#4D8B31","#FFAD05"]))
+
+
+ self.add_fixed_in_frame_mobjects(text_func)
+ self.play(ShowCreation(surface))
+ self.wait(3)
+ self.stop_ambient_camera_rotation()
+ self.move_camera(phi=0*DEGREES, theta=0*DEGREES)
+
+ self.play(FadeIn(field),FadeOut(text_func))
+ self.add_fixed_in_frame_mobjects(text_field)
+ self.wait()
+ self.play(FadeOut(surface), FadeOut(axes))
+ self.wait()
+
+
+class Third(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+ self.set_camera_orientation(phi=45*DEGREES,theta=60*DEGREES,distance=40)
+ self.begin_ambient_camera_rotation(rate=0.2)
+
+
+
+
+ surface_two = ParametricSurface(
+ lambda x, y: np.array([
+ x,
+ y,
+ -3*y/(x**2+y**2+1)
+ ]),u_min=-2,u_max=2, v_min=-2,v_max=2).set_color(BLUE_E).fade(0.7).scale(1.7)
+
+ text_func = TexMobject(r"f = \frac{-3y}{x^{2} + y^{2} +1}").shift(4.8*LEFT+3*UP).scale(0.7)
+ text_field = TexMobject(r"\nabla", r"f = \begin{bmatrix}\frac{\partial f}{\partial x}\\\frac{\partial f}{\partial y}\end{bmatrix}").shift(4.8*LEFT+3*UP).scale(0.7)
+ text_field_a = TexMobject(r"\nabla", r" f = \begin{bmatrix} \frac{6xy}{(x^{2} + y^{2} + 1)^{2}}\\-3\frac{x^{2} - y^{2} + 1}{(x^{2} + y^{2} + 1)^{2}}\end{bmatrix}").shift(4.8*LEFT+3*UP).scale(0.7)
+
+ field_two = VectorField(function_two, x_min = -3, x_max = 3, y_min = -3, y_max = 3, colors = (["#CC2936", "#4D8B31","#FFAD05"]))
+ text_field[0].set_color("#CC2936")
+ text_field_a[0].set_color("#CC2936")
+
+
+
+ self.add_fixed_in_frame_mobjects(text_func)
+ self.play(ShowCreation(surface_two))
+ self.wait(3)
+ self.stop_ambient_camera_rotation()
+ self.move_camera(phi=0*DEGREES, theta=0*DEGREES)
+
+ self.play(FadeIn(field_two),FadeOut(text_func))
+ self.add_fixed_in_frame_mobjects(text_field)
+ self.wait()
+ self.play(FadeOut(surface_two))
+ self.wait()
+
+
+
+class Fourth(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+ self.set_camera_orientation(phi=45*DEGREES,theta=60*DEGREES,distance=100)
+ self.begin_ambient_camera_rotation(rate=0.2)
+
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ np.exp(u)*np.cos(v)
+ ]),u_min=-3,u_max=3, v_min=-3,v_max=3).set_color(BLUE_E).fade(0.7)
+
+ text_func = TexMobject(r"\textbf{Input: Function}").shift(4.4*LEFT+3.3*UP).scale(0.7)
+ text_field = TexMobject(r"\textbf{Output: Vector Field}").shift(4.4*LEFT+3.3*UP).scale(0.7)
+ field = VectorField(function_three, x_min = -3, x_max = 3, y_min = -3, y_max = 3)
+
+
+ self.add_fixed_in_frame_mobjects(text_func)
+ self.play(ShowCreation(surface))
+ self.wait(3)
+
+ self.stop_ambient_camera_rotation()
+ self.move_camera(phi=0*DEGREES, theta=0*DEGREES)
+
+ self.play(FadeIn(field),FadeOut(text_func))
+ self.add_fixed_in_frame_mobjects(text_field)
+ self.wait()
+ self.add_fixed_in_frame_mobjects(text_field_a)
+ self.play(ReplacementTransform(text_field, text_field_a))
+ self.play(FadeOut(surface))
+ self.wait() \ No newline at end of file
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file3_input-output2.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file3_input-output2.gif
new file mode 100644
index 0000000..225d9d5
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file3_input-output2.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file3_input-output2.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file3_input-output2.py
new file mode 100644
index 0000000..b02e60b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file3_input-output2.py
@@ -0,0 +1,136 @@
+from manimlib.imports import *
+import numpy as np
+
+
+def function(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ 0.4*(-x*np.sin((x**2+y**2)))/1*(x**2 + y**2),
+ 0.4*(-y*np.sin((x**2+y**2)))/1*(x**2 + y**2),
+ 0,
+ ])
+
+
+def function_two(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ 6*x*y/(x**2+y**2+1)**2,
+ -3*(x**2 -y**2 +1)/(x**2+y**2+1)**2,
+ 0,
+ ])
+
+def function_three(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ np.exp(x)*np.cos(y),
+ -np.exp(x)*np.sin(y),
+ 0,
+ ])
+
+
+class Second(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+ self.set_camera_orientation(phi=45*DEGREES,theta=60*DEGREES,distance=40)
+ self.begin_ambient_camera_rotation(rate=0.05)
+
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ 0.4*u,
+ 0.4*v,
+ 0.4*np.cos(np.sqrt((u**2)+(v**2)))
+ ]),u_min=-10,u_max=10, v_min=-10,v_max=10, checkerboard_colors = (["#1C6E8C", "#1C6E8C"]), stroke_color = "#1C6E8C").fade(0.7)
+
+ text_func = TexMobject(r"\textbf{Input: Function}").shift(4.4*LEFT+3.3*UP).scale(0.7).set_stroke(width = 1.2)
+ text_field = TexMobject(r"\textbf{Output: Vector Field}").shift(4.4*LEFT+3.3*UP).scale(0.7).set_stroke(width = 1.2)
+ field = VectorField(function, x_min = -4, x_max = 4, y_min = -4, y_max = 4, colors = (["#CC2936", "#4D8B31","#FFAD05"]))
+
+
+ self.add_fixed_in_frame_mobjects(text_func)
+ self.play(ShowCreation(surface))
+ self.wait(3)
+ self.stop_ambient_camera_rotation()
+ self.move_camera(phi=0*DEGREES, theta=0*DEGREES)
+
+ self.play(FadeIn(field),FadeOut(text_func))
+ self.add_fixed_in_frame_mobjects(text_field)
+ self.wait()
+ self.play(FadeOut(surface), FadeOut(axes))
+ self.wait()
+
+
+class Third(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+ self.set_camera_orientation(phi=45*DEGREES,theta=60*DEGREES,distance=40)
+ self.begin_ambient_camera_rotation(rate=0.2)
+
+
+
+
+ surface_two = ParametricSurface(
+ lambda x, y: np.array([
+ x,
+ y,
+ -3*y/(x**2+y**2+1)
+ ]),u_min=-2,u_max=2, v_min=-2,v_max=2).set_color(BLUE_E).fade(0.7).scale(1.7)
+
+ text_func = TexMobject(r"f = \frac{-3y}{x^{2} + y^{2} +1}").shift(4.8*LEFT+3*UP).scale(0.7)
+ text_field = TexMobject(r"\nabla", r"f = \begin{bmatrix}\frac{\partial f}{\partial x}\\\frac{\partial f}{\partial y}\end{bmatrix}").shift(4.8*LEFT+3*UP).scale(0.7)
+ text_field_a = TexMobject(r"\nabla", r" f = \begin{bmatrix} \frac{6xy}{(x^{2} + y^{2} + 1)^{2}}\\-3\frac{x^{2} - y^{2} + 1}{(x^{2} + y^{2} + 1)^{2}}\end{bmatrix}").shift(4.8*LEFT+3*UP).scale(0.7)
+
+ field_two = VectorField(function_two, x_min = -3, x_max = 3, y_min = -3, y_max = 3, colors = (["#CC2936", "#4D8B31","#FFAD05"]))
+ text_field[0].set_color("#CC2936")
+ text_field_a[0].set_color("#CC2936")
+
+
+
+ self.add_fixed_in_frame_mobjects(text_func)
+ self.play(ShowCreation(surface_two))
+ self.wait(3)
+ self.stop_ambient_camera_rotation()
+ self.move_camera(phi=0*DEGREES, theta=0*DEGREES)
+
+ self.play(FadeIn(field_two),FadeOut(text_func))
+ self.add_fixed_in_frame_mobjects(text_field)
+ self.wait()
+ self.play(FadeOut(surface_two))
+ self.wait()
+
+
+
+class Fourth(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+ self.set_camera_orientation(phi=45*DEGREES,theta=60*DEGREES,distance=100)
+ self.begin_ambient_camera_rotation(rate=0.2)
+
+ surface = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ np.exp(u)*np.cos(v)
+ ]),u_min=-3,u_max=3, v_min=-3,v_max=3).set_color(BLUE_E).fade(0.7)
+
+ text_func = TexMobject(r"\textbf{Input: Function}").shift(4.4*LEFT+3.3*UP).scale(0.7)
+ text_field = TexMobject(r"\textbf{Output: Vector Field}").shift(4.4*LEFT+3.3*UP).scale(0.7)
+ field = VectorField(function_three, x_min = -3, x_max = 3, y_min = -3, y_max = 3)
+
+
+ self.add_fixed_in_frame_mobjects(text_func)
+ self.play(ShowCreation(surface))
+ self.wait(3)
+
+ self.stop_ambient_camera_rotation()
+ self.move_camera(phi=0*DEGREES, theta=0*DEGREES)
+
+ self.play(FadeIn(field),FadeOut(text_func))
+ self.add_fixed_in_frame_mobjects(text_field)
+ self.wait()
+ self.add_fixed_in_frame_mobjects(text_field_a)
+ self.play(ReplacementTransform(text_field, text_field_a))
+ self.play(FadeOut(surface))
+ self.wait() \ No newline at end of file
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file4_why-partials.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file4_why-partials.gif
new file mode 100644
index 0000000..048fd8d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file4_why-partials.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file4_why-partials.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file4_why-partials.py
new file mode 100644
index 0000000..a46ea32
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file4_why-partials.py
@@ -0,0 +1,66 @@
+from manimlib.imports import *
+import numpy as np
+
+
+def function(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ x,
+ y,
+ 0,
+ ])
+def x_dir(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ x,
+ 0,
+ 0
+ ])
+
+def y_dir(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ 0,
+ y,
+ 0,
+ ])
+
+
+class PartialDerivatives(MovingCameraScene):
+ def setup(self):
+ MovingCameraScene.setup(self)
+
+ def construct(self):
+ dot = Dot().move_to(np.array([2.5,2,0]))
+
+ self.camera_frame.save_state()
+ self.play(
+ self.camera_frame.set_width,dot.get_width()*35,
+ self.camera_frame.move_to,dot)
+
+ dx = TexMobject(r"\frac{\partial f}{\partial x}").move_to(np.array([4,2.5, 0])).set_color(["#00635D", BLUE_E]).scale(0.5)
+ x_aros = VectorField(x_dir, x_min = 0.5, x_max = 3, y_min = 0.5, y_max =3).set_color(["#00635D", BLUE_E])
+
+ dy = TexMobject(r"\frac{\partial f}{\partial y}").move_to(np.array([4,1.5, 0])).set_color_by_gradient(["#BAAB68", WHITE]).scale(0.5)
+ y_aros = VectorField(y_dir, y_min = 0.5, y_max =3, x_min = 0.5, x_max = 3 ).set_color_by_gradient(["#BAAB68", WHITE])
+
+ partials = VGroup(x_aros, y_aros, dx, dy)
+
+ dxdy = VectorField(function, y_min = 0.5, y_max =3, x_min = 0.5, x_max = 3 ).set_color_by_gradient(["#BAAB68", "#00635D"])
+ field = VectorField(function, y_min = -3, y_max =3, x_min = -3, x_max = 3 ).set_color_by_gradient(["#BAAB68", "#00635D"])
+ vector = TexMobject(r"\nabla f =").set_color_by_gradient(["#BAAB68", "#00635D"]).move_to(np.array([4,2, 0])).scale(0.5)
+ threed = TexMobject(r"\textit{With respect to the function, the gradient is computed by...}").scale(0.3).move_to(dot.get_center())
+
+
+
+ self.play(Write(x_aros), Write(dx))
+ self.wait()
+ self.play(Write(y_aros), Write(dy))
+ self.wait()
+ self.play(Write(dxdy), Write(vector), ApplyMethod(dx.next_to,vector, RIGHT+0.3*UP), ApplyMethod(dy.next_to, vector, RIGHT+0.3*DOWN))
+ self.wait()
+ self.play(FadeOut(x_aros), FadeOut(dx), FadeOut(vector), FadeOut(dxdy), FadeOut(y_aros), FadeOut(dy), ShowCreation(threed))
+ self.wait(2)
+ self.play(Uncreate(threed))
+
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file5_contour-lines-and-map.ipynb b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file5_contour-lines-and-map.ipynb
new file mode 100644
index 0000000..bd716ab
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file5_contour-lines-and-map.ipynb
@@ -0,0 +1,104 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%matplotlib inline\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.style.use('dark_background')\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def f(x, y):\n",
+ " return 5*np.sin(x)**15 + 20* np.cos(x/y) * np.sin(y-x)\n",
+ "# np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/padmapriya/.local/lib/python3.6/site-packages/ipykernel_launcher.py:2: RuntimeWarning: divide by zero encountered in true_divide\n",
+ " \n",
+ "/home/padmapriya/.local/lib/python3.6/site-packages/ipykernel_launcher.py:2: RuntimeWarning: invalid value encountered in true_divide\n",
+ " \n",
+ "/home/padmapriya/.local/lib/python3.6/site-packages/ipykernel_launcher.py:2: RuntimeWarning: invalid value encountered in cos\n",
+ " \n"
+ ]
+ }
+ ],
+ "source": [
+ "x = np.linspace(0, 8, 20)\n",
+ "y = np.linspace(0, 6, 15)\n",
+ "\n",
+ "X, Y = np.meshgrid(x, y)\n",
+ "Z = f(X, Y)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 432x288 with 1 Axes>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "a = plt.contourf(X, Y, Z, colors=None, cmap = 'gist_earth')\n",
+ "b = plt.contour(X, Y, Z, colors=None, cmap = 'gist_earth')\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file5_contour-lines-and-map.png b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file5_contour-lines-and-map.png
new file mode 100644
index 0000000..dcd4493
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file5_contour-lines-and-map.png
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file6_surf-contour-plot.ipynb b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file6_surf-contour-plot.ipynb
new file mode 100644
index 0000000..9bc29be
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file6_surf-contour-plot.ipynb
@@ -0,0 +1,171 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "numpy: 1.15.0\n",
+ "matplotlib: 3.2.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "print('numpy: '+np.version.full_version)\n",
+ "import matplotlib.pyplot as plt\n",
+ "from mpl_toolkits.mplot3d import Axes3D \n",
+ "import matplotlib.animation as animation\n",
+ "import matplotlib\n",
+ "print('matplotlib: '+matplotlib.__version__)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 720x576 with 1 Axes>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "<Figure size 432x288 with 0 Axes>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "plt.style.use('dark_background')\n",
+ "fig = plt.figure(figsize = (10,8))\n",
+ "ax = fig.add_subplot(111, projection=\"3d\")\n",
+ "ax.xaxis.set_pane_color((1.0, 1.0, 0.0, 0.0))\n",
+ "ax.yaxis.set_pane_color((1.0, 1.0, 0.0, 0.0))\n",
+ "ax.zaxis.set_pane_color((1.0, 0.0, 0.0, 0.0))\n",
+ "\n",
+ "ax.zaxis._axinfo[\"grid\"]['color'] = (1,1,1,0)\n",
+ "ax.xaxis._axinfo[\"grid\"]['color'] = (1,1,1,0)\n",
+ "ax.yaxis._axinfo[\"grid\"]['color'] = (1,1,1,0)\n",
+ "x, y = np.mgrid[-1:1:30j, -1:1:30j]\n",
+ "z = np.cos(np.pi*x)*np.cos(np.pi*y)\n",
+ "ax.plot_surface(x, y, z+1, cmap=\"gist_earth\", lw=0.5, rstride=1, cstride=1, alpha = 0.8)\n",
+ "ax.contour(x, y, z, 10, cmap=\"gist_earth\", linestyles=\"solid\", offset=-1)\n",
+ "#ax.contour(x, y, z, 3, lw=-10, colors=\"k\", linestyles=\"solid\", offset=-1)\n",
+ "plt.show()\n",
+ "plt.savefig('sc.png')\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 43,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/padmapriya/.local/lib/python3.6/site-packages/ipykernel_launcher.py:6: UserWarning: The following kwargs were not used by contour: 'lw'\n",
+ " \n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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JSWyQFRgYCD33Xcf58+fZ/ny5Xz7299GpVKh0WhISEjwKf64nURquhO3tdEdPHgwLpeL119/nWeeeaZDo9tVdnXjxo1s3ryZjRs3snbtWk6fPs1rr712C77JrcWyZctISEhg/fr1DBo0iIkTJ/qIwBcVFcm0teuVpQwICGDWrFmEhYWxZ88edDqdbIg98eebaYukUqmYPn06/fv359133+1US8JfdKQKZzKZUKvVpKWlcfr06XYC4TeL0aNHM2nSJHbs2OF3sYJKpeL+++9n0KBBnD59GpVKRWNjoxxe6A74w0x44oknWLBgAf379yc4OJji4mJGjBjBH/7wB+bOncvgwYPZt28f48ePl1u6X716leTk5NtKpKY7cVsbXQ8OHDjQqdHtavlTWloqS9u1Pe7rhKCgoA69WovFQmJiokxb69OnDw6Hg+LiYgoLC2W1tc4SVB7ZyK4STTfTFqlv374sWLCAEydO8Mknn3R7oiwiIoKUlBSys7O5cOECkZGRsqfp6RriXYBwvcUGnuowj/fs7wMtJCSEe+65h/z8fJYuXSrrEgQGBlJXV9dtRQ/+hA527drFihUrOHLkCEqlkqKiIkJCQtod633c1x13fCKtM6ENq9VKVVUVQUFBbNy4kf79+xMSEoLJZGqXuEhMTOS3v/2tvD148GCWLFnCu+++y9tvv01CQoJM//nmN7/J6dOnv5wv103oLIxQUVHB5s2b2bx5s7yvX79+TJ8+nalTp5KUlERoaCg1NTUUFxeTn59PVlYWZrOZmTNnUlZWxhtvvNEle6KiooKKigr5mnm3RZowYQIRERE4nc52spfz589Hr9ezfv16vxNN/kKlUpGUlERsbCybN2+WaWa5ubkyJU+j0chGOCkpiZCQEOx2u+yxe+QRO4IkSXJsOzU19broXImJicTHx7NixQrWrl3r81p3hmvAP5Ea72OcTifV1dVYrVaioqJ8DOztLlLTnfjKG929e/fKrUe88dOf/pRt27bd9PmXL1/Ovn37+Na3vsXx48dZvny5/JT24ODBg4waNQpweydZWVns2bNHfv2///u/7/jgvwfZ2dlkZ2fzxhtvAG4D5RGBnzp1Kt///vcJCgqiuLgYu91ObGxslyLwbeFd3eVt4Dzx4QceeICIiAhKS0u5cOECEREROByOblPEio2Nlb3n119/vVOvsbm5WRYw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\n",
+ "text/plain": [
+ "<Figure size 432x288 with 1 Axes>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(111, projection=\"3d\")\n",
+ "x, y = np.mgrid[-1:1:30j, -1:1:30j]\n",
+ "z = 5*np.sin(x)**15 + 20* np.cos(x/y) * np.sin(y-x)\n",
+ "ax.plot_surface(x, y, z, cmap=\"gist_earth\", lw=0.5, rstride=1, cstride=1)\n",
+ "ax.contour(x, y, z, 10, lw=3, cmap=\"gist_earth\", linestyles=\"solid\", offset=-1)\n",
+ "#ax.contour(x, y, z, 10, lw=3, colors=\"k\", linestyles=\"solid\")\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "NameError",
+ "evalue": "name 'plt' is not defined",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m<ipython-input-2-a500c398b7a3>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfig\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfigure\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0max\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_subplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m111\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mprojection\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"3d\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmgrid\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m30j\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m30j\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mz\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m5\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0;36m15\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m20\u001b[0m\u001b[0;34m*\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcos\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0max\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot_surface\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mz\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcmap\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"gist_earth\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlw\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m50\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrstride\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcstride\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;31mNameError\u001b[0m: name 'plt' is not defined"
+ ]
+ }
+ ],
+ "source": [
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(111, projection=\"3d\")\n",
+ "x, y = np.mgrid[-1:1:30j, -1:1:30j]\n",
+ "z = 5*np.sin(x)**15 + 20* np.cos(x/y) * np.sin(y-x)\n",
+ "ax.plot_surface(x, y, z, cmap=\"gist_earth\", lw=50, rstride=1, cstride=1)\n",
+ "ax.contour(x, y, z, 10, lw=30, cmap=\"gist_earth\", linestyles=\"solid\", offset=-1)\n",
+ "ax.contour(x, y, z, 10, lw=3, colors=\"k\", linestyles=\"solid\")\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file6_surf-contour-plot.png b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file6_surf-contour-plot.png
new file mode 100644
index 0000000..4488051
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file6_surf-contour-plot.png
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file7_missile.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file7_missile.py
new file mode 100644
index 0000000..aa62909
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file7_missile.py
@@ -0,0 +1,45 @@
+from manimlib.imports import *
+import numpy as np
+
+
+def function(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ np.sin(x-y),
+ np.exp(y),
+ 0
+ ])
+def func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -2*x,
+ y,
+ 0])
+
+class Missiles(GraphScene):
+ def construct(self):
+
+ field = VectorField(function)
+ #path = ParametricFunction(lambda x: -2*x)
+
+ dot = SVGMobject("miss").move_to(DL).scale(0.09).set_color(WHITE).rotate(PI/4 + PI)
+ path = ArcBetweenPoints(dot.get_center(), UP+0.2*LEFT)
+
+ toggle = Rectangle(width = 7, height = 0.5, fill_color = [BLUE_E, '#BCD2FF', '#FFD5B3', '#FF9225', '#FF6C00'], fill_opacity = 1).rotate(90*DEGREES).shift(6*RIGHT).set_stroke(width = 0.2)
+ guide = Triangle(color = WHITE, fill_color = WHITE, fill_opacity = 1).scale(0.3).rotate(90*DEGREES).move_to(toggle.get_center(), RIGHT+DOWN).shift(0.6*RIGHT + 3*DOWN)
+ #self.add(toggle, guide)
+ path_guide_one = Line(np.array([6.4, -3, 0]), np.array([6.4, 1, 0]))
+ path_guide_two = Line(np.array([6.4, 1, 0]), np.array([6.4, 3, 0]))
+ label = TexMobject(r"\textit{temperature in }",r"\textrm{ K}").next_to(toggle, DOWN).scale(0.5).shift(0.2*UP)
+
+ self.play(FadeIn(field))
+ self.wait()
+ self.bring_to_front(toggle, guide, label)
+ self.play(FadeIn(dot))
+ self.wait()
+ self.play(MoveAlongPath(dot, path), MoveAlongPath(guide, path_guide_one))
+ self.play(ApplyMethod(dot.rotate, PI/4),rate = 0.1)
+ self.play(ApplyMethod(dot.move_to, 3.5*UP), MoveAlongPath(guide, path_guide_two), rate = 0.3)
+ #self.play(ApplyMethod(dot.move_to, 3.5*UP))
+ #self.add_fixed_in_frame_mobjects(text_field)
+ self.wait() \ No newline at end of file
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file7_missiles.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file7_missiles.gif
new file mode 100644
index 0000000..4dc5596
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file7_missiles.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file8_fluid-flow.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file8_fluid-flow.gif
new file mode 100644
index 0000000..19562a2
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file8_fluid-flow.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file8_fluid-flow.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file8_fluid-flow.py
new file mode 100644
index 0000000..02a348d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Gradient/Gradient_file8_fluid-flow.py
@@ -0,0 +1,27 @@
+from manimlib.imports import *
+
+
+def funk(x,y):
+ x,y = coordinate[:2]
+ return np.array([
+ np.sin(x)**np.cos(y),
+ np.sin(y)**np.cos(x),
+ 0
+ ])
+
+class Fluid(Scene):
+ def construct(self):
+ vf = VectorField(funk).fade(0.5)
+ self.add(vf)
+ self.wait()
+ lines = StreamLines(
+ funk,
+ virtual_time=3,
+ min_magnitude=0,
+ max_magnitude=2,
+ )
+ self.add(AnimatedStreamLines(
+ lines,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ ))
+ self.wait(3)
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file1_ftc-analogue.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file1_ftc-analogue.gif
new file mode 100644
index 0000000..1101a96
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file1_ftc-analogue.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file1_ftc-analogue.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file1_ftc-analogue.py
new file mode 100644
index 0000000..222663b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file1_ftc-analogue.py
@@ -0,0 +1,265 @@
+from manimlib.imports import *
+
+
+def vector_field_func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ x,
+ y,
+ 0
+ ])
+def curl(coordinate):
+ x,y = coordinate[:2]
+ U = (x**2 + y**2)
+ return np.array([
+ -y/(x**2 + y**2),
+ x/(x**2 + y**2),
+ 0
+ ])
+
+
+
+
+
+class GreensVisual(Scene):
+
+ def construct(self):
+ axes_config = {"x_min": -6,
+ "x_max": 6,
+ "y_min": -6,
+ "y_max": 6,
+ "z_axis_config": {},
+ "z_min": -1,
+ "z_max": 1,
+ "z_normal": DOWN,
+ "light_source": 9 * DOWN + 7 * LEFT + 10 * OUT,
+ "number_line_config": {
+ "include_tip": False,
+ },
+ }
+
+ axes = Axes(**axes_config)
+
+ field = VectorField(vector_field_func).fade(0.5)
+ self.add(field)
+
+ title = TexMobject(r"\textit{According to Green's Theorem, }").shift(3*UP)
+
+ eq1 = TexMobject(r"\int_{C} \vec F . dr = \int \int_{D} \nabla \times \vec F dA").shift(3*DOWN)
+ eq5 = TexMobject(r"\int_{C} \vec F . dr = \int \int_{D} \nabla \times \vec F dA").shift(3*DOWN)
+
+ generalisation = TexMobject()
+
+ eq2 = TexMobject(r"\int_{C} \vec F . dr = \int_{C_1} \vec F . dr + \int_{C_{2}} \vec F . dr").shift(3*DOWN)
+ eq3 = TexMobject(r"\int_{C} \vec F . dr = \int_{C_{1}} \vec F . dr + \int_{C_{2}} \vec F . dr + \int_{C_{3}} \vec F . dr + \int_{C_{4}} \vec F . dr...").shift(3*DOWN)
+ eq4 = TexMobject(r"\int_{C_{r}} \vec F dr \approx \int\int_{D} \nabla \times \vec F dA").shift(3*DOWN)
+ eq = TexMobject(r"\int_{C_{r}} \textit{macroscopic curl} = \int\int_{D} \text{sum of all microscopic curls}").shift(3*UP)
+
+ text_1 = TexMobject(r"\textit{Split C into 2 parts and calculate curl of each one of the smaller regions seperately}").shift(3*UP)
+ #text_2 = TexMobject(r"\textit{}").shift(3*UP)
+ text_3 = TexMobject(r"\textit{By splitting C into n segments, the area of each region approaches the limit 0}", r"\textit{The macroscopic circulation along the curve }", r"\textit{is equivalent to the sum of microscopic circulation of all these small regions }")
+ text_3[0].move_to(3.8*UP)
+ text_3[1].set_color(YELLOW_E).next_to(text_3[0], DOWN, buff = SMALL_BUFF)
+ text_3[2].set_color(BLUE_E).next_to(text_3[1], DOWN, buff = SMALL_BUFF)
+
+
+
+ curl_rep_1 = StreamLines(
+ curl,
+ virtual_time=4,
+ min_magnitude=0,
+ max_magnitude=2,
+ dt = 0.1,
+ x_min = -0.5, x_max = 0.5, y_min = -0.5, y_max = 0.5,
+ ).set_color_by_gradient([BLUE_E, TEAL, WHITE])
+ flow_1 = AnimatedStreamLines(
+ curl_rep_1,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ )
+
+ static = VMobject()
+ for p in range(0, 8, 4):
+ curl_rep_n = [*StreamLines(
+ curl,
+ virtual_time=2,
+ min_magnitude=0,
+ max_magnitude=1,
+ dt = 0.1,
+ x_min = -0.5, x_max = 0.5, y_min = -0.5, y_max = 0.5,
+ ).scale(0.5).move_to(np.array([-2+p, 0,0]))]
+ static.add(*curl_rep_n)
+ static_1 = VMobject()
+ for p in range(-3, 4, 2):
+ curl_rep_1 = [*StreamLines(
+ curl,
+ virtual_time=2,
+ min_magnitude=0,
+ max_magnitude=1,
+ dt = 0.1,
+ x_min = -0.5, x_max = 0.5, y_min = -0.5, y_max = 0.5,
+ ).scale(0.25).move_to(np.array([p, 0.6,0]))]
+ static_1.add(*curl_rep_1)
+
+ static_2 = VMobject()
+ for p in range(-3, 4, 2):
+ curl_rep_2 = [*StreamLines(
+ curl,
+ virtual_time=2,
+ min_magnitude=0,
+ max_magnitude=1,
+ dt = 0.1,
+ x_min = -0.5, x_max = 0.5, y_min = -0.5, y_max = 0.5,
+ ).scale(0.25).move_to(np.array([p, -0.6,0]))]
+ static_2.add(*curl_rep_2)
+
+
+
+ surface_6 = ParametricSurface(
+ self.surface,
+ u_min=-3,
+ u_max=3,
+ v_min=-3,
+ v_max=3,
+ fill_color=BLACK,
+ checkerboard_colors=[BLACK, BLACK],
+ stroke_color=BLUE_E,
+ resolution = [64,64]
+ ).set_fill(opacity=0.2).scale(1.5)
+
+ boundary = ParametricSurface(
+ self.surface,
+ u_min=-3,
+ u_max=3,
+ v_min=-3,
+ v_max=3,
+ fill_color=BLACK,
+ checkerboard_colors=[BLACK, BLACK],
+ stroke_color=YELLOW_E,
+ resolution = [2,1]
+ ).set_fill(opacity=0).scale(1.75)
+
+
+
+
+ g1 = VGroup(surface_1, c)
+ g2 = VGroup( c1, c2, text_1)
+ g3 = VGroup(c1a, c2a, c3a, c4a)
+
+ tr = Ellipse(width = 9, height = 3)
+ line = Line(tr.get_center()+1.5*UP, tr.get_center()+1.5*DOWN)
+ b = VMobject(stroke_color = "#F4EDED")
+ b.set_points_smoothly([tr.get_center()+1.5*UP, np.array([-2.25, 1.26, 0]), tr.get_center()+4.5*LEFT, np.array([-2.25, -1.26, 0]), tr.get_center()+1.5*DOWN])
+
+
+ self.add(title)
+ self.play(ShowCreation(g1), ShowCreation(eq1))
+ self.wait(3)
+ self.remove(flow_1)
+ self.play(ShowCreation(surface_2), ReplacementTransform(eq1, eq2))
+ self.remove(g1)
+ self.wait()
+ self.play(ReplacementTransform(surface_2, surface_3), ReplacementTransform(eq2, eq3))
+ self.wait()
+ self.wait()
+ self.play(FadeOut(surface_3), ShowCreation(surface_4), ReplacementTransform(eq3, eq4), ReplacementTransform(title, eq))
+ self.play(FadeOut(surface_4), ShowCreation(surface_5))
+ self.play(FadeOut(surface_5), ShowCreation(surface_6))
+ self.wait()
+ #self.add(tr, line)
+ self.wait()
+ grd = ScreenGrid()
+
+ g = ParametricFunction(func, t_min = 0, t_max = 2*PI).scale(1.5)
+ self.add(grd, g)
+ self.wait()
+
+
+def circ(coordinate):
+ x,y = coordinate[:2]
+ for x in range(0, -5) and y in range(-1,1):
+ cr = Ellipse()
+ return cr
+
+def func(t):
+ return np.array([
+ np.sin(t),
+ np.cos(t),
+ 0])
+
+def surf(t,u):
+ return np.array([
+ u*np.sin(t),
+ np.cos(t),
+ 0])
+
+class Analogy(GraphScene):
+ CONFIG = {
+ "x_min": -1,
+ "x_max": 4,
+ "y_min": 0,
+ "y_max": 2,
+ "y_tick_frequency": 2.5,
+ "n_rect_iterations": 6,
+ "default_right_x": 3,
+ }
+
+ def construct(self):
+
+
+ ftc = TexMobject(r"\int_a^b f'(x) \ dx", r" = f(b) - f(a)").shift(3*UP).set_color("#F9DB6D").scale(0.7)
+ greens = TexMobject(r"\int \int_{R} curl \left(\vec F \right) \ dxdy", r" = \int_{C} \vec F \ dr").shift(3*UP).set_color("#F9DB6D").scale(0.7)
+ ftc[0].set_color("#36827F")
+ greens[1].set_color("#36827F")
+
+
+ two_to_one = TexMobject(r"\textit{2D region} \to", r"\textit{1D curve}").shift(3.6*DOWN).scale(0.7).set_color("#F9DB6D")
+ one_to_zero = TexMobject(r"\textit{1D curve}", r" \to \textit{0D points}").shift(3.6*DOWN).set_color("#F9DB6D").scale(0.7)
+ two_to_one[1].set_color("#36827F")
+ one_to_zero[0].set_color("#36827F")
+ greens_title = TexMobject(r"\textit{Green's Theorem}").scale(0.8).next_to(two_to_one, UP, buff = SMALL_BUFF).set_color("#F4EDED")
+ ftc_title = TexMobject(r"\textit{Fundamental Theorem of Calculus}").scale(0.8).next_to(two_to_one, UP, buff = SMALL_BUFF).set_color("#F4EDED")
+
+ surf= VMobject(fill_color = "#ED6A5A", stroke_color = "#ED6A5A", fill_opacity = 0.6)
+ surf.set_points_smoothly([np.array([-2, 1.8,0]),np.array([-1.6, 0.5,0]),np.array([-3.2, -1.2,0]),np.array([2.6, -1.5,0]),np.array([1, 0,0]),np.array([3.5,2.3, 0]), np.array([-2,1.8, 0])])
+ dot = Dot(np.array([-2,1.8, 0])).set_color("#F4EDED")
+ boundary = VMobject(stroke_color = "#F4EDED")
+ boundary.set_points_smoothly([np.array([-2, 1.8,0]),np.array([-1.6, 0.5,0]),np.array([-3.2, -1.2,0]),np.array([2.6, -1.5,0]),np.array([1, 0,0]),np.array([3.5,2.3, 0]), np.array([-2,1.8, 0])])
+ c = TexMobject(r"C").next_to(surf,RIGHT+UP).set_color("#F4EDED")
+ r = TexMobject(r"R").move_to(np.array([-0.2, 0.6, 0])).set_color("#F4EDED")
+
+ self.play(ShowCreation(surf), ShowCreation(r))
+ self.wait(2)
+ self.play(ShowCreation(boundary), MoveAlongPath(dot, boundary), Write(c), Write(greens),Write(greens_title), run_time= 1.5)
+ self.wait(2)
+ self.play(ReplacementTransform(surf, boundary), FadeOut(r), Write(two_to_one), FadeOut(dot))
+ self.wait(2)
+
+ self.setup_axes()
+
+ grapher = self.get_graph(self.funk)
+ grapher.set_color("#E94F37")
+ l1 = self.get_vertical_line_to_graph(1, grapher, color = "#F4EDED")
+ l2 =self.get_vertical_line_to_graph(3, grapher, color = "#F4EDED")
+ label_coord_1 = self.input_to_graph_point(1,grapher)
+ label_coord_2 = self.input_to_graph_point(3,grapher)
+
+
+ a = TexMobject(r"a").next_to(label_coord_1,RIGHT+UP).set_color("#F4EDED")
+ b = TexMobject(r"b").next_to(label_coord_2,RIGHT+UP).set_color("#F4EDED")
+
+
+
+
+
+ point_a = Dot(label_coord_1).set_color("#827081")
+ point_b = Dot(label_coord_2).set_color("#827081")
+
+
+ self.play(ReplacementTransform(boundary, grapher), FadeOut(c), FadeIn(a), FadeIn(b), FadeIn(point_a), FadeIn(point_b), ReplacementTransform(greens, ftc), ReplacementTransform(greens_title, ftc_title))
+ self.wait(2)
+ self.play(Uncreate(grapher), ReplacementTransform(two_to_one, one_to_zero))
+ self.wait(2)
+
+
+ def funk(self,x):
+ return 0.2*(x-2)**2 +1 \ No newline at end of file
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file2_line-int.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file2_line-int.gif
new file mode 100644
index 0000000..22d0509
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file2_line-int.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file2_line-int.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file2_line-int.py
new file mode 100644
index 0000000..704acf7
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file2_line-int.py
@@ -0,0 +1,132 @@
+from manimlib.imports import *
+
+def field_func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -x,
+ -y,
+ 0
+ ])
+
+
+class LineIntegral(MovingCameraScene, Scene):
+ def setup(self):
+ MovingCameraScene.setup(self)
+ Scene.setup(self)
+
+ def get_pending(self,path,proportion,dx=0.01):
+ if proportion < 1:
+ coord_i = path.point_from_proportion(proportion)
+ coord_f = path.point_from_proportion(proportion+dx)
+ else:
+ coord_i = path.point_from_proportion(proportion-dx)
+ coord_f = path.point_from_proportion(proportion)
+ line = Line(coord_i,coord_f)
+ angle = line.get_angle()
+ return angle
+
+ def construct(self):
+
+
+ # all the text
+ vec_f = TexMobject(r"\vec F",r" \textit{ is a vector field defined on the plane}").set_color("#EDF2EF")
+ c = TexMobject(r"C",r" \textit{ is a curve on the plane, oriented counter-clockwise.}").set_color("#EDF2EF")
+ dr = TexMobject(r"\vec dr", r"\textit{ gives the direction as we move along C}").set_color("#EDF2EF")
+
+ intg = TexMobject(r"\oint \vec F \cdot \vec dr", r"\textit{ gives the rotation along the curve}").shift(2.5*DOWN).scale(0.7).set_color("#EDF2EF")
+ text = VGroup(vec_f, c, dr).scale(0.6).set_stroke(width = 1.5)
+ text.arrange(DOWN, buff = 0.2)
+ text.shift(3.2*DOWN)
+
+ vec_f[0].set_color("#D1D646")
+ dr[0].set_color("#D1D646")
+ intg[0].set_color("#D1D646")
+
+
+
+
+ self.camera_frame.save_state()
+ vec_f_sym = TexMobject(r"\vec F")
+ c_sym = TexMobject(r"C").move_to(4.8*RIGHT+1.3*UP)
+ dr_sym = TexMobject(r"\vec dr").next_to(vec_f_sym, DOWN, buff = SMALL_BUFF)
+ dp_sym = TexMobject(r"\vec F \cdot \vec dr")
+ intg_sym = TexMobject(r"\oint \vec F \cdot \vec dr")
+
+ symbols = VGroup(vec_f_sym, dr_sym, dp_sym, intg_sym).shift(3*UP).set_color("#D1D646")
+
+
+
+
+ vector_field = VectorField(field_func, x_min = -15, x_max = 15, y_min = -15, y_max = 15).fade(0.5)
+ boundary = Ellipse(width = 9, height = 3).set_color("#32908F")
+ b2 = Ellipse(width = 9, height = 3).set_color(WHITE)
+
+ start_angle = self.get_pending(boundary, 0)
+
+ pointer = Triangle(fill_opacity = 1).set_height(0.25).set_color(WHITE)
+ pointer.set_fill(WHITE)
+ pointer.move_to(boundary.get_start())
+ pointer.rotate(- PI / 2)
+ pointer.save_state()
+ pointer.rotate(start_angle, about_point=pointer.get_center())
+ dp_sym_1 = TexMobject(r"\vec F \cdot \vec dr").next_to(pointer, RIGHT, buff = SMALL_BUFF).scale(0.5).set_color("#D1D646").add_background_rectangle()
+ intg_sym_1 = TexMobject(r"\oint \vec F \cdot \vec dr").next_to(pointer, RIGHT, buff = SMALL_BUFF).scale(0.5).set_color("#75485E").add_background_rectangle()
+ dp = TexMobject(r"\vec F \cdot \vec dr \textit{ measures whether } \vec F \textit{ and } \vec dr", r" \textit{ are oriented the same way }").next_to(dp_sym_1, DOWN, buff = SMALL_BUFF).scale(0.3).set_color("#EDF2EF")
+ dp[1].next_to(dp[0], DOWN, buff = SMALL_BUFF)
+
+
+ # groups according to animation
+ #one = VGroup( vec_f, vec_f_sym)
+ #two = VGroup(boundary, c_sym)
+ #three = VGroup(dr_sym, pointer)
+ #four = VGroup(dp, dp_sym) #this is when to zoom in
+ #five = VGroup(intg, intg_sym)
+
+ delete = VGroup(vec_f, vec_f_sym, c, dr, dr_sym)
+
+
+ self.play(ShowCreation(vec_f), ShowCreation(vec_f_sym))
+ self.wait()
+ self.play(ShowCreation(vector_field), Indicate(vec_f_sym))
+ self.wait(2)
+ self.play(ShowCreation(c))
+ self.wait()
+ self.play(ShowCreation(boundary), ShowCreation(c_sym), Indicate(c))
+ self.wait(2)
+ self.play(ShowCreation(dr))
+ self.wait(2)
+ self.play(ShowCreation(dr_sym), Indicate(dr), ShowCreation(pointer))
+
+ self.play(FadeOut(delete))
+ self.play(
+ self.camera_frame.scale,.25,
+ self.camera_frame.move_to,pointer
+ )
+ self.play(ShowCreation(dp_sym_1), ShowCreation(dp[0]), ShowCreation(dp[1]))
+ self.add(dp_sym)
+ self.wait(3)
+ self.play(Restore(self.camera_frame))
+ self.remove(dp[0], dp[1], dp_sym_1)
+ self.wait()
+ self.add(boundary, pointer, self.camera_frame)
+ def update_rotate_move(mob,alpha):
+ pointer.restore()
+
+ angle = self.get_pending(boundary,alpha)
+
+ pointer.move_to(boundary.point_from_proportion(alpha))
+ pointer.rotate(angle, about_point=pointer.get_center())
+
+
+
+ self.play(
+ #self.camera_frame.scale,.25,
+ UpdateFromAlphaFunc(pointer,update_rotate_move),
+ run_time=3,
+ )
+ self.play(Write(b2))
+ self.play(ReplacementTransform(dp_sym, intg_sym), ShowCreation(intg))
+ self.play(ReplacementTransform(b2, intg_sym))
+ self.play(Indicate(intg_sym))
+ self.wait(2)
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file3_line-int-sum.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file3_line-int-sum.gif
new file mode 100644
index 0000000..bedfd4c
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file3_line-int-sum.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file3_line-int-sum.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file3_line-int-sum.py
new file mode 100644
index 0000000..c5280e1
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file3_line-int-sum.py
@@ -0,0 +1,211 @@
+from manimlib.imports import *
+
+def field_func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -x,
+ -y,
+ 0
+ ])
+
+
+class LineIntegral(MovingCameraScene, Scene):
+ def setup(self):
+ MovingCameraScene.setup(self)
+ Scene.setup(self)
+
+ def get_pending(self,path,proportion,dx=0.01):
+ if proportion < 1:
+ coord_i = path.point_from_proportion(proportion)
+ coord_f = path.point_from_proportion(proportion+dx)
+ else:
+ coord_i = path.point_from_proportion(proportion-dx)
+ coord_f = path.point_from_proportion(proportion)
+ line = Line(coord_i,coord_f)
+ angle = line.get_angle()
+ return angle
+
+ def construct(self):
+ axes_config = {"x_min": -6,
+ "x_max": 6,
+ "y_min": -6,
+ "y_max": 6,
+ "z_axis_config": {},
+ "z_min": -1,
+ "z_max": 1,
+ "z_normal": DOWN,
+ "light_source": 9 * DOWN + 7 * LEFT + 10 * OUT,
+ "number_line_config": {
+ "include_tip": False,
+ },
+ }
+
+ axes = Axes(**axes_config)
+ c_sym = TexMobject(r"C").move_to(4.8*RIGHT+1.3*UP)
+
+
+ final_eq = TexMobject(r"\oint_{C} \vec F \cdot \vec dr", r" = \sum_{i = 1}^{n} \oint_{C_{i}} \vec F \cdot \vec dr ").shift(3*DOWN).set_color("#EDF2EF").scale(1.5)
+ final_eq[0].set_color("#D1D646")
+
+ text = TexMobject(r"\oint_{C} \vec F . dr",r" = \oint_{C_{1}} \vec F . dr ",r"+ \oint_{C_{2}} \vec F . dr",r" + \oint_{C_{3}} \vec F . dr + \oint_{C_{4}} \vec F . dr + ...", r" + \oint_{C_n} \vec F \cdot \vec dr ").shift(3*DOWN).set_color("#EDF2EF").scale(0.7)
+ text[0].set_color("#D1D646")
+
+ vector_field = VectorField(field_func, x_min = -15, x_max = 15, y_min = -15, y_max = 15).fade(0.5)
+ boundary = Ellipse(width = 9, height = 3).set_color("#32908F")
+ start_angle = self.get_pending(boundary, 0)
+
+ pointer = Triangle(fill_opacity = 1).set_height(0.25).set_color(YELLOW_E)
+ pointer.set_fill(YELLOW_E)
+ pointer.move_to(boundary.get_start())
+ pointer.rotate(- PI / 2)
+ pointer.save_state()
+ pointer.rotate(start_angle, about_point=pointer.get_center())
+
+ split_1 = Line(boundary.get_center()+1.5*UP, boundary.get_center()+1.5*DOWN).set_color("#32908F")
+ split_2 = Line(boundary.get_center()+4.5*LEFT, boundary.get_center()+4.5*RIGHT).set_color("#32908F")
+
+ surface_3 = ParametricSurface(
+ self.surface,
+ u_min=-3,
+ u_max=3,
+ v_min=-3,
+ v_max=3,
+ fill_color=BLACK,
+ checkerboard_colors=[BLACK, BLACK],
+ stroke_color="#32908F",
+ stroke_width = 1.5,
+ resolution = [4,4]
+ ).set_fill(opacity=0.2).scale(1.5).set_stroke(width = 1.5)
+
+ surface_4 = ParametricSurface(
+ self.surface,
+ u_min=-3,
+ u_max=3,
+ v_min=-3,
+ v_max=3,
+ fill_color=BLACK,
+ checkerboard_colors=[BLACK, BLACK],
+ stroke_color="#32908F",
+ stroke_width = 1.5,
+ resolution = [16,16]
+ ).set_fill(opacity=0.2).scale(1.5).set_stroke(width = 1.5)
+
+ surface_5 = ParametricSurface(
+ self.surface,
+ u_min=-3,
+ u_max=3,
+ v_min=-3,
+ v_max=3,
+ fill_color=BLACK,
+ checkerboard_colors=[BLACK, BLACK],
+ stroke_color="#32908F",
+ stroke_width = 1.5,
+ resolution = [32,32]
+ ).set_fill(opacity=0.2).scale(1.5).set_stroke(width = 1.5)
+ surface_6 = ParametricSurface(
+ self.surface,
+ u_min=-3,
+ u_max=3,
+ v_min=-3,
+ v_max=3,
+ fill_color=BLACK,
+ checkerboard_colors=[BLACK, BLACK],
+ stroke_color="#32908F",
+ stroke_width = 1.5,
+ resolution = [64,64]
+ ).set_fill(opacity=0.2).scale(1.5).set_stroke(width = 1.5)
+
+ dot = Dot()
+ dot_1 = Dot()
+ dot_2 = Dot()
+
+
+ pointer = Triangle(fill_opacity = 1).set_height(0.25).set_color("#75485E")
+ pointer.set_fill("#75485E")
+ pointer.move_to(boundary.get_start())
+ pointer.rotate(- PI / 2)
+ pointer.save_state()
+ pointer.rotate(start_angle, about_point=pointer.get_center())
+
+ pointer_b2 = Triangle(fill_opacity = 1).set_height(0.25).set_color(YELLOW_E)
+ pointer_b2.set_fill(YELLOW_E)
+ pointer_b2.move_to(boundary.get_start())
+ pointer_b2.rotate(- PI / 2)
+ pointer_b2.save_state()
+ pointer_b2.rotate(start_angle, about_point=pointer_b2.get_center())
+
+
+ # labels
+ labels_1 = VGroup( TexMobject(r"C_{1}").move_to(np.array([0, 3, 0])),
+ TexMobject(r"C_{2}").move_to(np.array([0, -3, 0]))).scale(0.7)
+ labels_2 = VGroup( TexMobject(r"C_{1}").move_to(np.array([-2.25, 2.5, 0])),
+ TexMobject(r"C_{2}").move_to(np.array([-2.25, -2.5, 0])),
+ TexMobject(r"C_{3}").move_to(np.array([2.25, -2.5, 0])),
+ TexMobject(r"C_{4}").move_to(np.array([2.25, 2.5, 0]))).scale(0.7)
+
+ og = VGroup(boundary, split_1, split_2, labels_1, labels_2)
+
+
+ self.add(vector_field, boundary, pointer, text[0], c_sym)
+ def update_rotate_move(mob,alpha):
+ pointer.restore()
+
+ angle = self.get_pending(boundary,alpha)
+
+ pointer.move_to(boundary.point_from_proportion(alpha))
+ pointer.rotate(angle, about_point=pointer.get_center())
+
+ self.play(
+ UpdateFromAlphaFunc(pointer,update_rotate_move),
+ run_time=3,
+ )
+ self.wait()
+ self.play(Indicate(text[0]))
+ self.wait(2)
+ self.play(ShowCreation(text[1]), FadeIn(split_2), ShowCreation(text[2]), ShowCreation(labels_1), FadeOut(pointer), FadeOut(c_sym))
+ self.play(Indicate(text[1]), Indicate(text[2]))
+ self.wait(2)
+ self.play(FadeIn(split_1), ShowCreation(text[3]), ReplacementTransform(labels_1, labels_2))
+ self.play(Indicate(text[1]), Indicate(text[2]), Indicate(text[3]))
+ self.wait(2)
+ self.play(FadeOut(og), ShowCreation(surface_3))
+ self.play(FadeOut(surface_3), ShowCreation(surface_4))
+ self.play(FadeOut(surface_4), ShowCreation(surface_5))
+ self.play(FadeOut(surface_5), ShowCreation(surface_6), ShowCreation(text[4]))
+ self.wait(2)
+ self.play(ReplacementTransform(text, final_eq))
+ self.wait()
+ self.play(Indicate(final_eq))
+ self.wait()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @staticmethod
+ def surface(t, v):
+ return np.array([
+ v*np.sin(t),
+ np.cos(t),
+ 0
+ ])
+
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file4_theorem-proof.gif b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file4_theorem-proof.gif
new file mode 100644
index 0000000..ead9fe5
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file4_theorem-proof.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file4_theorem-proof.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file4_theorem-proof.py
new file mode 100644
index 0000000..b038bd9
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/Greens Theorem/GreensTheorem_file4_theorem-proof.py
@@ -0,0 +1,184 @@
+from manimlib.imports import *
+
+def field_func(coordinate):
+ x,y = coordinate[:2]
+ return np.array([
+ -x,
+ -y,
+ 0
+ ])
+
+def curl(coordinate):
+ x,y = coordinate[:2]
+ U = (x**2 + y**2)
+ return np.array([
+ -y/(x**2 + y**2),
+ x/(x**2 + y**2),
+ 0
+ ])
+
+
+class LineIntegral(ZoomedScene, Scene):
+ def setup(self):
+ ZoomedScene.setup(self)
+ Scene.setup(self)
+
+ def get_pending(self,path,proportion,dx=0.01):
+ if proportion < 1:
+ coord_i = path.point_from_proportion(proportion)
+ coord_f = path.point_from_proportion(proportion+dx)
+ else:
+ coord_i = path.point_from_proportion(proportion-dx)
+ coord_f = path.point_from_proportion(proportion)
+ line = Line(coord_i,coord_f)
+ angle = line.get_angle()
+ return angle
+
+ def construct(self):
+ CONFIG = {
+ "zoom_factor": 0.3,
+ "zoomed_display_height": 1,
+ "zoomed_display_width": 6,
+ "image_frame_stroke_width": 20,
+ "zoomed_camera_config": {
+ "default_frame_stroke_width": 3,
+ },
+ }
+
+
+ axes_config = {"x_min": -6,
+ "x_max": 6,
+ "y_min": -6,
+ "y_max": 6,
+ "z_axis_config": {},
+ "z_min": -1,
+ "z_max": 1,
+ "z_normal": DOWN,
+ "light_source": 9 * DOWN + 7 * LEFT + 10 * OUT,
+ "number_line_config": {
+ "include_tip": False,
+ },
+ }
+
+ axes = Axes(**axes_config)
+ surface_a = ParametricSurface(
+ self.surface,
+ u_min=-3,
+ u_max=3,
+ v_min=-3,
+ v_max=3,
+ fill_color=BLACK,
+ checkerboard_colors=[BLACK, BLACK],
+ stroke_color=BLUE_E,
+ stroke_width = 1.5,
+ resolution = [64,64]
+ ).set_fill(opacity=0.2).scale(1.5).set_stroke(width = 1.5)
+ vector_field = VectorField(field_func)
+
+ dot = Dot().scale(0.5).shift(0.49*LEFT+0.039*UP)
+ dot_show = Dot().scale(0.05).move_to(dot.get_center())
+
+ zoomed_camera = self.zoomed_camera
+ zoomed_display = self.zoomed_display
+ frame = zoomed_camera.frame
+ zoomed_display_frame = zoomed_display.display_frame
+
+ frame.move_to(dot)
+ frame.scale(0.75)
+
+ box = Square(fill_color= BLUE_E, fill_opacity = 0.8).scale(0.07).move_to(dot.get_center()).flip()
+
+ label_box = TexMobject(r"D_i").scale(0.05).next_to(box, DOWN, buff = 0.05)
+
+ label = TexMobject(r"x_i, y_i").scale(0.06).next_to(dot_show, DOWN, buff = 0.05)
+
+ start_angle = self.get_pending(box, 0)
+
+ pointer = Triangle(fill_opacity = 1).set_height(0.03).set_color(YELLOW_E)
+ pointer.set_fill(YELLOW_E)
+ pointer.move_to(box.get_start())
+ pointer.rotate(- PI / 2)
+ pointer.save_state()
+ pointer.rotate(start_angle, about_point=pointer.get_center())
+
+
+ flow = StreamLines(
+ curl,
+ virtual_time=2,
+ min_magnitude=0,
+ max_magnitude=1,
+ dt = 0.1,
+ x_min = -0.5, x_max = 0.5, y_min = -0.5, y_max = 0.5,
+ ).scale(0.05).move_to(dot.get_center())
+ flow_1 = AnimatedStreamLines(
+ flow,
+ line_anim_class=ShowPassingFlashWithThinningStrokeWidth
+ )
+
+
+ # all the text
+ text_zoomed = TexMobject(r"\oint_{C_{i}} \vec F \cdot \vec dr = (\frac{\partial Q}{\partial x} - \frac{\partial P}{\partial y}).", r" \mid D_{i} \mid").add_background_rectangle()
+ text_gen_1 = TexMobject(r"\sum_{i = 1}^{n}\oint_{C_{i}} \vec F \cdot \vec dr = \sum_{i = 1}^{n} (\frac{\partial Q}{\partial x} - \frac{\partial P}{\partial y}). \mid D_{i} \mid").add_background_rectangle()
+ text_gen_2 = TexMobject(r"\oint_{C} \vec F \cdot \vec dr = \sum_{i = 1}^{n} (\frac{\partial Q}{\partial x} - \frac{\partial P}{\partial y}. \mid D_{i} \mid")
+ text_conclusion = TexMobject(r"\oint \vec F \cdot \vec dr = \int \int_D (\frac{\partial Q}{\partial x} - \frac{\partial P}{\partial y}) dA").add_background_rectangle()
+ text_intuition = TexMobject(r"\oint_{C} \textit{Macroscopic curl } = \int \int_{D} \textit{Sum of microscopic curls }").add_background_rectangle()
+
+ texts = VGroup(text_zoomed, text_gen_1, text_gen_2, text_conclusion, text_intuition).shift(2.8*DOWN).scale(0.8)
+
+ self.add(vector_field, surface_a, dot_show, label)
+ self.wait()
+ self.activate_zooming(animate=True)
+ self.wait(2)
+ self.add(pointer)
+ def update_rotate_move(mob,alpha):
+ pointer.restore()
+
+ angle = self.get_pending(box,alpha)
+
+ pointer.move_to(box.point_from_proportion(alpha))
+ pointer.rotate(angle, about_point=pointer.get_center())
+ self.add(flow_1)
+ self.play(ShowCreation(text_zoomed))
+ #self.play(ReplacementTransform(box, text_zoomed[1]))
+ #self.wait(2)
+ self.play(
+ UpdateFromAlphaFunc(pointer,update_rotate_move),
+ run_time=3,
+ )
+ self.wait(3)
+ #self.play(ReplacementTransform(text_zoomed, text_gen_1))
+ #self.wait(2)
+ #self.play(ReplacementTransform(text_gen_1, text_gen_2))
+
+ self.play(
+ self.get_zoomed_display_pop_out_animation(),
+ # -------> Inverse
+ rate_func=lambda t: smooth(1-t),
+ )
+ self.play(
+ Uncreate(zoomed_display_frame),
+ FadeOut(frame),
+ )
+ self.wait()
+ self.remove(pointer, flow_1, label, dot_show, label_box)
+ self.play(ReplacementTransform(text_zoomed, text_gen_1))
+ self.wait(2)
+ self.play(FadeIn(text_conclusion), FadeOut(text_gen_1))
+ self.wait(2)
+ self.play(FadeOut(text_conclusion), FadeIn(text_intuition))
+ self.wait(2)
+
+
+
+
+
+
+
+
+ @staticmethod
+ def surface(t, v):
+ return np.array([
+ v*np.sin(t),
+ np.cos(t),
+ 0
+ ]) \ No newline at end of file
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/conservative-fields/README.md b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/conservative-fields/README.md
new file mode 100644
index 0000000..afce19b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/conservative-fields/README.md
@@ -0,0 +1,13 @@
+**conservative_file1_paths-3d.py** <br>
+![conservative_file1_paths-3d.py](Conservative_file1_paths-3d.gif)
+**conservative_file2_line-int.py** <br>
+![conservative_file2_line-int.py](Conservative_file2_line-int.gif)
+**conservative_file3_path-independent.py** <br>
+![conservative_file3_path-independent.py](Conservative_file3_path-independent.gif)
+**conservative_file4_path-dependent.py** <br>
+![conservative_file4_path-dependent.py](Conservative_file4_path-dependent.gif)
+**conservative_file5_closed-loop.py** <br>
+![conservative_file5_closed-loop.py](Conservative_file5_closed-loop.gif)
+**conservative_file6_potential-func.py** <br>
+![conservative_file6_potential-func.py](Conservative_file6_potential-func.gif)
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/curl-and-div/README.md b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/curl-and-div/README.md
new file mode 100644
index 0000000..36e335d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/curl-and-div/README.md
@@ -0,0 +1,24 @@
+**DivCurl_file1_sources-and-sinks.py** <br>
+![DivCurl_file1_sources-and-sinks.py](DivCurl_file1_sources-and-sinks.gif)
+**DivCurl_file2_div-curl-types.py** <br>
+![DivCurl_file2_div-curl-types.py](DivCurl_file2_div_curl-types.gif)
+**DivCurl_file3_threed-vec-field.ipynb** <br>
+![DivCurl_file3_threed-vec-field.ipynb](DivCurl_file3_threed-vec-field.gif)
+**DivCurl_file4_output-curl.ipynb** <br>
+![DivCurl_file4_output-curl.ipynb](DivCurl_file4_output-curl.gif)
+**DivCurl_file5_neg-div.ipynb** <br>
+![DivCurl_file5_neg-div.ipynb](DivCurl_file5_neg-div.gif)
+**DivCurl_file6_macro-micro-curl.py** <br>
+![DivCurl_file6_macro-micro-curl.py](DivCurl_file6_macro-micro-curl.gif)
+**DivCurl_file7_div-formula.py** <br>
+![DivCurl_file7_div-formula.py](DivCurl_file7_div-formula.gif)
+**DivCurl_file8_curl-paddle.py** <br>
+![DivCurl_file8_curl-paddle.py](DivCurl_file8_curl-paddle.gif)
+**DivCurl_file9_formal-def.py** <br>
+![DivCurl_file9_formal-def.py](DivCurl_file9_formal-def.gif)
+**DivCurl_file10_gauss.ipynb** <br>
+![DivCurl_file10_gauss.ipynb](DivCurl_file10_gauss.png)
+**DivCurl_file11_gravitational-field.ipynb** <br>
+![DivCurl_file11_gravitational-field.ipynb](DivCurl_file11_gravitational-field.png)
+**DivCurl_file12_ponder-curl.py** <br>
+![DivCurl_file12_ponder-curl.py](DivCurl_file12_ponder-curl.gif)
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/README.md b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/README.md
new file mode 100644
index 0000000..c284f76
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/README.md
@@ -0,0 +1,19 @@
+**Gradient_file1_analogy.py** <br>
+![Gradient_file1_analogy.py](Gradient_file1_analogy.gif)
+**Gradient_file2_input-output.py** <br>
+![Gradient_file2_input-output.py](Gradient_file2_input-output.gif)
+**Gradient_file3_input-output2.py** <br>
+![Gradient_file3_input-output2.py](Gradient_file3_input-output2.gif)
+**Gradient_file4_why-partials.py** <br>
+![Gradient_file4_why-partials.py](Gradient_file4_why-partials.gif)
+**Gradient_file5_contour-lines-and-map.ipynb** <br>
+![Gradient_file5_contour-lines-and-map.ipynb](Gradient_file5_contour-lines-and-map.png)
+**Gradient_file6_surf-contour-plot.ipynb** <br>
+![Gradient_file6_surf-contour-plot.ipynb](Gradient_file6_surf-contour-plot.png)
+**Gradient_file7_missiles.py** <br>
+![Gradient_file7_missiles.py](Gradient_file7_missiles.gif)
+**Gradient_file8_fluid-flow.py** <br>
+![Gradient_file8_fluid-flow.py](Gradient_file8_fluid-flow.gif)
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file1_missile-example.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file1_missile-example.py
deleted file mode 100644
index cd754cd..0000000
--- a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file1_missile-example.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from manimlib.imports import *
-import numpy as np
-
-
-def function(coordinate):
- x,y = coordinate[:2]
- return np.array([
- np.sin(x-y),
- np.exp(y),
- 0
- ])
-def func(coordinate):
- x,y = coordinate[:2]
- return np.array([
- -2*x,
- y,
- 0])
-
-class Missiles(GraphScene):
- def construct(self):
-
- field = VectorField(function)
- #path = ParametricFunction(lambda x: -2*x)
-
- dot = SVGMobject("miss").move_to(DL).scale(0.09).set_color(WHITE).rotate(PI/4 + PI)
- path = ArcBetweenPoints(dot.get_center(), UP+0.2*LEFT)
-
- self.play(FadeIn(field))
- self.wait()
- self.play(FadeIn(dot))
- self.wait()
- self.play(MoveAlongPath(dot, path))
- self.play(ApplyMethod(dot.rotate, PI/4), rate = 0.2)
- self.play(ApplyMethod(dot.move_to, 3.5*UP), rate = 0.3)
- #self.play(ApplyMethod(dot.move_to, 3.5*UP))
- #self.add_fixed_in_frame_mobjects(text_field)
- self.wait() \ No newline at end of file
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file2_gradient-example-1.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file2_gradient-example-1.py
deleted file mode 100644
index 7a95867..0000000
--- a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file2_gradient-example-1.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from manimlib.imports import *
-import numpy as np
-
-
-def function(coordinate):
- x,y = coordinate[:2]
- return np.array([
- 0.4*x,
- 0.4*y,
- 0.4*np.cos(np.sqrt((x**2)+(y**2))
- )])
-
-class ThreeDVector(ThreeDScene):
- def construct(self):
- axes = ThreeDAxes()
- self.add(axes)
- self.set_camera_orientation(phi=45*DEGREES,theta=60*DEGREES,distance=40)
- self.begin_ambient_camera_rotation(rate=0.5)
-
- surface = ParametricSurface(
- lambda u, v: np.array([
- 0.4*u,
- 0.4*v,
- 0.4*np.cos(np.sqrt((u**2)+(v**2)))
- ]),u_min=-20,u_max=20, v_min=-10,v_max=10).set_color(BLUE_E).fade(0.7)
-
- text_func = TexMobject(r"\textbf{Input: Function}").shift(4.4*LEFT+3.3*UP).scale(0.7)
- text_field = TexMobject(r"\textbf{Output: Vector Field}").shift(4.4*LEFT+3.3*UP).scale(0.7)
-
-
- self.add_fixed_in_frame_mobjects(text_func)
- self.play(ShowCreation(surface))
- self.wait(3)
-
- field = VectorField(function)
- self.play(FadeIn(field), FadeOut(text_func))
- self.add_fixed_in_frame_mobjects(text_field)
- self.wait()
- self.play(FadeOut(surface))
- self.wait()
-
-
-
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file3_gradient-example-2.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file3_gradient-example-2.py
deleted file mode 100644
index e37581d..0000000
--- a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file3_gradient-example-2.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from manimlib.imports import *
-import numpy as np
-
-
-def function(coordinate):
- x,y = coordinate[:2]
- return np.array([
- x,
- y,
- x**2 - y**2
- ])
-
-class ThreeDVector_three(ThreeDScene):
- def construct(self):
- axes = ThreeDAxes()
- self.add(axes)
- self.set_camera_orientation(phi=45*DEGREES,theta=85*DEGREES,distance=40)
- self.begin_ambient_camera_rotation(rate=0.5)
-
- surface = ParametricSurface(
- lambda x, y: np.array([
- x,
- y,
- x**2 - y**2
- ]),u_min=-2,u_max=2, v_min=-1.5,v_max=1.5).set_color(BLUE_E).fade(0.7).scale(1.7)
-
- text_func = TexMobject(r"\textbf{Input: Function}").shift(4.4*LEFT+3.3*UP).scale(0.7)
- text_field = TexMobject(r"\textbf{Output: Vector Field}").shift(4.4*LEFT+3.3*UP).scale(0.7)
-
- self.add_fixed_in_frame_mobjects(text_func)
- self.play(ShowCreation(surface))
- self.wait(3)
-
- field = VectorField(function)
- self.play(FadeIn(field), FadeOut(text_func))
- self.add_fixed_in_frame_mobjects(text_field)
- self.wait()
- self.play(FadeOut(surface))
- self.wait(2) \ No newline at end of file
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file4-multidimensional-gradient.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file4-multidimensional-gradient.py
deleted file mode 100644
index e9c8fd0..0000000
--- a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file4-multidimensional-gradient.py
+++ /dev/null
@@ -1,113 +0,0 @@
-from manimlib.imports import *
-import numpy as np
-
-
-class Hills(ThreeDScene):
- def construct(self):
- axes = ThreeDAxes(
- number_line_config={
- "color": GREEN,
- "include_tip": False,
- "exclude_zero_from_default_numbers": True,
- }
- )
- self.add(axes)
-
- self.set_camera_orientation(phi=45*DEGREES,theta=45*DEGREES,distance=40)
- #self.begin_ambient_camera_rotation(rate=0.5)
- self.wait()
-
- cylinder_1 = ParametricSurface(
- lambda u, v: np.array([
- u,
- v,
- 7*u*v/np.exp(u**2+v**2)
- ]),u_min=-3,u_max=3, v_min=-1,v_max=-0.95).set_color(YELLOW_E).rotate(PI/2).shift(LEFT).fade(0.5)
- cylinder = ParametricSurface(
- lambda u, v: np.array([
- u,
- v,
- 7*u*v/np.exp(u**2+v**2)
- ]),u_min=-3,u_max=3, v_min=-3,v_max=3).set_color(YELLOW_E).rotate(PI/2).shift(LEFT).fade(0.5)
- text_one = TexMobject(r"\textrm{Single variable functions slope up and down}")
- #name = TexMobject(r"\textrm{PROBE}").next_to(text_one, DOWN, buff = SMALL_BUFF).scale(0.7)
- text_one_a = TexMobject(r"\textrm{Position }", r" \rightarrow ").next_to(text_one, DOWN, buff = SMALL_BUFF)
- probe = Sphere(radius = 0.2).next_to(text_one_a, RIGHT).set_color(BLUE_E)
- text_one_b = TexMobject(r" \rightarrow ", r"\textrm{ slope }").next_to(probe, RIGHT, buff = SMALL_BUFF)
- name = TextMobject("PROBE").next_to(probe, DOWN, buff = SMALL_BUFF).scale(0.5)
- text = VGroup(text_one, text_one_a, probe, text_one_b, name).to_edge(UP+1.5*LEFT).scale(0.5)
-
- text_two = TexMobject(r"\textrm{Multivariable functions slope in infinitely many directions!}")
- #name_two = TexMobject(r"\textrm{PROBE2.0}").next_to(text_two, DOWN, buff = SMALL_BUFF).scale(0.7)
- text_two_a = TexMobject(r"\textrm{Position, Direction }", r" \rightarrow ").next_to(text_two, DOWN, buff = SMALL_BUFF)
- probe_two = Sphere(radius = 0.2).next_to(text_two_a, RIGHT).set_color(PURPLE_E)
- text_two_b = TexMobject(r" \rightarrow ", r"\textrm{ slope }").next_to(probe_two, RIGHT, buff = SMALL_BUFF)
- name_two = TextMobject("PROBE2.0").next_to(probe_two, DOWN, buff = SMALL_BUFF).scale(0.5)
- two = VGroup(text_two, text_two_a, probe_two, text_two_b, name_two).to_edge(UP+LEFT).scale(0.5).shift(3.5*LEFT)
-
-
-
-
-
-
- self.play(ShowCreation(cylinder_1))
- self.wait()
- self.add_fixed_in_frame_mobjects(text)
- self.wait(3.5)
- self.play(FadeOut(text))
- self.play(ReplacementTransform(cylinder_1, cylinder))
- self.wait()
- self.add_fixed_in_frame_mobjects(two)
- self.begin_ambient_camera_rotation(rate=0.5)
- self.wait(4)
-
-class OneMore(ThreeDScene, GraphScene):
- def setup(self):
- GraphScene.setup(self)
- ThreeDScene.setup(self)
-
- def construct(self):
- axes = ThreeDAxes(
- number_line_config={
- "color": GREEN,
- "include_tip": False,
- "exclude_zero_from_default_numbers": True,
- }
- )
- self.add(axes)
-
- self.set_camera_orientation(phi=90*DEGREES,theta=90*DEGREES,distance=40)
- #self.begin_ambient_camera_rotation(rate=0.5)
- self.wait()
-
- shape = ParametricSurface(
- lambda u, v: np.array([
- u,
- v,
- 2 - u**2 - v**2,
- ]),u_min=0,u_max =0.01, v_min=-2,v_max=2).set_color(GREEN_C)
-
- shape_A = ParametricSurface(
- lambda u, v: np.array([
- 0*u,
- 0,
- v,
- ]),u_min=-2,u_max = 2, v_min=-2,v_max=2).set_color(GREEN_C)
-
-
- '''
- path = self.get_graph(lambda u,v: np.array([
- u,
- 2 - u**2 - v**2]), u_min=-2,u_max=2, v_min=-2,v_max=2)
- location = np.array([-2,-2, -2]) #location: Point
- dot = Dot(location)
- '''
-
- self.play(ShowCreation(shape))
- self.add(shape_A)
- #self.play(ShowCreation(path), ShowCreation(dot))
- #self.play(MoveAlongPath(dot, path))
- #self.wait(3)
- self.play(ApplyMethod(shape.fade, 0.5))
- self.begin_ambient_camera_rotation(rate = 0.5)
- self.wait(3)
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file4_gradient-example-3.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file4_gradient-example-3.py
deleted file mode 100644
index 7c0ef54..0000000
--- a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file4_gradient-example-3.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from manimlib.imports import *
-import numpy as np
-
-
-def function(coordinate):
- x,y = coordinate[:2]
- return np.array([
- x,
- y,
- 1/np.cos(x*y),
- ])
-
-class ThreeDVector(ThreeDScene):
- def construct(self):
- axes = ThreeDAxes()
- self.add(axes)
- self.set_camera_orientation(phi=45*DEGREES,theta=45*DEGREES,distance=40)
- self.begin_ambient_camera_rotation(rate=0.5)
-
- surface = ParametricSurface(
- lambda x, y: np.array([
- x,
- y,
- 1/np.cos(x*y),
- ]),u_min=-1.15,u_max=1.15, v_min=-1.15,v_max=1.15).set_color(BLUE_E).fade(0.7).scale(1.4)
-
- text_func = TexMobject(r"\textbf{Input: Function}").shift(4.4*LEFT+3.3*UP).scale(0.3)
- text_field = TexMobject(r"\textbf{Output: Vector Field}").shift(4.4*LEFT+3.3*UP).scale(0.7)
-
- self.add_fixed_in_frame_mobjects(text_func)
- self.play(ShowCreation(surface))
- self.wait(2)
-
- field = VectorField(function).scale(0.7)
- self.play(FadeIn(field), FadeOut(text_func))
- self.add_fixed_in_frame_mobjects(text_field)
- self.wait()
-
- self.play(FadeOut(surface))
- self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file5_steepest-ascent-analogy.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file5_steepest-ascent-analogy.py
deleted file mode 100644
index 803ea4a..0000000
--- a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file5_steepest-ascent-analogy.py
+++ /dev/null
@@ -1,71 +0,0 @@
-from manimlib.imports import *
-import numpy as np
-
-class Rules(ThreeDScene):
-
- def setup(self):
- ThreeDScene.setup(self)
-
- def construct(self):
- axes = ThreeDAxes()#.scale(0.8)#.shift(2*RIGHT, 2*DOWN)
- self.set_camera_orientation(phi=PI/3 + 10*DEGREES,theta=-PI/4 + 25*DEGREES,distance=60)
-
- plane = Polygon(np.array([4,4,0]), np.array([4, -4, 0]), np.array([-4, -4, 0]), np.array([-4, 4, 0]), color = BLACK, fill_color = YELLOW_E, fill_opacity = 0.3)
-
- path_one = Line(start = ORIGIN, end = np.array([3, 0, 0])).set_color(BLUE_E)
- path_one_text = TexMobject(r"\textrm{3 steps in the x direction}").shift(2*DOWN+3.5*LEFT).scale(0.5).set_color(BLUE_E)
- path_two_text = TexMobject(r"\textrm{2 steps in the y direction}").next_to(path_one_text, DOWN, buff = SMALL_BUFF).scale(0.5).set_color(GREEN_C)
- path_three_text = TexMobject(r"\textrm{2 steps in the z direction}").next_to(path_two_text, DOWN, buff = SMALL_BUFF).scale(0.5).set_color(PURPLE_E)
- obj = TextMobject("Objective: ", "Maximise points for a set number of steps").scale(0.8).to_edge(UP+LEFT)
-
- steps = TexMobject(r"\textrm{Total steps = 7}").to_edge(RIGHT, buff = LARGE_BUFF).set_color(YELLOW_E).scale(0.7).shift(1*UP)
- points_one = TexMobject(r"\textrm{Total points = 13}").next_to(steps, DOWN, buff = SMALL_BUFF).scale(0.7).set_color(YELLOW_E)
- question = TexMobject(r"\textrm{Change direction to score more points?}").shift(2*DOWN+2.5*RIGHT).scale(0.9)
-
- path_two = Line(start = np.array([3, 0, 0]), end = np.array([3, 2, 0])).set_color(GREEN_C)
- path_three = Line(start = np.array([3, 2, 0]), end = np.array([3, 2, 2])).set_color(PURPLE_E)
- total = Line(start = np.array([0, 0, 0]), end = np.array([3, 2, 2])).set_color(YELLOW_E)
- projection_total = Line(start = np.array([0, 0, 0]), end = np.array([3, 2, 0]))
- paths = VGroup(path_one, path_two, path_three, path_one_text, path_two_text, path_three_text)
-
- total_one = VGroup(total, projection_total)
-
- total_two = Line(start = np.array([0, 0, 0]), end = np.array([4, 1, 2])).set_color(YELLOW_E)
- projection_total_two = Line(start = np.array([0, 0, 0]), end = np.array([4, 1, 0]))
- points_two = TexMobject(r"\textrm{Total points = 12}").next_to(steps, DOWN, buff = SMALL_BUFF).scale(0.7).set_color(YELLOW_E)
-
- total_three = Line(start = np.array([0, 0, 0]), end = np.array([1, 4, 2])).set_color(YELLOW_E)
- projection_total_three = Line(start = np.array([0, 0, 0]), end = np.array([1, 4, 0]))
- points_three = TexMobject(r"\textrm{Total points = 15}").next_to(steps, DOWN, buff = SMALL_BUFF).scale(0.7).set_color(YELLOW_E)
-
- everything = VGroup(axes, plane, path_one, path_two, path_three, total, projection_total, total_two, projection_total_two, total_three, projection_total_three)
- everything.scale(0.7).shift(2*LEFT+1*DOWN)
- self.add_fixed_in_frame_mobjects(obj)
- self.add(axes, plane)
- self.wait()
- self.add_fixed_in_frame_mobjects(path_one_text)
- self.play(ShowCreation(path_one))
- self.wait()
- self.add_fixed_in_frame_mobjects(path_two_text)
- self.play(ShowCreation(path_two))
- self.wait()
- self.add_fixed_in_frame_mobjects(path_three_text)
- self.play(ShowCreation(path_three))
- self.add_fixed_in_frame_mobjects(steps, points_one)
- self.wait()
- self.play(ShowCreation(total))
- self.play(ReplacementTransform(total.copy(), projection_total))
- self.wait()
- self.play(FadeOut(paths))
- self.add_fixed_in_frame_mobjects(question)
- self.wait()
- self.play(ReplacementTransform(total, total_two), ReplacementTransform(projection_total, projection_total_two))
- self.play(FadeOut(points_one))
- self.add_fixed_in_frame_mobjects(points_two)
- self.wait()
- self.play(ReplacementTransform(total_two, total_three), ReplacementTransform(projection_total_two, projection_total_three))
- self.play(FadeOut(points_two))
- self.add_fixed_in_frame_mobjects(points_three)
- self.wait()
-
-
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file6-maximum.py b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file6-maximum.py
deleted file mode 100644
index 255a0eb..0000000
--- a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/gradient/file6-maximum.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from manimlib.imports import *
-import numpy as np
-
-
-def function(coordinate):
- x,y = coordinate[:2]
- return np.array([
- x,
- y,
- 2 - x**2 - y**2
- ])
-
-class ThreeDVector_one(ThreeDScene):
- def construct(self):
- axes = ThreeDAxes()
- self.add(axes)
- self.set_camera_orientation(phi=75*DEGREES,theta=45*DEGREES,distance=40)
- self.begin_ambient_camera_rotation(rate=0.5)
-
- surface = ParametricSurface(
- lambda x, y: np.array([
- x,
- y,
- 2 - x**2 - y**2
- ]),u_min=-2,u_max=2, v_min=-2,v_max=2).set_color(RED_E).fade(0.7)
-
- probe = Sphere(radius = 0.2).set_color(PURPLE_E)
- probe_one = Sphere(radius = 0.1).set_color(PURPLE_E).move_to(np.array([0,0,2.1]))
- text_one_b = TexMobject(r" \textrm{ reads 0 at local maximum }").next_to(probe, RIGHT, buff = SMALL_BUFF)
- name = TextMobject("PROBE2.0 ").next_to(probe, DOWN, buff = SMALL_BUFF).scale(0.5)
- text = VGroup(probe, text_one_b, name).to_edge(1.5*UP+0.5*LEFT).scale(0.5)
-
-
- self.play(ShowCreation(surface))
- self.add(probe_one)
- field = VectorField(function).scale(0.8)
- self.play(FadeIn(field))
- self.add_fixed_in_frame_mobjects(text)
- self.wait(3)
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/greens-theorem/README.md b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/greens-theorem/README.md
new file mode 100644
index 0000000..157592d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/greens-theorem/README.md
@@ -0,0 +1,8 @@
+**GreensTheorem_file1_ftc-analogue.py** <br>
+![GreensTheorem_file1_ftc-analogue.py](GreensTheorem_file1_ftc-analogue.gif)
+**GreensTheorem_file2_line-int.py** <br>
+![GreensTheorem_file2_line-int.py](GreensTheorem_file2_line-int.gif)
+**GreensTheorem_file3_line-int-sum.py** <br>
+![GreensTheorem_file3_line-int-sum.py](GreensTheorem_file3_line-int-sum.gif)
+**GreensTheorem_file4_theorem-proof.py** <br>
+![GreensTheorem_file4_theorem-proof.py](GreensTheorem_file4_theorem-proof.gif)
diff --git a/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/vec-f-is-conservative-implies-curl-f-is-0/README.md b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/vec-f-is-conservative-implies-curl-f-is-0/README.md
new file mode 100644
index 0000000..61da28c
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/div-curl-grad-and-all-that/vec-f-is-conservative-implies-curl-f-is-0/README.md
@@ -0,0 +1,12 @@
+**CurlTheorem_file1_closed-loop.py** <br>
+![CurlTheorem_file1_closed-loop.py](CurlTheorem_file1_closed-loop.gif)
+**CurlTheorem_file2_curl-paddle.py** <br>
+![CurlTheorem_file2_curl-paddle.py](CurlTheorem_file2_curl-paddle.gif)
+**CurlTheorem_file3_measure-curl.py** <br>
+![CurlTheorem_file3_measure-curl.py](CurlTheorem_file3_measure-curl.gif)
+**CurlTheorem_file4_vortex-streamplot.ipynb** <br>
+![CurlTheorem_file4_vortex-streamplot.ipynb](CurlTheorem_file4_vortex-streamplot.png)
+**CurlTheorem_file5_connected-regions.py** <br>
+![CurlTheorem_file5_connected-regions.py](CurlTheorem_file5_connected-regions.gif)
+**CurlTheorem_file6_not-connected-regions.py** <br>
+![CurlTheorem_file6_not-connected-regions.py](CurlTheorem_file6_not-connected-regions.gif)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/README.md b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/README.md
index e69de29..b46936b 100644
--- a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/README.md
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/README.md
@@ -0,0 +1,9 @@
+This repository contains the codes written by [Saarth Deshpande](https://github.com/saarthdeshpande) during the course of FOSSEE Summer Fellowship 2020 under the FLOSS: Mathematics using Python.
+
+__Sub-topics covered__:
+* Equations of Planes and Lines
+* General Parametric Curves
+* Space Curves (an Intro to Coordinates in 3D)
+* Velocity and Differentiability
+* Finding Arc Length and Curvature
+* TNB Frame and Serret-Frenet Formulae
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/README.md b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/README.md
new file mode 100644
index 0000000..10786d6
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/README.md
@@ -0,0 +1,11 @@
+**file1_simple_visualization.py** <br>
+![file1_simple_visualization.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file1_simple_visualization.gif)
+
+**file2_circle_curvature.py** <br>
+![file2_circle_curvature.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file2_circle_curvature.gif)
+
+**file3_curvature_interpretation.py** <br>
+![file3_curvature_interpretation.py](https://github.com/saarthdeshpande/FSF-mathematics-python-code-archive/blob/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file3_curvature_interpretation.gif)
+
+**file4_different_curvature_single_curve.py** <br>
+![file4_different_curvature_single_curve.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file4_different_curvature_single_curve.gif)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file1_arc_length.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file1_arc_length.gif
new file mode 100644
index 0000000..bbad112
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file1_arc_length.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file1_arc_length.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file1_arc_length.py
new file mode 100644
index 0000000..7c970e5
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file1_arc_length.py
@@ -0,0 +1,123 @@
+from manimlib.imports import *
+
+
+class arcl(MovingCameraScene):
+ def construct(self):
+ # self.setup()
+ def curve_(x):
+ return 3 - (3653*x**2)/5292 + (2477*x**3)/31752 + (13*x**4)/784 - (17*x**5)/5292 + (17*x**6)/63504
+
+ curve = FunctionGraph(curve_, x_min=-2, x_max=6, stroke_width = 2, color = BLUE).scale(0.1).move_to(ORIGIN)
+ lines = [Line(length = 0.05, color = RED).scale(0.2).move_to(ORIGIN).shift(np.array([-4 + 0.1*i, curve_(-2.5 + 0.1*i), 0])).rotate(-25*DEGREES) for i in range(4)]
+ lines2 = [Line(length = 0.05, color = RED).scale(0.2).move_to(ORIGIN).shift(np.array([-4 + 0.125*i, curve_(-2.5 + 0.1*i), 0])).rotate(-25*DEGREES) for i in range(4, 9)]
+ # lines[0].rotate(-25*DEGREES).shift(np.array([-4,curve_(-2.5), 0]))
+ # lines[1].rotate(-25*DEGREES).shift(np.array([-3.78,curve_(-2.3), 0]))
+ # lines3 = [Line(length = 0.05, color = RED).scale(0.2).move_to(ORIGIN + 1.5*UP + 0.6*RIGHT).shift(np.array([-1 + 0.2*i, -1.5 - 0.2*i, 0])).rotate(30*DEGREES) for i in range(4)]
+ # lines2b = VGroup(*lines3).rotate(-8*DEGREES)
+ # lines4 = [Line(length = 0.05, color = RED).scale(0.2).move_to(ORIGIN + 1.6*UP + 0.5*RIGHT).shift(np.array([-1 + 0.18*i, -1.65 - 0.2*i, 0])).rotate(22*DEGREES) for i in range(4, 9)]
+ # lines5 = [Line(length = 0.05, color = RED).scale(0.2).move_to(ORIGIN + 7*RIGHT).shift(np.array([-4 + 0.1*i, curve_(-2.5 + 0.1*i), 0])).rotate(-25*DEGREES) for i in range(4)]
+ # lines6 = [Line(length = 0.05, color = RED).scale(0.2).move_to(ORIGIN +7.25*RIGHT).shift(np.array([-4 + 0.053*i, curve_(-2.5 + 0.1*i), 0])).rotate(-26*DEGREES) for i in range(4, 9)]
+
+ # lc1 = [Line(length = 0.05, color = RED).scale(0.2).rotate((-25 + i*2) * DEGREES).shift(np.array([-1 + 0.125*i, curve_(-1.5 + 0.1*i), 0])) for i in range(2)]
+ # lc1b = VGroup(*lc1).shift(1.7*LEFT + 0.2*DOWN)
+
+ text = TextMobject(r'$r(t) = \left\langle t, t^{3} - 2t, 0\right\rangle$ \\ $r\prime (t) = \left\langle 1, 3t^{2} - 2, 0\right\rangle$').scale(0.7).shift(3*UP + 4*RIGHT)
+
+ # l = VGroup(*lines, *lines2, lines2b, *lines4, *lines5, *lines6, lc1b).shift(curve.get_center())
+ l = VGroup(*lines, *lines2)
+ arc = Line(lines[3].get_center(), lines2[0].get_center() + np.array([0.005, 0 ,0]), color = GREEN_SCREEN).rotate(12*DEGREES)
+ arctext = TextMobject(r'$ds$', color = GREEN_SCREEN).scale(0.15).next_to(arc.get_center(), 0.001*DOWN + 0.01*RIGHT,buff = 0.01)
+ dy = Arrow(arc.get_start(), np.array([arc.get_start()[0], lines2[0].get_center()[1] + 0.01, 0]), color = YELLOW)
+ dx = Arrow(arc.get_start(), np.array([lines2[0].get_center()[0] - 0.01, arc.get_start()[1], 0]), color = BLUE)
+ dxt = DashedLine(dy.get_end(), dy.get_end() + np.array([0.13, 0 ,0]))
+ dyt = DashedLine(dx.get_end(), dx.get_end() + np.array([0, 0.3 ,0]))
+ dxtext = TextMobject(r'$dx$').scale(0.2).next_to(dx, RIGHT, buff = 0.01)
+ dytext = TextMobject(r'$dy$').scale(0.2).next_to(dy, LEFT, buff = 0.01)
+ formula = TextMobject(r"Consider a very small interval ", r'$ds$. \\', r"Using Pythagoras' theorem, \\", r'$ds$', r" = $\sqrt{(dx)^{2} + (dy)^{2}}$").scale(0.25).shift(5*LEFT + 0.5*UP)
+ formula.set_color_by_tex_to_color_map({
+ "$ds$. \\": GREEN_SCREEN,
+ "$ds$": GREEN_SCREEN
+ })
+
+ formula2 = TextMobject(r'To compute the arc length \\ from $a$ to $b$, we need to \\ sum over all intervals ', r'$ds$').scale(0.25).shift(5.2*LEFT + 0.7*UP)
+ formula2.set_color_by_tex_to_color_map({
+ "$ds$": GREEN_SCREEN
+ })
+
+ formula3 = TextMobject(r'$L = \int_{a}^{b} ds$ \\ $= \int_{a}^{b} \sqrt{(\frac{dx}{dt})^{2} + (\frac{dy}{dt})^{2} + (\frac{dz}{dt})^{2}}\quad dt$').scale(0.25).shift(5.2*LEFT + 0.1*UP)
+
+ bl = DashedLine(lines2[4].get_center(), lines2[4].get_center() + np.array([1,0,0]))
+ blt = TextMobject(r'$b$').scale(0.5).next_to(bl.get_center(), DOWN, buff=0.1)
+ al = DashedLine(lines[0].get_center(), lines[0].get_center() + np.array([1,0,0]))
+ alt = TextMobject(r'$a$').scale(0.5).next_to(al.get_center(), UP, buff=0.1)
+ pts = VGroup(*[bl, blt, al, alt])
+
+ compute = TextMobject(r'To compute the arc length from \\ $t = -1.4$ to $t = -1.1$, \\ summation of small intervals $ds$ \\ is given by $L = \int_{-1.4}^{-1.1} ds$ \\').scale(0.7).shift(6.8*LEFT + 2.5*UP)
+ compute_ = TextMobject(r'L = $ \int_{-1.4}^{-1.1} \sqrt{(\frac{dx}{dt})^{2} + (\frac{dy}{dt})^{2} + (\frac{dz}{dt})^{2}}\quad dt$ \\ = $\int_{-1.4}^{-1.1} \sqrt{1^{2} + (3t^{2} - 2)^{2} + 0^{2}}\quad dt$').scale(0.7).shift(6.8*LEFT + -0.6*DOWN)
+ #compute = VGroup(*[compute, compute_])
+ compute2 = TextMobject(r'$ = \int_{-1.4}^{-1.1} \sqrt{9t^{4} - 12t^{2} + 5}\quad dt$').scale(0.7).shift(6.8*LEFT + 0.7*DOWN)
+ compute3 = TextMobject(r'$L = 0.8693$').scale(0.7).shift(6.8*LEFT + 1.2*DOWN)
+ arclen = compute3.copy()
+ arclen = arclen.scale(0.8).next_to(arc.get_center(), RIGHT, buff = 0.1)
+ dsd = TextMobject(r'We can divide the curve \\ into multiple small arcs ', r'$ds$').scale(0.25).shift(5.2*LEFT + 0.2*UP)
+ dsd.set_color_by_tex_to_color_map({
+ "$ds$": GREEN_SCREEN
+ })
+
+ # 13th sec, consider a v small interval ds, show Pythagoras
+ # reduce text size
+ # then show we can divide curve into small ds
+ # all red ds
+ # To compute arc length, we need to sum over all intervals ds
+ # a and b show and give dashes dy dx for first and last
+ # give dz in formula and show it's zero
+ # Zooom out, Remove red bars, draw yellow line
+ # Consider t = -1.4 to -1.1
+ # at end show l = 0.693 near yellow line, smaller size
+
+ ax1 = Vector((0,1,0), color = YELLOW)
+ ax1l = TextMobject(r'$y$').next_to(ax1, LEFT, buff = 0)
+ ax2 = Vector((1,0,0), color = BLUE)
+ ax2l = TextMobject(r'$x$').next_to(ax2, RIGHT, buff = 0)
+ ax = VGroup(*[ax1, ax1l, ax2, ax2l]).scale(0.6).shift(3*DOWN + 6*LEFT)
+
+ self.play(FadeIn(curve), FadeIn(ax))
+ self.play(ApplyMethod(curve.scale, 10), FadeIn(text))
+ # self.play(FadeIn(l))
+ self.wait(2)
+ self.play(FadeOut(text))
+ self.play(self.camera_frame.set_width, 5,
+ self.camera_frame.move_to, 3.8*LEFT+0.4*DOWN,
+ ax.shift, UP,
+ ax.scale, 0.5, run_time = 4)
+ long = ArcBetweenPoints(lines[1].get_center() + 0.01, lines2[3].get_center(), color = YELLOW, angle = 10*DEGREES).rotate(180*DEGREES)
+
+
+ self.play(Write(formula),FadeIn(VGroup(*[arc, arctext, dy, dx, dxt, dyt, dxtext, dytext])), FadeIn(VGroup(*[lines[3], lines2[0]])))
+ self.wait(2)
+ self.play(ReplacementTransform(formula, dsd), TransformFromCopy(VGroup(*[lines[3], lines2[0]]) , l))
+ #Transform(l, VGroup(*[lines[3], lines2[0]])), )
+ self.wait(2)
+ self.play(ReplacementTransform(dsd, formula2), FadeIn(pts))
+ self.wait(3)
+ self.play(FadeIn(formula3))
+ self.wait(2)
+ self.play(FadeOut(VGroup(*[formula3, l, pts, formula2, arc, arctext, dy, dx, dxt, dyt, dxtext, dytext])))
+ self.play(
+ self.camera_frame.set_width, 15,
+ self.camera_frame.move_to, 3*LEFT,
+ ax.shift, DOWN + 3*LEFT,
+ ax.scale, 2.3,
+ run_time = 4)
+ text = text.shift(2*LEFT)
+ self.play(FadeIn(long), FadeIn(compute), FadeIn(text))
+ self.wait(2)
+ self.play(FadeIn(compute_))
+ self.wait(2)
+ self.play(FadeIn(compute2))
+ self.wait(1)
+ self.play(FadeIn(compute3))
+ self.wait(1)
+ self.play(TransformFromCopy(compute3, arclen))
+ self.wait(2)
+ self.play(FadeOut(VGroup(*[ax, arclen, compute_, curve, text, compute, compute2, compute3, long])))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file2_simple_visualization.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file2_simple_visualization.gif
new file mode 100644
index 0000000..3f7ecd1
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file2_simple_visualization.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file2_simple_visualization.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file2_simple_visualization.py
new file mode 100644
index 0000000..05cad80
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file2_simple_visualization.py
@@ -0,0 +1,91 @@
+from manimlib.imports import *
+
+class a(GraphScene):
+ CONFIG = {
+ "x_min": -3,
+ "x_max": 6,
+ "y_min": -6,
+ "y_max": 10,
+ "graph_origin": ORIGIN
+ }
+ def construct(self):
+ intro = TextMobject('Consider the following curve.')
+ mid = TextMobject(r'Notice how the direction of the unit tangent vector\\changes with respect to the arc length.')
+ outro = TextMobject(r'The rate of change of unit tangent with \\ respect to the arc length $ds$ is called curvature.\\Mathematically, curvature $ = k = \left|{\frac{dT}{ds}}\right|$')
+
+ XTD = self.x_axis_width/(self.x_max- self.x_min)
+ YTD = self.y_axis_height/(self.y_max- self.y_min)
+
+ circle = Circle(radius = 0.95, color = GRAY, fill_opacity = 0.2, fill_color = RED)
+ circle.set_stroke(width = 0.1)
+
+ tgt1 = Arrow((-2.2*XTD,-0.5*YTD,0),(-1*XTD,1,0))
+ tgt2 = Arrow((-1.2*XTD, 1.93*YTD,0),(0*XTD,1.6,0)).scale(1.2)
+ tgt3 = Arrow((-0.3*XTD,3*YTD, 0), (1.5*XTD, 3*YTD,0))
+ tgt4 = Arrow((1.4*XTD, 2*YTD,0),(2.4*XTD, 1*YTD,0)).scale(2.8)
+ tgt5 = Arrow((2.4*XTD, 0, 0), (3.8*XTD,-2*YTD, 0)).scale(1.2).shift(0.26*RIGHT)
+ tgt6 = Arrow((3.8*XTD,-1*YTD, 0), (4.8*XTD, -1*YTD, 0)).scale(2.8).shift(0.26*RIGHT)
+ tgt7 = Arrow((5.3*XTD, 0, 0),(6.3*XTD,1,0)).shift(0.35*LEFT+0.1*DOWN).scale(1.3)
+
+ dot1 = Dot(tgt1.get_start(), color = RED)
+ dot2 = Dot(tgt2.get_start(), color = RED)
+ dot3 = Dot(tgt3.get_start(), color = RED)
+ dot4 = Dot(tgt4.get_start(), color = RED)
+ dot5 = Dot(tgt5.get_start(), color = RED)
+ dot6 = Dot(tgt6.get_start(), color = RED)
+ dot7 = Dot(tgt7.get_start(), color = RED)
+
+ arc = ArcBetweenPoints(dot1.get_center(), dot2.get_center(), color = GREEN_SCREEN, angle = 10*DEGREES).rotate(180*DEGREES)
+
+ dots = VGroup(*[dot1, dot2, dot3, dot4, dot5, dot6, dot7])
+
+ ds = CurvedArrow((-4, 2, 0), (tgt1.get_start() + tgt2.get_start()) / 2, color = YELLOW)
+ ds_text = TextMobject(r'$ds$').next_to(ds, UP, buff = 0.1).shift(1.3*LEFT)
+
+ self.setup_axes(hideaxes=True)
+
+ def curve(x):
+ return 3 - (3653*x**2)/5292 + (2477*x**3)/31752 + (13*x**4)/784 - (17*x**5)/5292 + (17*x**6)/63504
+
+ # parabola_x_out = FunctionGraph(curve, x_min=-2, x_max=6, stroke_width = 2, color = BLUE)
+ parabola_x_out = self.get_graph(curve)
+
+ dot_x = Dot().rotate(PI/2).set_color(YELLOW_E)
+ alpha_x = ValueTracker(-2)
+ vector_x = self.get_tangent_vector(alpha_x.get_value(),parabola_x_out,scale=1.5)
+ dot_x.add_updater(lambda m: m.move_to(vector_x.get_center()))
+ vector_x.add_updater(
+ lambda m: m.become(
+ self.get_tangent_vector(alpha_x.get_value()%1,parabola_x_out,scale=1.5)
+ )
+ )
+
+ self.play(FadeIn(intro))
+ self.wait(2)
+ self.play(FadeOut(intro))
+ self.setup_axes(hideaxes=False)
+ self.play(ShowCreation(parabola_x_out), FadeIn(dots), FadeIn(ds), FadeIn(ds_text), FadeIn(arc))
+ self.wait(2)
+ self.play(FadeOut(self.axes), FadeOut(arc), FadeOut(parabola_x_out),FadeIn(mid), FadeOut(dots), FadeOut(ds), FadeOut(ds_text))
+ self.wait(3)
+ self.play(FadeOut(mid))
+ self.play(FadeIn(self.axes), FadeIn(parabola_x_out), FadeIn(dots))
+ self.add(vector_x)
+ self.play(alpha_x.increment_value, 1, run_time=8, rate_func=linear)
+ self.remove(vector_x)
+ self.play(FadeOut(VGroup(*[self.axes, dots, parabola_x_out])))
+ self.play(FadeIn(outro))
+ self.wait(3)
+ self.play(FadeOut(outro))
+ self.wait(1)
+
+
+
+
+ def get_tangent_vector(self, proportion, curve, dx=0.001, scale=1):
+ coord_i = curve.point_from_proportion(proportion)
+ coord_f = curve.point_from_proportion(proportion + dx)
+ reference_line = Line(coord_i,coord_f)
+ unit_vector = reference_line.get_unit_vector() * scale
+ vector = Arrow(coord_i , coord_i + unit_vector, color = YELLOW, buff=0)
+ return vector
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file3_circle_curvature.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file3_circle_curvature.gif
new file mode 100644
index 0000000..989a3b7
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file3_circle_curvature.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file3_circle_curvature.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file3_circle_curvature.py
new file mode 100644
index 0000000..232ac41
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file3_circle_curvature.py
@@ -0,0 +1,27 @@
+from manimlib.imports import *
+
+class circleC(GraphScene):
+ CONFIG = {
+ "x_min": -6,
+ "x_max": 6,
+ "y_min": -6,
+ "y_max": 6,
+ "graph_origin": ORIGIN,
+ "x_axis_width": 12,
+ "y_axis_height": 12
+ }
+ def construct(self):
+ epiphany = TextMobject(r'Driving a vehicle on which of \\ the two paths would be easier?').scale(0.6).shift(3.5*LEFT + 3*UP)
+ outro = TextMobject(r'The larger path, due to its \\ smaller curvature, since $k = \frac{1}{R}$.').scale(0.6).shift(3.7*LEFT + 3*UP)
+ XTD = self.x_axis_width/(self.x_max- self.x_min)
+ YTD = self.y_axis_height/(self.y_max- self.y_min)
+
+ circle = Circle(radius = 2, color = BLUE)
+ circle2 = Circle(radius = 3, color = GREEN_E)
+
+ self.setup_axes(hideaxes=True)
+ self.play(FadeIn(self.axes), Write(circle, run_time = 2), FadeIn(epiphany))
+ self.play(Write(circle2, run_time = 3))
+ self.play(ReplacementTransform(epiphany, outro))
+ self.wait(2)
+ self.play(FadeOut(VGroup(*[self.axes, circle, circle2, epiphany, outro])))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file4_curvature_interpretation.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file4_curvature_interpretation.gif
new file mode 100644
index 0000000..22a450a
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file4_curvature_interpretation.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file4_curvature_interpretation.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file4_curvature_interpretation.py
new file mode 100644
index 0000000..f10fa26
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file4_curvature_interpretation.py
@@ -0,0 +1,114 @@
+from manimlib.imports import *
+
+class interpretation(ZoomedScene):
+ CONFIG = {
+ "zoomed_display_height": 3,
+ "zoomed_display_width": 3,
+ "zoom_factor": 0.15,
+ "zoomed_display_center": ORIGIN + 4*LEFT + DOWN,
+ }
+ def construct(self):
+
+ tgt = Vector((1, 2, 0), color = YELLOW).shift(0.005*RIGHT + 0.007*DOWN)
+ dot = Dot(tgt.get_start(),color = RED)
+ curve = ParametricFunction(
+ lambda t: np.array([
+ 2*(t**2),
+ 4*t,
+ 0
+ ]), t_min = -5, t_max = 5
+ ).scale(0.3).move_to(ORIGIN + 4*RIGHT).rotate(6*DEGREES)
+
+ ds = ParametricFunction(
+ lambda t: np.array([
+ 2*(t**2),
+ 4*t,
+ 0
+ ]), t_min = 0, t_max = 0.05, color = GREEN_SCREEN
+ ).scale(0.9).shift(3.09*LEFT).rotate(-27.5*DEGREES).move_to(ORIGIN).shift(0.07*UP + 0.05*RIGHT).set_stroke(width=20)
+
+ dsl = TextMobject(r'$ds$', color = GREEN_SCREEN).scale(0.2).next_to(ds, RIGHT, buff = 0)
+
+
+ tgtText = TextMobject(r'$r\prime (t) = \left\langle 1, 2, 0\right\rangle$').next_to(tgt, UP, buff = 0).scale(0.7)
+ tgt2 = DashedLine((0,0,0),(1, 2, 0), color = GRAY).shift(DOWN + 2*RIGHT)
+ circle = Circle(radius = 0.9, color = GREEN_SCREEN).shift(0.85*RIGHT + 0.38*DOWN)
+ circle.set_stroke(opacity = 1)
+ dl = DashedLine(circle.get_center(), dot.get_center())
+ dltext = TextMobject(r'$R = 2.795$').scale(0.5).next_to(circle.get_center(), DOWN, buff = 0.1)
+
+ main = TextMobject(r'r(t) = $\left\langle t^{2}, 2t, 0 \right\rangle\quad r\prime (t) = \left\langle 2t, 2, 0 \right\rangle\quad$ \\ $r\prime\prime (t) = \left\langle 2, 0, 0 \right\rangle$').scale(0.7).shift(3*UP + 3*LEFT)
+ main2 = TextMobject(r'Curvature at an arbitrary point \\ say r(t = 0.5) can be given as: \\ $\kappa = \frac{1}{R} = \frac{1}{2.795} = 0.357$').scale(0.7).shift(3.5*LEFT)
+ main3 = TextMobject(r'The ', 'tangent', r' and ', 'normal', r' vectors \\ can be represented as:').scale(0.7).shift(3.5*LEFT)
+ main3.set_color_by_tex_to_color_map({
+ "tangent": YELLOW,
+ "normal": BLUE
+ })
+ main4 = TextMobject(r'These vectors travel along \\ a small interval ', r'$ds$').scale(0.7).shift(1.5*UP + 3*LEFT)
+ main4.set_color_by_tex_to_color_map({
+ "$ds$": GREEN_SCREEN
+ })
+
+ main5 = TextMobject(r'$\kappa = 0.357$').scale(0.7).shift(main.get_center() + np.array([2.4,-0.18,0]))
+
+ nm = Vector((2, -1, 0), color = BLUE).shift(0.005*RIGHT + 0.007*DOWN)
+ nmText = TextMobject(r'$r\prime\prime (t) = \left\langle 2,0,0\right\rangle$').next_to(nm, DOWN+RIGHT, buff = 0).scale(0.7)
+ nm2 = DashedLine((0,0,0),(2, -1, 0), color = GRAY).shift(2*UP + RIGHT)
+ square = Square(fill_color = WHITE, fill_opacity = 0.2).rotate(63*DEGREES).shift(0.5*UP +1.5*RIGHT).scale(1.1)
+ square.set_stroke(width = 0.1)
+ square2 = Square(fill_color = PINK, fill_opacity = 0.2).scale(0.55).rotate(63*DEGREES).move_to((square.get_center() - dot.get_center()) / 2)
+ square2.set_stroke(width = 0.1)
+ arrow = CurvedArrow(square.get_center() + np.array([2,1,0]), square.get_center() + np.array([0.5,0,0]))
+ arrowText = TextMobject(r'$r\prime (t)\times r\prime\prime (t) = 4$').next_to(arrow.get_start(), DOWN+1*RIGHT, buff = 0).scale(0.7)
+
+ text1 = TextMobject(r'$\left|\frac{dT}{ds}\right| = \frac{\left|\frac{dT}{dt}\right|}{\left|\frac{ds}{dt}\right|}$').shift(UP+3*LEFT).scale(0.7)
+ text2 = TextMobject(r'$\left|\frac{dT}{ds}\right| = \frac{\frac{r\prime\prime (t)}{\left| r\prime (t)\right|}\times\frac{r\prime (t)}{\left| r\prime (t)\right|}}{\left|r\prime (t)\right|}$').next_to(text1, DOWN, buff = 0.1).scale(0.7)
+ text3 = TextMobject(r'$= \frac{4}{(4t^{2} + 4)^{\frac{3}{2}}}$ \\ $= \frac{1}{2\sqrt{(1 + (0.5)^{2})^{3}}}$').next_to(text2, DOWN, buff = 0.1).scale(0.7)
+ text4 = TextMobject(r'$ = 0.357$').scale(0.7).next_to(text3, DOWN, buff = 0.2)
+ unit = VGroup(*[tgt, tgt2, nm, nm2])
+
+ tgt2text = TextMobject(r'$\frac{r\prime (t)}{\left| r\prime (t)\right|}$').shift(1.1*UP).scale(0.7).rotate(63*DEGREES )
+ nm2text = TextMobject(r'$\frac{r\prime\prime (t)}{\left| r\prime (t)\right|}$').scale(0.7).shift(0.7*RIGHT+0.8*DOWN).rotate(-25*DEGREES)
+ unit2 = unit.copy().scale(0.5).shift(0.75*LEFT+0.25*DOWN)
+
+ self.play(FadeIn(curve), FadeIn(main))
+ self.wait(1)
+ self.play(ApplyMethod(curve.scale, 3), ApplyMethod(curve.shift, ORIGIN + 3.31*RIGHT))
+ # self.wait(2)
+ self.play(FadeIn(main2), FadeIn(dot))
+ self.play(FadeIn(circle), FadeIn(dl), FadeIn(dltext))
+ self.wait()
+ self.play(ReplacementTransform(main2, main5), FadeIn(main3), FadeOut(circle), FadeOut(dl), FadeOut(dltext), FadeIn(VGroup(*[tgt, tgtText])))
+ self.wait(1)
+ self.play(FadeIn(VGroup(*[nm, nmText])))
+ self.wait(1)
+ self.remove(dot)
+ self.setup()
+ #self.camera_frame.set_width(4)
+ self.activate_zooming(animate = True)
+ self.play(FadeIn(ds), FadeIn(dsl), FadeOut(main3))
+ self.wait(1)
+ self.play(FadeIn(main4))
+ self.play(ApplyMethod(tgt.shift, 0.16*UP + 0.09*RIGHT), ApplyMethod(nm.shift, 0.16*UP + 0.09*RIGHT), run_time = 5)
+ self.wait(1)
+ self.play(FadeOut(ds), FadeOut(dsl), FadeOut(main4), FadeOut(self.zoomed_display, run_time = 1), FadeOut(self.zoomed_camera.frame, run_time = 1))
+ # tgt = tgt.shift(0.16*DOWN + 0.08*LEFT)
+ # nm = nm.shift(0.16*DOWN + 0.08*LEFT)
+ self.play(ApplyMethod(tgt.shift, 0.16*DOWN + 0.09*LEFT, run_time = 1), ApplyMethod(nm.shift, 0.16*DOWN + 0.09*LEFT, run_time = 1))
+ self.play(FadeIn(dot), FadeIn(VGroup(*[tgt2, nm2])))
+ self.wait(1)
+ self.play(FadeIn(VGroup(*[square, arrow, arrowText])))
+ self.wait(1)
+ self.play(FadeIn(unit2), FadeIn(square2))
+ self.wait(1)
+ self.play(FadeIn(VGroup(*[tgt2text, nm2text])))
+ self.wait(1)
+ self.play(FadeIn(text1))
+ self.wait(1)
+ self.play(FadeIn(text2))
+ self.wait(1)
+ self.play(FadeIn(text3))
+ self.wait(1)
+ self.play(FadeIn(text4))
+ self.wait(2)
+ self.play(FadeOut(VGroup(*[main, main5, square2, curve, dot, tgt2text, nm2text, text1, text2, text3, text4, tgt, tgtText,nm, nmText,tgt2, nm2,square, arrow, arrowText,unit2])))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file5_different_curvature_single_curve.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file5_different_curvature_single_curve.gif
new file mode 100644
index 0000000..3b78b5f
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file5_different_curvature_single_curve.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file5_different_curvature_single_curve.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file5_different_curvature_single_curve.py
new file mode 100644
index 0000000..0dc06bb
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/arc-length-and-curvature/file5_different_curvature_single_curve.py
@@ -0,0 +1,76 @@
+from manimlib.imports import *
+
+class GR(GraphScene):
+ CONFIG = {
+ "x_axis_label": "",
+ "y_axis_label": "",
+ "x_min": -4,
+ "x_max": 6,
+ "y_min": -6,
+ "y_max": 10,
+ "graph_origin": ORIGIN,
+ 'x_tick_frequency': 20,
+ 'y_tick_frequency': 20
+ }
+
+ def construct(self):
+
+ self.setup_axes()
+ def curve(x):
+ return 3 - (3653*x**2)/5292 + (277*x**3)/31752 + (13*x**4)/784 - (17*x**5)/5292 + (170*x**6)/63504
+
+ graph = FunctionGraph(curve, x_min=-2, x_max=6, stroke_width = 2, color = BLUE)
+
+ tracker = ValueTracker(-2)
+
+ text = TextMobject(r'$\because R_{1} > R_{2}$, the curvature at \\ point $P_{1}$ is less than that \\ at point $P_{2}$ as $\kappa = \frac{1}{R}$').shift(3.2*LEFT+3*UP).scale(0.6)
+
+ dot1 = Dot((0,3,0), color = YELLOW)
+ dot1label = TextMobject(r'$P_{1}$').next_to(dot1, UP+RIGHT, buff = 0.1)
+ dot2 = Dot((2.9,-0.47, 0), color = YELLOW)
+ dot2label = TextMobject(r'$P_{2}$').next_to(dot2, DOWN, buff = 0.1)
+ dots = VGroup(*[dot1, dot2, dot1label, dot2label])
+
+ def get_tangent_line():
+ line = Line(
+ ORIGIN, 2 * RIGHT,
+ color=RED,
+ stroke_width=4,
+ )
+ dx = 0.0001
+
+ x = tracker.get_value()
+ p0 = np.array([x-dx,curve(x-dx),0])
+ p1 = np.array([x, curve(x), 0])
+ p2 = np.array([x + dx, curve(x + dx), 0])
+
+ angle = angle_of_vector(p2 - p1)
+ line.rotate(angle)
+ line.move_to(p0)
+ return line
+
+ circle1 = Circle(radius = 0.8, color = GREY, opacity = 0.2).shift(2.2*UP)
+ tgt1 = Line((-2,3,0), (2,3,0), color = GREY, opacity = 0.2).scale(0.4)
+
+ r1 = Line(circle1.get_center(), circle1.get_center() + np.array([0,0.8,0]), color=GREEN_SCREEN)
+ r1label = TextMobject(r'$R_{1}$',color=WHITE).next_to(r1, RIGHT, buff = 0.1).scale(0.6)
+
+ curvature1 = VGroup(*[circle1, tgt1, r1, r1label])
+
+ circle2 = Circle(radius = 0.2, color = GREY, opacity = 0.2).shift(0.3*DOWN + 2.9*RIGHT)
+ tgt2 = Line((4,-2,0), (6, -2, 0), color = GREY, opacity = 0.2).scale(0.5).shift(2.1*LEFT + 1.5*UP)
+
+ r2 = Line(circle2.get_center(), circle2.get_center() - np.array([0,0.2,0]), color=GREEN_SCREEN)
+ r2label = TextMobject(r'$R_{2}$', color=WHITE).next_to(r2.get_start(), np.array([0,0,0]), buff = 0).scale(0.4)
+
+ curvature2 = VGroup(*[circle2, tgt2, r2, r2label])
+
+ line = always_redraw(get_tangent_line)
+
+ self.add(graph, line, dots, text)
+ self.wait(1.2)
+ self.play(tracker.set_value, 4, rate_func=smooth, run_time=10)
+ self.play(FadeIn(curvature1), FadeIn(curvature2))
+ self.wait(2)
+ self.play(FadeOut(VGroup(*[curvature1, curvature2, graph, self.axes, line, dots, text])))
+ self.wait()
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/README.md b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/README.md
new file mode 100644
index 0000000..29d2f6a
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/README.md
@@ -0,0 +1,14 @@
+**file1_line_eqn.py**<br>
+![file1_line_eqn.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file1_line_eqn.gif)
+
+**file2_point_normal_form_plane.py**<br>
+![file2_point_normal_form_plane.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file2_point_normal_form_plane.gif)
+
+**file3_intercept_form_plane.py**<br>
+![file3_intercept_form_plane.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file3_intercept_form_plane.gif)
+
+**file4_3d_plane.py**<br>
+![file4_3d_plane.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file4_3d_plane.gif)
+
+**file5_vector_form_line.py**<br>
+![file5_vector_form_line.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file5_vector_form_line.gif)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file1_line_eqn.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file1_line_eqn.gif
new file mode 100644
index 0000000..a8a301a
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file1_line_eqn.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file1_line_eqn.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file1_line_eqn.py
new file mode 100644
index 0000000..402775b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file1_line_eqn.py
@@ -0,0 +1,26 @@
+from manimlib.imports import *
+
+class three(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.set_camera_orientation(phi=14.25* DEGREES,theta=0*DEGREES,distance=8)
+ self.play(FadeIn(axes))
+
+ plane = ParametricSurface(
+ lambda u,v: np.array([
+ 6,
+ 8*v,
+ 3*u
+ ]), u_min = -0.8, u_max = 0.8, fill_opacity = 0.4).rotate(45*DEGREES).move_to(ORIGIN).shift(RIGHT+UP)
+ d2text = TextMobject(r'$\mathbb{R}^{2}: y = mx + c$').shift(3*LEFT + 2*UP).rotate(np.pi/2)
+ d3text = TextMobject(r'$\mathbb{R}^{3}: y = mx + c$').shift(4*RIGHT+3*UP)
+ self.play(FadeIn(plane), FadeIn(d2text))
+ self.wait(3)
+ self.play(FadeOut(d2text))
+ self.move_camera(phi = 60*DEGREES, theta=45*DEGREES,run_time=3)
+ self.begin_ambient_camera_rotation(rate=0.02)
+ self.add_fixed_in_frame_mobjects(d3text)
+ self.play(FadeIn(d3text))
+ self.wait(3)
+ self.play(FadeOut(d3text), FadeOut(plane), FadeOut(axes))
+ self.wait()
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file2_point_normal_form_plane.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file2_point_normal_form_plane.gif
new file mode 100644
index 0000000..e651be0
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file2_point_normal_form_plane.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file2_point_normal_form_plane.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file2_point_normal_form_plane.py
new file mode 100644
index 0000000..122a9ff
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file2_point_normal_form_plane.py
@@ -0,0 +1,39 @@
+from manimlib.imports import *
+
+class pointnormal(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+
+ self.set_camera_orientation(phi = 75*DEGREES, theta=45*DEGREES)
+ normal = Arrow((0,-0.15,-0.25), (-3,0,3), color = YELLOW)
+ plane1 = Polygon(np.array([1,0,2]),np.array([-1,2.5,1]),np.array([-3,2,1]),np.array([-1,-1,2]), color = GREEN_E, fill_color = WHITE, fill_opacity=0.5)
+ plane2 = Polygon(np.array([1,0,2]),np.array([-1,2.5,1]),np.array([-3,2,1]),np.array([-1,-1,2]), color = BLUE, fill_color = WHITE, fill_opacity=0.3)
+ normalLabel = TextMobject(r'$\overrightarrow{n}$').shift((2,2.5,0))
+ pointLabel = TextMobject(r'$P$').shift((2,1.2,0))
+ xlabel = TextMobject(r'$x$').shift(4.5*LEFT + 1.7*DOWN)
+ ylabel = TextMobject(r'$y$').shift(4.5*RIGHT + 1.8*DOWN)
+ zlabel = TextMobject(r'$z$').shift(3.3*UP+0.5*RIGHT)
+
+ normaltext = TextMobject(r'Consider an arbitrary \\ normal vector $\overrightarrow{n}$').scale(0.6).shift(2*UP + 2.5*LEFT)
+ planetext = TextMobject(r'A single vector is normal \\ to infinitely many planes.').scale(0.6).shift(2*UP + 2.5*LEFT)
+ pointtext = TextMobject(r'Given a fixed point $P$, \\ a plane is obtained as:').scale(0.6).shift(2*UP + 2.5*LEFT)
+
+ point = Dot(color = RED).shift((1.6,1.3,0))
+ self.play(FadeIn(axes))
+ self.add_fixed_in_frame_mobjects(xlabel, ylabel, zlabel)
+ self.wait(1)
+ self.play(FadeIn(normal))
+ self.add_fixed_in_frame_mobjects(normalLabel, normaltext)
+ self.play(FadeIn(normaltext))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(planetext)
+ self.play(ReplacementTransform(normaltext, planetext), run_time=0.01)
+ self.play(MoveAlongPath(plane1, normal), run_time = 6)
+ self.add_fixed_in_frame_mobjects(pointtext)
+ self.play(ReplacementTransform(planetext, pointtext))
+ self.add_fixed_in_frame_mobjects(point, pointLabel)
+ self.wait(1)
+ self.play(Transform(plane1, plane2))
+ self.wait(2)
+ self.play(FadeOut(axes), FadeOut(plane2), FadeOut(plane1), FadeOut(point), FadeOut(pointLabel), FadeOut(normal), FadeOut(normalLabel), FadeOut(planetext), FadeOut(pointtext), FadeOut(normaltext), FadeOut(VGroup(*[xlabel, ylabel, zlabel])))
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file3_intercept_form_plane.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file3_intercept_form_plane.gif
new file mode 100644
index 0000000..a8b7d75
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file3_intercept_form_plane.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file3_intercept_form_plane.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file3_intercept_form_plane.py
new file mode 100644
index 0000000..258ac3c
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file3_intercept_form_plane.py
@@ -0,0 +1,29 @@
+from manimlib.imports import *
+
+class pointnormal(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes(x_min = 0, y_min = 0, z_min = 0)
+ self.set_camera_orientation(phi = 75*DEGREES, theta=45*DEGREES)
+
+ plane1 = Polygon(np.array([2,-3,2.5]),np.array([-1.45,2,2.5]),np.array([-0.5,4.5,-0.1]),np.array([3.5,-1,-0.2]), fill_color = WHITE, fill_opacity=0.3)
+
+ xlabel = TextMobject(r'$x$').shift(5*LEFT + 1.5*DOWN)
+ ylabel = TextMobject(r'$y$').shift(5*RIGHT + 1.5*DOWN)
+ zlabel = TextMobject(r'$z$').shift(3.3*UP + 0.5*LEFT)
+
+ zintercept = Dot().shift(2.5*UP)
+ zinterceptlabel = TextMobject(r'$(0,0,c\prime)$').shift(2.8*UP + RIGHT).scale(0.7)
+
+ yintercept = Dot().shift(3.7*RIGHT + 0.925*DOWN)
+ yinterceptlabel = TextMobject(r'$(0,b\prime ,0)$').shift(3.7*RIGHT+1.5*DOWN).scale(0.7)
+
+ xintercept = Dot().shift(2.9*LEFT + 0.75*DOWN)
+ xinterceptlabel = TextMobject(r'$(a\prime ,0,0)$').shift(3*LEFT+1.3*DOWN).scale(0.7)
+
+ self.play(FadeIn(axes), FadeIn(plane1))
+ self.add_fixed_in_frame_mobjects(xlabel, ylabel, zlabel, zintercept, zinterceptlabel, yintercept, yinterceptlabel, xintercept, xinterceptlabel)
+ self.wait(2)
+ self.remove(zintercept, zinterceptlabel, yintercept, yinterceptlabel, xintercept, xinterceptlabel, xlabel, ylabel, zlabel)
+ self.begin_ambient_camera_rotation(rate=0.5)
+ self.wait(5)
+ self.play(FadeOut(axes), FadeOut(plane1))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file4_3d_plane.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file4_3d_plane.gif
new file mode 100644
index 0000000..b4c259e
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file4_3d_plane.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file4_3d_plane.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file4_3d_plane.py
new file mode 100644
index 0000000..26ad825
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file4_3d_plane.py
@@ -0,0 +1,49 @@
+from manimlib.imports import *
+
+class pointnormal(ThreeDScene):
+ CONFIG = {
+ 'x_axis_label': '$x$',
+ 'y_axis_label': '$y$'
+ }
+ def construct(self):
+ axes = ThreeDAxes()
+ axes.add(axes.get_axis_labels())
+ self.set_camera_orientation(phi = 75*DEGREES, theta=45*DEGREES)
+
+ plane = Polygon(
+ np.array([2,0,2.7]),
+ np.array([0,0,0.4]),
+ np.array([-3.2,0,0.55]),
+ np.array([-3,-2,2.5]),
+ fill_color = WHITE, fill_opacity = 0.25)
+
+ normal = Arrow((0.25,2,0), (1.5,3.5,0))
+ normalLabel = TextMobject(r'$\overrightarrow{n}$').shift((1.5,2.8,0))
+
+ point = Dot(color = RED).shift((1.6,1.3,0))
+ pointLabel = TextMobject(r'$P_{0}$').shift((2,1.2,0))
+
+ point2 = Dot(color = RED).shift((-0.2,1.8,0))
+ point2Label = TextMobject(r'$P$').shift((-0.3,2,0))
+
+ arrow1 = Arrow((0,-0.25,-0.2), (-2.55,0,1), color = YELLOW).set_stroke(width=3)
+ arrow2 = Arrow((0,0,-0.25), (0.3,0,2), color = YELLOW).set_stroke(width=3)
+ res = Arrow((1.8,1.23,0),(-0.35,1.85,0), color = BLUE).set_stroke(width=3)
+
+ arrow1label = TextMobject(r'$\overrightarrow{r_{0}}$').next_to(arrow2, UP).shift(RIGHT + 0.16*DOWN).scale(0.7)
+ arrow2label = TextMobject(r'$\overrightarrow{r}$').next_to(arrow2, UP).shift(0.7*LEFT).scale(0.7)
+ reslabel = TextMobject(r'$\overrightarrow{r} - \overrightarrow{r_{0}}$').next_to(arrow2, UP).shift(0.7*RIGHT + 1.2*UP).scale(0.7)
+
+ self.play(FadeIn(axes), FadeIn(plane))
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(normal, normalLabel)
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(point, pointLabel)
+ self.add_fixed_in_frame_mobjects(point2, point2Label)
+ self.play(Write(arrow1), Write(arrow2))
+ self.add_fixed_in_frame_mobjects(arrow2label, arrow1label)
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(res, reslabel)
+ self.play(Write(res), FadeIn(reslabel))
+ self.wait(1)
+ self.play(FadeOut(axes), FadeOut(plane), FadeOut(point), FadeOut(pointLabel), FadeOut(normal), FadeOut(normalLabel), FadeOut(point2), FadeOut(point2Label), FadeOut(arrow1label), FadeOut(arrow2label), FadeOut(reslabel), FadeOut(arrow1), FadeOut(arrow2), FadeOut(res)) \ No newline at end of file
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file5_vector_form_line.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file5_vector_form_line.gif
new file mode 100644
index 0000000..b6fdb51
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file5_vector_form_line.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file5_vector_form_line.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file5_vector_form_line.py
new file mode 100644
index 0000000..e25c4eb
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/equations-of-planes-and-lines/file5_vector_form_line.py
@@ -0,0 +1,47 @@
+from manimlib.imports import *
+
+class line_(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ xlabel = TextMobject(r'$x$').shift(4.5*LEFT + 1.7*DOWN)
+ ylabel = TextMobject(r'$y$').shift(4.5*RIGHT + 1.8*DOWN)
+ zlabel = TextMobject(r'$z$').shift(3.3*UP+0.5*RIGHT)
+
+ self.set_camera_orientation(phi = 75*DEGREES, theta=45*DEGREES)
+ pointLabel = TextMobject(r'$P$').shift((2.28,2.12,0)).scale(0.7)
+ point = Dot(color = RED).shift((1.95,1.9,0))
+
+ vlabel = TextMobject(r'$\overrightarrow{v}$').shift((0.5,1.3,0)).scale(0.7)
+
+ inf_text = TextMobject(r'Infinitely many lines pass \\ through a single point.').scale(0.6).shift(2*UP + 2.5*LEFT)
+ pointtext = TextMobject(r'Given a direction vector $\overrightarrow{v}$, \\ a line is obtained as:').scale(0.6).shift(2*UP + 2.5*LEFT)
+
+
+ line = Line((0.7,0.7,0), (2,3,0)).shift(0.06*UP+0.6*RIGHT)
+ v = Vector((0.8,1,0), color = GREEN_E)
+ #finalLine = Line((-1.56,0,0.5),(-4,0,2.42), color = YELLOW)
+ finalLine = Line((1,0.8,0),(3,3,0), color = YELLOW).shift(0.05*LEFT)
+ self.play(FadeIn(axes))
+ self.add_fixed_in_frame_mobjects(zlabel, ylabel, xlabel)
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(point, pointLabel)
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(inf_text)
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(line)
+
+ for i in range(9):
+ self.play(ApplyMethod(line.rotate, -np.pi/12), run_time = 0.7)
+ if i == 8:
+ self.add_fixed_in_frame_mobjects(pointtext)
+ self.play(ReplacementTransform(inf_text, pointtext))
+ self.add_fixed_in_frame_mobjects(v, vlabel)
+ # if i == 13:
+ # self.add_fixed_in_frame_mobjects(pointtext)
+
+ self.add_fixed_in_frame_mobjects(finalLine)
+ self.play(FadeIn(finalLine))
+ self.play(Transform(line, finalLine), run_time = 4)
+ #self.play(FadeOut(line), FadeIn(finalLine))
+ self.wait(1.5)
+ self.play(FadeOut(VGroup(*[axes, xlabel, ylabel, zlabel, finalLine, v, vlabel, point, pointLabel, pointtext, line])))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/README.md b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/README.md
new file mode 100644
index 0000000..8a47a0e
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/README.md
@@ -0,0 +1,11 @@
+**file1_parametric_circle..py** <br>
+![file1_parametric_circle.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file1_parametric_circle.gif)
+
+**file2_cycloid_manim.py** <br>
+![file2_cycloid_manim.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file2_cycloid_manim.gif)
+
+**file3_brachistochrone.py** <br>
+![file3_brachistochrone.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file3_brachistochrone.gif)
+
+**file4_helix_visualization.py** <br>
+![file4_helix_visualization.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file4_helix_visualization.gif)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file1_parametric_circle.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file1_parametric_circle.gif
new file mode 100644
index 0000000..732b6bb
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file1_parametric_circle.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file1_parametric_circle.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file1_parametric_circle.py
new file mode 100644
index 0000000..37d079e
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file1_parametric_circle.py
@@ -0,0 +1,81 @@
+from manimlib.imports import *
+
+class parametricCircle(ThreeDScene, GraphScene):
+ def construct(self):
+ self.x_min = -5
+ self.y_min = -5
+ self.graph_origin = ORIGIN
+ self.x_max = 5
+ self.y_max = 5
+ self.x_axis_label = ""
+ self.y_axis_label = ""
+ self.x_axis_width = 10
+ self.y_axis_height = 10
+ self.y_tick_frequency = 1.9
+ self.x_tick_frequency = 1.4
+
+ axes = []
+
+ # self.setup_axes()
+ ax = Axes(y_tick_frequency = 1, x_axis_width = 10, y_axis_height = 10, y_min = -5, x_max = 5, y_max = 5, x_tick_frequency = 1, x_axis_label = "", y_axis_label = "", x_min = -5, )
+ ax.scale(0.5).shift(3*LEFT)
+ axes.append(ax)
+ self.setup_axes()
+ self.axes.scale(0.3).shift(3*RIGHT + 2*UP)
+ axes.append(self.axes)
+ self.setup_axes()
+ self.axes.scale(0.3).shift(3*RIGHT + 2*DOWN)
+ axes.append(self.axes)
+
+ axes = VGroup(*axes)
+ t_value = ValueTracker(-3.14)
+ t_tex = DecimalNumber(t_value.get_value()).add_updater(lambda v: v.set_value(t_value.get_value()))
+ t_label = TexMobject("t = ")
+ group = VGroup(t_tex,t_label).shift(3*DOWN)
+ t_label.next_to(t_tex,LEFT, buff=0.2,aligned_edge=t_label.get_bottom())
+
+ asint_text = TextMobject(r'$x = a\sin{t}$').scale(0.7).shift(4*RIGHT + 3*UP)
+ xlabel1 = TextMobject(r'$x$').shift(3.3*RIGHT + 3.7*UP).scale(0.7)
+ tlabel1 = TextMobject(r'$t$').shift(4.8*RIGHT + 2*UP).scale(0.7)
+ up_text = VGroup(*[asint_text, xlabel1, tlabel1])
+ asint = ParametricFunction(
+ lambda t: np.array([
+ t,
+ 2*np.sin(t),
+ 0
+ ]), t_min = -np.pi, t_max = np.pi, color = GREEN_E
+ ).shift(3*RIGHT + 2*UP).scale(0.4)
+
+ acost_text = TextMobject(r'$y = a\cos{t}$').scale(0.7).shift(4*RIGHT + DOWN)
+ ylabel1 = TextMobject(r'$y$').shift(3.3*RIGHT+0.3*DOWN).scale(0.7)
+ tlabel2 = TextMobject(r'$t$').shift(4.8*RIGHT + 2*DOWN).scale(0.7)
+ down_text = VGroup(*[acost_text, ylabel1, tlabel2])
+ acost = ParametricFunction(
+ lambda t: np.array([
+ t,
+ 2*np.cos(t),
+ 0
+ ]), t_min = -np.pi, t_max = np.pi, color = BLUE
+ ).shift(3*RIGHT + 2*DOWN).scale(0.4)
+
+ up_dot = Dot(color = RED)
+ down_dot = Dot(color = RED)
+ circle_dot = Dot(color = RED)
+
+ ylabel2 = TextMobject(r'$y$').scale(0.7).shift(3*UP + 3*LEFT)
+ xlabel2 = TextMobject(r'$x$').scale(0.7)
+ ellipse_text = TextMobject(r'$x = a\sin{t}$ \\ $y = a\cos{t}$').scale(0.7).shift(2*UP + 1.3*LEFT)
+ main_text = VGroup(*[xlabel2, ylabel2, ellipse_text])
+ circle = ParametricFunction(
+ lambda t: np.array([
+ np.cos(t),
+ np.sin(t),
+ 0
+ ]), t_min = -np.pi, t_max = np.pi, color = WHITE
+ ).shift(3*LEFT)
+ self.play(FadeIn(axes), FadeIn(asint), FadeIn(acost), FadeIn(circle), FadeIn(up_text), FadeIn(down_text), FadeIn(main_text), FadeIn(group))
+ self.wait(1)
+ self.play(MoveAlongPath(up_dot, asint, run_time = 7), MoveAlongPath(down_dot, acost, run_time = 7), MoveAlongPath(circle_dot, circle, run_time = 7), t_value.set_value,3.14, rate_func=linear, run_time=7)
+ self.wait(1)
+ self.play(FadeOut(VGroup(*[axes, asint, acost, circle, up_text, down_text, main_text, up_dot, down_dot, circle_dot, group])))
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file2_cycloid_manim.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file2_cycloid_manim.gif
new file mode 100644
index 0000000..e68b841
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file2_cycloid_manim.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file2_cycloid_manim.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file2_cycloid_manim.py
new file mode 100644
index 0000000..7b6c0d1
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file2_cycloid_manim.py
@@ -0,0 +1,46 @@
+from manimlib.imports import *
+
+t_offset = 0
+c_t = 0
+
+class cycloid(Scene):
+ def construct(self):
+
+ cycl = ParametricFunction(
+ lambda t: np.array([
+ t - np.sin(t),
+ 1 - np.cos(t),
+ 0
+ ]), t_min = -2.75*np.pi, t_max = 3*np.pi, color = BLUE
+ ).shift(0.73*RIGHT)
+ wheel_radius = 1
+ wheel_function_path = lambda x : 0 + wheel_radius
+
+ line = FunctionGraph(lambda x : 0, color = BLACK)
+ wheel_path = FunctionGraph(wheel_function_path)
+
+ velocity_factor = 0.25
+ frame_rate = self.camera.frame_rate
+ self.dt = 1 / frame_rate
+
+ wheel = Circle(color = BLACK, radius = 1)
+ dot = Dot(radius = 0.16, color = RED)
+ #dot.move_to(wheel.get_arc_center() + np.array([0,2,0]))
+
+ def update_dot(mob,dt):
+ global t_offset,c_t
+ if dt == 0 and c_t == 0:
+ rate= - velocity_factor * self.dt
+ c_t += 1
+ else:
+ rate = - dt*velocity_factor
+ if dt > 0:
+ c_t = 0
+ mob.move_to(wheel.point_from_proportion(((t_offset + rate))%1))
+ t_offset += rate
+ #self.add(mob.copy())
+
+ #dot.move_to(wheel.get_arc_center() + np.array([0,2,0]))
+ dot.add_updater(update_dot)
+ self.add(wheel,dot, line, cycl)
+ self.play(MoveAlongPath(wheel, wheel_path, run_time = 9, rate_func = linear))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file3_brachistochrone.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file3_brachistochrone.gif
new file mode 100644
index 0000000..8daf4c0
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file3_brachistochrone.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file3_brachistochrone.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file3_brachistochrone.py
new file mode 100644
index 0000000..633e500
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file3_brachistochrone.py
@@ -0,0 +1,13 @@
+from manimlib.imports import *
+
+class brachistochrone(Scene):
+ def construct(self):
+ curve = ParametricFunction(
+ lambda t: np.array([
+ 0.5*(t - np.sin(t)),
+ 0.5*(1 - np.cos(t)),
+ 0
+ ]), t_max = np.pi
+ ).scale(5).rotate(540*DEGREES)
+ dot = Dot(color = RED, radius = 0.2)
+ self.play(FadeIn(curve), MoveAlongPath(dot, curve, run_time = 2))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file4_helix_visualization.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file4_helix_visualization.gif
new file mode 100644
index 0000000..16d2509
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file4_helix_visualization.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file4_helix_visualization.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file4_helix_visualization.py
new file mode 100644
index 0000000..eddd3fe
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/general-parametric-curves/file4_helix_visualization.py
@@ -0,0 +1,31 @@
+from manimlib.imports import *
+
+class helix_(ThreeDScene):
+ CONFIG = {
+ "x_min": -6,
+ "x_max": 6,
+ "y_min": -6,
+ "y_max": 6,
+ "graph_origin": ORIGIN
+ }
+ def construct(self):
+ axes = ThreeDAxes()
+ helix = ParametricFunction(
+ lambda t: np.array([
+ 1.5*np.cos(TAU*t),
+ 1.5*np.sin(TAU*t),
+ 2*t
+ ]), t_min = -1, t_max = 2, color = RED
+ )
+ cylinder = ParametricSurface(
+ lambda u, v: np.array([
+ 1.5*np.cos(TAU*v),
+ 1.5*np.sin(TAU*v),
+ 2*u
+ ]), u_min = -1, u_max = 2, fill_opacity = -.4, fill_color = WHITE, color = WHITE
+ )
+ self.set_camera_orientation(phi=60* DEGREES,theta=45*DEGREES)
+ self.play(FadeIn(axes), FadeIn(cylinder), ShowCreation(helix, run_time = 4))
+ self.begin_ambient_camera_rotation(rate=0.5)
+ self.wait(5)
+ self.play(FadeOut(axes),FadeOut(helix), FadeOut(cylinder))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/README.md b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/README.md
new file mode 100644
index 0000000..42f5df1
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/README.md
@@ -0,0 +1,11 @@
+**file1_parametric_ellipse.py** <br>
+![file1_parametric_ellipse.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file1_parametric_ellipse.gif)
+
+**file2_parametric_helix.py** <br>
+![file2_parametric_helix.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file2_parametric_helix.gif)
+
+**file3_circletosphere.py** <br>
+![file3_circletosphere.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file3_circletosphere.gif)
+
+**file4_cone.py** <br>
+![file4_cone.py](https://raw.githubusercontent.com/saarthdeshpande/FSF-mathematics-python-code-archive/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file4_cone.gif)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file1_parametric_ellipse.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file1_parametric_ellipse.gif
new file mode 100644
index 0000000..90c0349
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file1_parametric_ellipse.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file1_parametric_ellipse.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file1_parametric_ellipse.py
new file mode 100644
index 0000000..1ce29d7
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file1_parametric_ellipse.py
@@ -0,0 +1,78 @@
+from manimlib.imports import *
+
+class parametricEllipse(ThreeDScene, GraphScene):
+ def construct(self):
+ self.x_min = -5
+ self.y_min = -5
+ self.graph_origin = ORIGIN
+ self.x_max = 5
+ self.y_max = 5
+ self.x_axis_label = ""
+ self.y_axis_label = ""
+ self.x_axis_width = 10
+ self.y_axis_height = 10
+
+ axes = []
+
+ self.setup_axes()
+ self.axes.scale(0.5).shift(3*LEFT)
+ axes.append(self.axes)
+ self.setup_axes()
+ self.axes.scale(0.3).shift(3*RIGHT + 2*UP)
+ axes.append(self.axes)
+ self.setup_axes()
+ self.axes.scale(0.3).shift(3*RIGHT + 2*DOWN)
+ axes.append(self.axes)
+
+ axes = VGroup(*axes)
+ t_value = ValueTracker(-3.14)
+ t_tex = DecimalNumber(t_value.get_value()).add_updater(lambda v: v.set_value(t_value.get_value()))
+ t_label = TexMobject("t = ")
+ group = VGroup(t_tex,t_label).shift(3*DOWN)
+ t_label.next_to(t_tex,LEFT, buff=0.2,aligned_edge=t_label.get_bottom())
+
+ asint_text = TextMobject(r'$x = a\sin{t}$').scale(0.7).shift(4*RIGHT + 3*UP)
+ xlabel1 = TextMobject(r'$x$').shift(3.3*RIGHT + 3.7*UP).scale(0.7)
+ tlabel1 = TextMobject(r'$t$').shift(4.8*RIGHT + 2*UP).scale(0.7)
+ up_text = VGroup(*[asint_text, xlabel1, tlabel1])
+ asint = ParametricFunction(
+ lambda t: np.array([
+ t,
+ np.sin(t),
+ 0
+ ]), t_min = -np.pi, t_max = np.pi, color = GREEN_E
+ ).shift(3*RIGHT + 2*UP).scale(0.4)
+
+ bcost_text = TextMobject(r'$y = b\cos{t}$').scale(0.7).shift(4*RIGHT + DOWN)
+ ylabel1 = TextMobject(r'$y$').shift(3.3*RIGHT+0.3*DOWN).scale(0.7)
+ tlabel2 = TextMobject(r'$t$').shift(4.8*RIGHT + 2*DOWN).scale(0.7)
+ down_text = VGroup(*[bcost_text, ylabel1, tlabel2])
+ bcost = ParametricFunction(
+ lambda t: np.array([
+ t,
+ 1.5*np.cos(t),
+ 0
+ ]), t_min = -np.pi, t_max = np.pi, color = BLUE
+ ).shift(3*RIGHT + 2*DOWN).scale(0.4)
+
+ up_dot = Dot(color = RED)
+ down_dot = Dot(color = RED)
+ ellipse_dot = Dot(color = RED)
+
+ ylabel2 = TextMobject(r'$y$').scale(0.7).shift(3*UP + 3*LEFT)
+ xlabel2 = TextMobject(r'$x$').scale(0.7)
+ ellipse_text = TextMobject(r'$x = a\sin{t}$ \\ $y = b\cos{t}$').scale(0.7).shift(2*UP + 1.3*LEFT)
+ main_text = VGroup(*[xlabel2, ylabel2, ellipse_text])
+ ellipse = ParametricFunction(
+ lambda t: np.array([
+ 1.5*np.cos(t),
+ np.sin(t),
+ 0
+ ]), t_min = -np.pi, t_max = np.pi, color = WHITE
+ ).shift(3*LEFT)
+ self.play(FadeIn(axes), FadeIn(asint), FadeIn(bcost), FadeIn(ellipse), FadeIn(up_text), FadeIn(down_text), FadeIn(main_text), FadeIn(group))
+ self.wait(1)
+ self.play(MoveAlongPath(up_dot, asint, run_time = 7), MoveAlongPath(down_dot, bcost, run_time = 7), MoveAlongPath(ellipse_dot, ellipse, run_time = 7), t_value.set_value,3.14, rate_func=linear, run_time=7)
+ self.wait(1)
+ self.play(FadeOut(VGroup(*[axes, asint, bcost, ellipse, up_text, down_text, main_text, up_dot, down_dot, ellipse_dot, group])))
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file2_parametric_helix.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file2_parametric_helix.gif
new file mode 100644
index 0000000..4f349b1
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file2_parametric_helix.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file2_parametric_helix.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file2_parametric_helix.py
new file mode 100644
index 0000000..3791752
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file2_parametric_helix.py
@@ -0,0 +1,91 @@
+from manimlib.imports import *
+
+class parametricHelix(ThreeDScene, GraphScene):
+ def construct(self):
+ self.x_min = -5
+ self.y_min = -4
+ self.graph_origin = ORIGIN
+ self.x_max = 5
+ self.y_max = 4
+ self.x_axis_label = ""
+ self.y_axis_label = ""
+ self.x_axis_width = 10
+ self.y_axis_height = 7.5
+ ax1 = ThreeDAxes().scale(0.65).shift(2.6*RIGHT+DOWN+np.array([0,0,0.5]))
+ axes_group = []
+
+ self.setup_axes()
+ self.axes.shift(3*RIGHT + 2*UP).scale(0.3)
+ axes_group.append(self.axes)
+
+ self.setup_axes()
+ self.axes.shift(3*RIGHT + 2*DOWN).scale(0.3)
+ axes_group.append(self.axes)
+
+ axes_group = VGroup(*axes_group)
+
+ asint_text = TextMobject(r'$x = a\sin{t}$').scale(0.7).shift(4*RIGHT + 3*UP)
+ xlabel1 = TextMobject(r'$x$').shift(3.3*RIGHT + 3.7*UP).scale(0.7)
+ tlabel1 = TextMobject(r'$t$').shift(5*RIGHT + 2*UP).scale(0.7)
+ up_text = VGroup(*[asint_text, xlabel1, tlabel1])
+ asint = ParametricFunction(
+ lambda t: np.array([
+ t,
+ np.sin(t),
+ 0
+ ]), t_min = -4*np.pi, t_max = 4*np.pi, color = GREEN_E
+ ).shift(3*RIGHT + 2*UP).scale(0.12)
+
+ acost_text = TextMobject(r'$y = a\cos{t}$').scale(0.7).shift(4*RIGHT + DOWN)
+ ylabel1 = TextMobject(r'$y$').shift(3.3*RIGHT+0.3*DOWN).scale(0.7)
+ tlabel2 = TextMobject(r'$t$').shift(5*RIGHT + 2*DOWN).scale(0.7)
+ down_text = VGroup(*[acost_text, ylabel1, tlabel2])
+ acost = ParametricFunction(
+ lambda t: np.array([
+ t,
+ np.cos(t),
+ 0
+ ]), t_min = -4*np.pi, t_max = 4*np.pi, color = BLUE
+ ).shift(3*RIGHT + 2*DOWN).scale(0.12)
+
+ up_dot = Dot(color = RED).scale(0.6)
+ down_dot = Dot(color = RED).scale(0.6)
+ helix_dot = Dot(radius = 0.16, color = RED)
+
+ zlabel = TextMobject(r'$z$').scale(0.7).shift(3*UP + 2.8*LEFT)
+ ylabel2 = TextMobject(r'$y$').scale(0.7).shift(0.3*DOWN+0.15*RIGHT)
+ xlabel2 = TextMobject(r'$x$').scale(0.7).shift(0.5*DOWN + 6.4*LEFT)
+ helix_text = TextMobject(r'$x = a\sin{t}$ \\ $y = a\cos{t}$ \\ $z = ct$').scale(0.7).shift(2.3*UP + 1.3*LEFT)
+ main_text = VGroup(*[xlabel2, ylabel2, zlabel, helix_text])
+ helix = ParametricFunction(
+ lambda t: np.array([
+ np.cos(TAU*t),
+ np.sin(TAU*t),
+ 0.4*t
+ ]), t_min = -2*np.pi/3, t_max = 1.8*np.pi/3, color = WHITE
+ ).shift(ax1.get_center())
+
+ self.set_camera_orientation(phi = 75*DEGREES, theta=45*DEGREES)
+
+ t_tracker = ValueTracker(-12.56)
+ t=t_tracker.get_value
+
+ t_label = TexMobject(
+ "t = ",color=WHITE
+ ).next_to(helix_text,DOWN, buff=0.2).scale(0.6)
+
+ t_text = always_redraw(
+ lambda: DecimalNumber(
+ t(),
+ color=WHITE,
+ ).next_to(t_label, RIGHT, buff=0.2)
+ ).scale(0.6)
+
+ group = VGroup(t_text,t_label).scale(1.5).move_to(ORIGIN).shift(2*DOWN)
+ self.add_fixed_in_frame_mobjects(axes_group, main_text, up_text, down_text, acost, asint)
+ self.play(FadeIn(ax1), FadeIn(axes_group), FadeIn(asint), FadeIn(acost), FadeIn(helix), FadeIn(up_text), FadeIn(down_text), FadeIn(main_text))
+ #self.begin_ambient_camera_rotation(rate = 0.06)
+ self.add_fixed_in_frame_mobjects(up_dot, down_dot, group)
+ self.play(MoveAlongPath(up_dot, asint, run_time = 8), MoveAlongPath(down_dot, acost, run_time = 8), MoveAlongPath(helix_dot, helix, run_time = 8), t_tracker.set_value,12.56, rate_func=linear, run_time=8)
+ self.play(FadeOut(VGroup(*[ax1, axes_group, asint, acost, helix, up_text, down_text, main_text, up_dot, down_dot, helix_dot, group])))
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file3_circletosphere.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file3_circletosphere.gif
new file mode 100644
index 0000000..d6a8afc
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file3_circletosphere.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file3_circletosphere.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file3_circletosphere.py
new file mode 100644
index 0000000..6c0e810
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file3_circletosphere.py
@@ -0,0 +1,45 @@
+from manimlib.imports import *
+
+class sphere(GraphScene, ThreeDScene):
+ CONFIG = {
+ 'x_min': -10,
+ 'x_max': 10,
+ 'y_min': -10,
+ 'y_max': 10,
+ 'graph_origin': ORIGIN,
+ "x_axis_width": 10,
+ "y_axis_height": 10,
+ }
+ def construct(self):
+ XTD = self.x_axis_width/(self.x_max- self.x_min)
+ YTD = self.y_axis_height/(self.y_max- self.y_min)
+ circleeqn = TextMobject(r'Hence, $x^{2} + y^{2} = 2(r^{2} - u^{2})$')
+ plottext = TextMobject(r'$x = \sqrt{r^{2} - u^{2}}cos\theta$ \\ $y = \sqrt{r^{2} - u^{2}}sin\theta$').shift(2*UP + 3*RIGHT)
+
+
+ self.setup_axes()
+ self.play(FadeIn(self.axes), FadeIn(plottext))
+
+ dots = []
+ for t in range(19):
+ dot = Dot().shift((3*XTD*np.cos(t), 3*YTD*np.sin(t),0))
+ dots.append(dot)
+ self.play(FadeIn(dot), run_time = 0.2)
+ dots = VGroup(*dots)
+ circle = Circle(radius = 3*XTD).set_color(WHITE).set_stroke(width = 10)
+ self.play(FadeIn(circle), FadeOut(dots), FadeOut(plottext))
+ self.wait(2)
+
+
+ axes = ThreeDAxes(**self.CONFIG)
+ sph = Sphere(radius = 3).scale(0.5)
+ text2 = TextMobject(r'Setting $u = 3$,\\$z = u$').shift(4*YTD*UP + 5*XTD*RIGHT)
+
+ self.play(Transform(self.axes,axes), ReplacementTransform(circle, sph))
+ self.add(text2)
+ self.wait(2)
+ self.remove(text2)
+ self.move_camera(phi = 60*DEGREES, theta=45*DEGREES,run_time=5)
+ self.begin_ambient_camera_rotation(rate=0.03)
+ self.play(FadeOut(axes), FadeOut(sph), FadeOut(self.axes))
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file4_cone.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file4_cone.gif
new file mode 100644
index 0000000..b126d20
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file4_cone.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file4_cone.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file4_cone.py
new file mode 100644
index 0000000..e6ae1c6
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/space-curves/file4_cone.py
@@ -0,0 +1,33 @@
+from manimlib.imports import *
+
+class cone(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ eqn = TextMobject(r'$z^{2} = x^{2} + y^{2}$')
+
+ conecurve = ParametricFunction(
+ lambda t: np.array([
+ t*np.cos(TAU*t),
+ t*np.sin(TAU*t),
+ t
+ ]), t_min = -2.6, t_max = 2.6
+ ).scale(0.85)
+
+ conesurface = ParametricSurface(
+ lambda u,v: np.array([
+ 3*np.sin(u)*np.cos(TAU*v),
+ 3*np.sin(u)*np.sin(TAU*v),
+ 2.7*u
+ ]), u_min = -1
+ ).scale(0.85)
+
+ self.play(FadeIn(eqn))
+ self.wait(2)
+ self.play(FadeOut(eqn))
+ self.set_camera_orientation(phi = 75*DEGREES, theta=50*DEGREES)
+ self.play(FadeIn(axes), ShowCreation(conecurve, run_time = 3))
+ self.play(FadeOut(conecurve), FadeIn(conesurface))
+ self.begin_ambient_camera_rotation(rate=0.03)
+ self.wait(2)
+ self.play(FadeOut(axes), FadeOut(conesurface))
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/README.md b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/README.md
new file mode 100644
index 0000000..7874f43
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/README.md
@@ -0,0 +1,15 @@
+**file1_tnb_creation.py**<br>
+![file1_tnb_creation.py](https://github.com/saarthdeshpande/FSF-mathematics-python-code-archive/blob/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file1_tnb_creation.gif)
+
+
+**file2_tnb_basic.py** <br>
+![file2_tnb_basic.py](https://github.com/saarthdeshpande/FSF-mathematics-python-code-archive/blob/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file2_tnb_basic.gif)
+
+**file3_tnb_frame_manim.py** <br>
+![file3_tnb_frame_manim.py](https://github.com/saarthdeshpande/FSF-mathematics-python-code-archive/blob/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file3_tnb_frame_manim.gif)
+
+**file4_fs1.py** <br>
+![file4_fs1.py](https://github.com/saarthdeshpande/FSF-mathematics-python-code-archive/blob/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file4_fs1.gif)
+
+**file5_fs2.py** <br>
+![file5_fs2.py](https://github.com/saarthdeshpande/FSF-mathematics-python-code-archive/blob/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file5_fs2.gif)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file1_tnb_creation.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file1_tnb_creation.gif
new file mode 100644
index 0000000..eae8686
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file1_tnb_creation.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file1_tnb_creation.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file1_tnb_creation.py
new file mode 100644
index 0000000..80372ee
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file1_tnb_creation.py
@@ -0,0 +1,66 @@
+from manimlib.imports import *
+
+class tnb(ThreeDScene):
+ def construct(self):
+ self.set_camera_orientation(phi = 75*DEGREES, theta=45*DEGREES)
+
+ helix1 = ParametricFunction(
+ lambda t: np.array([
+ np.cos(TAU*t),
+ np.sin(TAU*t),
+ 0.4*t
+ ]), t_min = -2*np.pi/3, t_max = -1.638*np.pi/3, color = WHITE
+ )
+
+ helix2 = ParametricFunction(
+ lambda t: np.array([
+ np.cos(TAU*t),
+ np.sin(TAU*t),
+ 0.4*t
+ ]), t_min = -1.638*np.pi/3, t_max = -1.33*np.pi/3, color = WHITE
+ )
+
+ pointText = TextMobject(r'Consider an arbitrary point \\ on the given curve.').scale(0.8).shift(1.5*UP)
+ tgtText = TextMobject(r'Unit', ' tangent ', r'vector at \\ this point is given as:').scale(0.8).shift(1.5*UP)
+ tgtText.set_color_by_tex_to_color_map({
+ "tangent": YELLOW
+ })
+ normalText = TextMobject(r'Unit', ' normal ', r'vector at \\ this point is given as:').scale(0.8).shift(1.5*UP)
+ normalText.set_color_by_tex_to_color_map({
+ "normal": BLUE
+ })
+ planeText = TextMobject(r'$\overrightarrow{T}$ and $\overrightarrow{N}$ \\ prescribe a plane.').scale(0.8).shift(1.5*UP)
+ bnmText = TextMobject(r'The vector normal to this plane \\ is called the', ' binormal ', 'vector.').scale(0.8).shift(1.5*UP)
+ bnmText.set_color_by_tex_to_color_map({
+ "binormal": GREEN_E
+ })
+
+ dot1 = Dot(np.array([np.cos(-np.pi/3), np.sin(-np.pi/3), -0.4*np.pi/3]) + np.array([0,0.2,0]), radius = 0.16, color=RED)
+ tgt1 = Arrow((0,0,0), (-2,-0.55,0), color = YELLOW).shift(dot1.get_center() + np.array([0.18,0.04,0]))
+ nm1 = Arrow((0,0,0), (0.4,-2,0), color = BLUE).shift(dot1.get_center() + np.array([0,0.26,0]))
+ bnm1 = Arrow((0,0,0), (0,2,0), color=GREEN_E).shift(2.1*RIGHT+2*DOWN)
+ plane1 = Square(color = DARK_BROWN, fill_color = WHITE, fill_opacity=0.3).shift(dot1.get_center() + np.array([-0.4, -0.6, 0])).rotate(13*DEGREES).scale(1.2)
+ point1 = VGroup(*[dot1, tgt1, nm1, plane1]).scale(0.8).shift(np.array([1,4.86,0])).rotate(-15*DEGREES)
+
+
+
+ helix = VGroup(*[helix1, helix2])
+ self.play(FadeIn(helix))
+ self.play(ApplyMethod(helix.scale, 4))
+ self.add_fixed_in_frame_mobjects(pointText)
+ self.play(FadeIn(dot1), FadeIn(pointText))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(tgtText)
+ self.play(Write(tgt1), ReplacementTransform(pointText, tgtText))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(normalText)
+ self.play(Write(nm1), ReplacementTransform(tgtText, normalText))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(planeText)
+ self.play(FadeIn(plane1), ReplacementTransform(normalText, planeText))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(bnmText)
+ self.add_fixed_in_frame_mobjects(bnm1)
+ self.play(ReplacementTransform(planeText, bnmText), Write(bnm1))
+ self.wait(2)
+ self.play(FadeOut(VGroup(*[helix, bnm1, bnmText, dot1, tgt1, nm1, plane1])))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file2_tnb_basic.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file2_tnb_basic.gif
new file mode 100644
index 0000000..67aaea2
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file2_tnb_basic.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file2_tnb_basic.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file2_tnb_basic.py
new file mode 100644
index 0000000..c870210
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file2_tnb_basic.py
@@ -0,0 +1,36 @@
+from manimlib.imports import *
+
+class tnb(ThreeDScene):
+ def construct(self):
+ t = TextMobject(r'T', color = YELLOW)
+ n = TextMobject(r'N', color = BLUE).next_to(t, RIGHT, buff=0)
+ b = TextMobject(r'B', color = GREEN_E).next_to(n, RIGHT, buff=0)
+ frame = TextMobject(r'Frame').next_to(b, RIGHT, buff=0.2)
+ f1 = TextMobject(r'$\overrightarrow{B}$ ', color = GREEN_E)
+ f2 = TextMobject(r' = $\overrightarrow{T}$', color = YELLOW).next_to(f1, RIGHT, buff=0.2)
+ f3 = TextMobject(r'$\times\overrightarrow{N}$', color = BLUE).next_to(f2, RIGHT, buff=0.1)
+ formula = VGroup(*[f1, f2, f3]).move_to(ORIGIN).shift(3*UP)
+
+ # text = VGroup(*[t,n,b,frame]).move_to(ORIGIN).shift(3*UP)
+ curve = ParametricFunction(
+ lambda t: np.array([
+ np.sin(TAU*t),
+ np.cos(TAU*t),
+ 0
+ ])
+ ).scale(2.5)
+ dot = Dot(color = RED).scale(1.5).shift(1.05*LEFT)
+ tgt = Arrow(dot.get_center(), (-2, 2, 0), color = YELLOW).shift(0.3*DOWN + 0.09*RIGHT)
+ normal = Arrow(tgt.get_start(), (1, 1, 0), color = BLUE).shift(0.2*LEFT + 0.05*DOWN)
+ binormal = Arrow(dot.get_center() - np.array([0,0,0.3]), (tgt.get_start()[0], tgt.get_start()[1],2), color = GREEN)
+ square = Square(color = DARK_BROWN, fill_color = WHITE, fill_opacity=0.3).move_to(tgt.get_start()).rotate(27*DEGREES).shift(UP+0.4*RIGHT).scale(1.2)
+ group = VGroup(*[dot, tgt, normal, square, binormal]).shift(np.array([-1.24,-1,0]))
+
+ self.add_fixed_in_frame_mobjects(formula)
+ self.add(curve, group)
+ self.wait(1)
+ self.move_camera(phi = 75*DEGREES, theta=45*DEGREES, run_time = 2)
+ self.add_fixed_in_frame_mobjects(formula)
+ self.begin_ambient_camera_rotation(rate = 0.5)
+ self.wait(5)
+ self.play(FadeOut(VGroup(*[formula, curve, dot, tgt, normal, square, binormal])))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file3_tnb_frame_manim.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file3_tnb_frame_manim.gif
new file mode 100644
index 0000000..78e3aa3
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file3_tnb_frame_manim.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file3_tnb_frame_manim.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file3_tnb_frame_manim.py
new file mode 100644
index 0000000..091c1e2
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file3_tnb_frame_manim.py
@@ -0,0 +1,218 @@
+from manimlib.imports import *
+
+class tnb(ThreeDScene):
+ def construct(self):
+ self.set_camera_orientation(phi = 75*DEGREES, theta=45*DEGREES)
+
+ t = TextMobject(r'T', color = YELLOW)
+ n = TextMobject(r'N', color = BLUE).next_to(t, RIGHT, buff=0)
+ b = TextMobject(r'B', color = GREEN_E).next_to(n, RIGHT, buff=0)
+ frame = TextMobject(r'Frame').next_to(b, RIGHT, buff=0.2)
+
+ text = VGroup(*[t,n,b,frame]).move_to(ORIGIN).shift(3*UP)
+
+ c1 = TextMobject(r'$r(t) = \left\langle\cos{t}, \sin{t}, 0.4t\right\rangle\quad r\prime (t) =\left\langle -\sin{t}, \cos{t}, 0.4\right\rangle$').next_to(text, DOWN, buff = 0.1).scale(0.7)
+
+
+ helix1 = ParametricFunction(
+ lambda t: np.array([
+ np.cos(TAU*t),
+ np.sin(TAU*t),
+ 0.4*t
+ ]), t_min = -2*np.pi/3, t_max = -1.638*np.pi/3, color = WHITE
+ )
+
+ helix2 = ParametricFunction(
+ lambda t: np.array([
+ np.cos(TAU*t),
+ np.sin(TAU*t),
+ 0.4*t
+ ]), t_min = -1.638*np.pi/3, t_max = -1.33*np.pi/3, color = WHITE
+ )
+
+ helix3 = ParametricFunction(
+ lambda t: np.array([
+ np.cos(TAU*t),
+ np.sin(TAU*t),
+ 0.4*t
+ ]), t_min = -1.33*np.pi/3, t_max = -np.pi/3, color = WHITE
+ )
+
+ helix4 = ParametricFunction(
+ lambda t: np.array([
+ np.cos(TAU*t),
+ np.sin(TAU*t),
+ 0.4*t
+ ]), t_min = -np.pi/3, t_max = -1.3*np.pi/6, color = WHITE
+ )
+
+ helix5 = ParametricFunction(
+ lambda t: np.array([
+ np.cos(TAU*t),
+ np.sin(TAU*t),
+ 0.4*t
+ ]), t_min = -1.3*np.pi/6, t_max = 0, color = WHITE
+ )
+
+ helix_dot = Dot(radius = 0.16, color = RED)
+
+ t_tracker = ValueTracker(-2*np.pi/3)
+ t=t_tracker.get_value
+
+ # t_label = TexMobject(
+ # "t = ",color=WHITE
+ # ).next_to(helix1,DOWN, buff=0.2).scale(0.6)
+
+ cval1 = TextMobject(r'r(').next_to(c1, DOWN+16.5*LEFT, buff = 0.1).scale(0.7)
+
+ t_text = always_redraw(
+ lambda: DecimalNumber(
+ t(),
+ color=WHITE,
+ ).next_to(cval1, RIGHT, buff=0.05).scale(0.7)
+ ).scale(0.6)
+
+
+ cval2 = always_redraw(
+ lambda: TextMobject(r') = $\left\langle$').scale(0.7).next_to(t_text, RIGHT, buff = 0.05)
+ )
+
+ cos = always_redraw(
+ lambda: DecimalNumber(
+ np.cos(t()),
+ color=WHITE,
+ ).next_to(cval2, RIGHT, buff=0.1).scale(0.7)
+ ).scale(0.6)
+
+ sin = always_redraw(
+ lambda: DecimalNumber(
+ np.sin(t()),
+ color=WHITE,
+ ).next_to(cos, RIGHT, buff=0.1).scale(0.7)
+ ).scale(0.6)
+
+ zpart = always_redraw(
+ lambda: DecimalNumber(
+ 0.4* t(),
+ color=WHITE,
+ ).next_to(sin, RIGHT, buff=0.1).scale(0.7)
+ ).scale(0.6)
+
+ cvalend = always_redraw(
+ lambda: TextMobject(r' $\right\rangle$').next_to(zpart, RIGHT, buff = 0.2).scale(0.7)
+ ).scale(0.6)
+
+
+ valgroup = VGroup(*[cval1, cval2,cos,sin,zpart, cvalend])
+
+ rp1 = always_redraw(
+ lambda: TextMobject(r'$r\prime ($').scale(0.7).next_to(cvalend, RIGHT, buff = 0.6)
+ )
+
+ t_text2 = always_redraw(
+ lambda: DecimalNumber(
+ t(),
+ color=WHITE,
+ ).next_to(rp1, RIGHT, buff=0.05).scale(0.7)
+ ).scale(0.6)
+
+ rp2 = always_redraw(
+ lambda: TextMobject(r') = $\left\langle$').scale(0.7).next_to(t_text2, RIGHT, buff = 0.05)
+ )
+
+ rps = always_redraw(
+ lambda: DecimalNumber(
+ -np.sin(t()),
+ color=WHITE,
+ ).next_to(rp2, RIGHT, buff=0.1).scale(0.7)
+ ).scale(0.6)
+
+
+ rpc = always_redraw(
+ lambda: DecimalNumber(
+ np.cos(t()),
+ color=WHITE,
+ ).next_to(rps, RIGHT, buff=0.1).scale(0.7)
+ ).scale(0.6)
+
+
+ const = always_redraw(
+ lambda: TextMobject(r'0.4 $\right\rangle$').next_to(rpc, RIGHT, buff = 0.2).scale(0.7)
+ ).scale(0.6).shift(0.1*DOWN)
+
+ val2group = VGroup(*[rp1, rp2, rps, rpc, const])
+
+ #group = VGroup(t_text, t_text2).scale(1.5).move_to(ORIGIN).shift(3.7*DOWN)
+
+
+ dot0 = Dot(np.array([np.cos(-2*np.pi/3), np.sin(-2*np.pi/3), -0.8*np.pi/3]), radius = 0.16, color=RED).shift(np.array([4.65,0,-0.8]))
+ tgt0 = Arrow((0,0,0), (1,2,0), color = YELLOW).shift(dot0.get_center() - np.array([0.04,0.2,0]))
+ nm0 = Arrow((0,0,0), (-2,1,0), color = BLUE).shift(dot0.get_center() + np.array([0.3,0,0]))
+ bnm0 = Arrow((0,0,0), (0,2,0), color = GREEN_E).shift(6.1*LEFT + 3*DOWN)
+ plane0 = Square(color = DARK_BROWN, fill_color = WHITE, fill_opacity=0.3).shift(dot0.get_center() + np.array([-0.35, 0.85, 0])).scale(1.2).rotate(65*DEGREES)
+ point0 = VGroup(*[dot0, tgt0, nm0, bnm0, plane0]).scale(0.8).shift(np.array([1,0,0]))
+
+ dot1 = Dot(np.array([np.cos(-np.pi/3), np.sin(-np.pi/3), -0.4*np.pi/3]) + np.array([0,0.2,0]), radius = 0.16, color=RED)
+ tgt1 = Arrow((0,0,0), (-2,-0.55,0), color = YELLOW).shift(dot1.get_center() + np.array([0.18,0.04,0]))
+ nm1 = Arrow((0,0,0), (0.4,-2,0), color = BLUE).shift(dot1.get_center() + np.array([0,0.26,0]))
+ bnm1 = Arrow((0,0,0), (0,2,0), color=GREEN_E).shift(3.68*RIGHT+2.48*DOWN)
+ plane1 = Square(color = DARK_BROWN, fill_color = WHITE, fill_opacity=0.3).shift(dot1.get_center() + np.array([-0.4, -0.6, 0])).rotate(13*DEGREES).scale(1.2)
+ point1 = VGroup(*[dot1, tgt1, nm1, plane1]).scale(0.8).shift(np.array([1,6.25,0]))
+
+ dot2 = Dot(np.array([np.cos(-np.pi/6), np.sin(-np.pi/6), -0.2*np.pi/3]) - np.array([1.9,0,0]), radius=0.16,color=RED)
+ tgt2 = Arrow((0,0,0), (1,-2,0), color = YELLOW).shift(dot2.get_center() + np.array([-0.2,0.2,0]))
+ nm2 = Arrow((0,0,0), (2,1,0), color = BLUE).shift(dot2.get_center() + np.array([-0.2,-0.06,0]))
+ bnm2 = Arrow((0,0,0), (0,2,0), color=GREEN_E).shift(0.4*RIGHT + 0.16*DOWN)
+ plane2 = Square(color = DARK_BROWN, fill_color = WHITE, fill_opacity=0.3).shift(dot2.get_center() + np.array([0.92, -0.5, 0])).rotate(23*DEGREES).scale(1.2)
+ point2 = VGroup(*[dot2, tgt2, nm2, bnm2, plane2])
+
+ helix = VGroup(*[helix1, helix2, helix3, helix4, helix5])
+ self.add_fixed_in_frame_mobjects(text, c1)
+ self.play(FadeIn(helix), FadeIn(text), FadeIn(c1))
+ self.play(ApplyMethod(helix.scale, 4))
+ self.add_fixed_in_frame_mobjects(bnm0, valgroup, val2group, t_text, t_text2)
+ self.play(FadeIn(point0), FadeIn(t_text), FadeIn(t_text2), FadeIn(valgroup), FadeIn(val2group))
+ self.play(ApplyMethod(point0.set_color, GRAY, opacity = 0.1, run_time = 0.5), MoveAlongPath(helix_dot, helix1, run_time=5), t_tracker.set_value,-1.638*np.pi/3, rate_func=linear, run_time=5)
+
+ self.add_fixed_in_frame_mobjects(bnm1)
+ self.play(FadeIn(point1))
+ self.play(ApplyMethod(point1.set_color, GRAY, opacity = 0.1, run_time = 0.5), ApplyMethod(bnm1.set_color, GRAY, opacity = 0.1, run_time = 0.5), MoveAlongPath(helix_dot, helix2, run_time = 5), t_tracker.set_value,-1.33*np.pi/3, rate_func=linear, run_time=5)
+
+ self.add_fixed_in_frame_mobjects(bnm2)
+ self.play(FadeIn(point2))
+ self.play(ApplyMethod(point2.set_color, GRAY, opacity = 0.1, run_time = 0.5), MoveAlongPath(helix_dot, helix3, run_time=5), t_tracker.set_value,-np.pi/3, rate_func=linear, run_time=5)
+
+ dot3 = Dot(np.array([np.cos(-np.pi/3), np.sin(-np.pi/3), -0.4*np.pi/3]) + np.array([3.3,-0.25,0]), radius = 0.16, color=RED)
+ tgt3 = Arrow((0,0,0), (0,2,0), color = YELLOW).shift(helix_dot.get_center() - np.array([-0.05,0.2,0]))
+ nm3 = Arrow((0,0,0), (-2,0,0), color = BLUE).shift(helix_dot.get_center() + np.array([0.25,0,0]))
+ bnm3 = Arrow((0,0,0), (0,2,0), color = GREEN_E).shift(3.87*LEFT + 1.24*DOWN)
+ plane3 = Square(color = DARK_BROWN, fill_color = WHITE, fill_opacity=0.3).shift(helix_dot.get_center() + np.array([-0.5, 0.62, 0]))
+ point3 = VGroup(*[dot3, tgt3, nm3, bnm3, plane3]).shift(np.array([0,0,0]))
+
+ dot4 = Dot(np.array([np.cos(-np.pi/12), np.sin(-np.pi/12), -0.1*np.pi/3]) + np.array([-3.4,3.4,0]), radius = 0.16, color=RED)
+ tgt4 = Arrow((0,0,0), (-2,-0.85,0), color = YELLOW).shift(dot4.get_center() - np.array([-0.05,0,0]))
+ nm4 = Arrow((0,0,0), (0.8,-2,0), color = BLUE).shift(dot4.get_center() + np.array([-0.1,0.25,0]))
+ bnm4 = Arrow((0,0,0), (0,2,0), color = GREEN_E).shift(4.03*RIGHT + 0.5*DOWN)
+ plane4 = Square(color = DARK_BROWN, fill_color = WHITE, fill_opacity=0.3).shift(dot4.get_center() + np.array([-0.4,-1,0])).rotate(22*DEGREES).scale(1.2)
+ point4 = VGroup(*[dot4, tgt4, nm4, bnm4, plane4])
+
+ dot5 = Dot((1,0,0) + np.array([2.3,-1,1]))
+ tgt5 = Arrow((0,0,0), (0,2,0), color = YELLOW).shift(dot5.get_center() - np.array([-0.05,0.2,0]))
+ nm5 = Arrow((0,0,0), (-2,0,0), color = BLUE).shift(dot5.get_center() + np.array([0.25,0,0]))
+ bnm5 = Arrow((0,0,0), (0,2,0), color = GREEN_E).shift(3.34*LEFT+0.3*UP)
+ plane5 = Square(color = DARK_BROWN, fill_color = WHITE, fill_opacity=0.3).shift(dot5.get_center() + np.array([-0.5,0.5,0]))
+ point5 = VGroup(*[tgt5, nm5, bnm5, plane5])
+
+ self.add_fixed_in_frame_mobjects(bnm3)
+ self.play(FadeIn(point3))
+ self.play(ApplyMethod(point3.set_color, GRAY, opacity = 0.1, run_time = 0.5), MoveAlongPath(helix_dot, helix4, run_time=5), t_tracker.set_value,-1.3*np.pi/6, rate_func=linear, run_time=5)
+
+ self.add_fixed_in_frame_mobjects(bnm4)
+ self.play(FadeIn(point4))
+ self.play(ApplyMethod(point4.set_color, GRAY, opacity = 0.1, run_time = 0.5), MoveAlongPath(helix_dot, helix5, run_time=5), t_tracker.set_value,0, rate_func=linear, run_time=5)
+
+ self.add_fixed_in_frame_mobjects(bnm5)
+ self.play(FadeIn(point5))
+ self.wait(2)
+
+ self.play(FadeOut(VGroup(*[valgroup, val2group, t_text, t_text2, c1, text, helix, bnm1, point0, point1, point2, point3, point4, point5, helix_dot])))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file4_fs1.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file4_fs1.py
new file mode 100644
index 0000000..f3f5a9c
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file4_fs1.py
@@ -0,0 +1,91 @@
+from manimlib.imports import *
+class fs1(GraphScene):
+ CONFIG = {
+ "x_min": -2,
+ "x_max": 2,
+ "y_min": -6,
+ "y_max": 6,
+ "graph_origin": ORIGIN
+ }
+ def construct(self):
+
+ text = TextMobject(r'$\frac{dT}{ds} = \kappa N$ \\ $\frac{dT}{ds}$ gives the direction of N, \\ while $\kappa$ gives its magnitude.').scale(0.7).shift(3*UP + 3*LEFT)
+
+ self.setup_axes()
+ def curve_(x):
+ return x**3 - 2*x
+
+ def nm(x):
+ return abs(6 * x / ((9*(x**4) - 6*(x**2) + 5)**1.5))
+
+ figure = self.get_graph(curve_)
+
+
+ dot = Dot().rotate(PI/2)
+ alpha = ValueTracker(0)
+ t2_ = ValueTracker(-2)
+ t2 = t2_.get_value
+ t = alpha.get_value
+ vector_x = self.get_tangent_vector(t(),figure,scale=2)
+ vector_y = self.get_normal_vector(t(),figure,scale=2)
+
+ kappa = TextMobject(r'$\kappa = $').scale(0.7).shift(3*DOWN + 3*RIGHT)
+
+ t_text = always_redraw(
+ lambda: DecimalNumber(
+ nm(t2()),
+ color=WHITE,
+ ).scale(0.7).next_to(kappa)
+ ).scale(0.6)
+
+ self.play(
+ ShowCreation(figure),
+ GrowFromCenter(dot),
+ GrowArrow(vector_x),
+ GrowArrow(vector_y)
+ )
+ vector_x.add_updater(
+ lambda m: m.become(
+ self.get_tangent_vector(t(),figure,scale=2)
+ )
+ )
+ vector_y.add_updater(
+ lambda m: m.become(
+ self.get_normal_vector(t(),figure,scale=2)
+ )
+ )
+ dot.add_updater(lambda m: m.move_to(vector_x.get_start()))
+ circle = Circle(radius = 2, color = GREEN_SCREEN). shift(2.63*RIGHT + 2.8*UP)
+ dot2 = Dot(np.array([2, curve_(2), 0]), color = WHITE).shift(2*DOWN + 2.5*RIGHT)
+
+ self.add(vector_x, vector_y,dot, t_text, kappa, text)
+ self.play(t2_.set_value, 2, alpha.set_value, 1, run_time=18, rate_func=smooth)
+ self.play(FadeIn(dot2), FadeIn(circle))
+ self.wait(2)
+ self.play(FadeOut(VGroup(*[self.axes, dot2, figure, circle, text, kappa, t_text])))
+
+
+ def get_tangent_vector(self, proportion, curve, dx=0.001, scale=0.5):
+ coord_i = curve.point_from_proportion(proportion)
+ coord_f = curve.point_from_proportion(proportion + dx)
+ reference_line = Line(coord_i,coord_f)
+ unit_vector = reference_line.get_unit_vector() * 0.7
+ vector = Arrow(coord_i , coord_i + unit_vector, color = YELLOW, buff=0)
+ return vector
+
+ def get_normal_vector(self, proportion, curve, dx=0.001, scale=1):
+ t = proportion.copy()/6
+ coord_i = curve.point_from_proportion(proportion)
+ coord_f = curve.point_from_proportion(proportion + dx)
+ length = 6 * t / ((9*(t**4) - 6*(t**2) + 5)**1.5)
+ if coord_i[0] <= 0 and coord_i[0] > -0.5:
+ reference_line = Line(coord_i,coord_f).rotate(PI/2).set_width(0).scale(2)
+ elif coord_i[0] > 0 and (coord_i[0] < 0.5 or coord_i[0] > 2.7):
+ reference_line = Line(coord_i,coord_f).rotate(PI/2).set_width(0).scale(2)
+ elif coord_i[0] > 0:
+ reference_line = Line(coord_i,coord_f).rotate(PI/2).set_width(length).scale(2)
+ else:
+ reference_line = Line(coord_i,coord_f).rotate(-PI/2).set_width(length).scale(2)
+ unit_vector = reference_line.get_vector() * scale
+ vector = Arrow(coord_i , coord_i + unit_vector, color = RED_C, buff=0)
+ return vector
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file5_torsion_intuition.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file5_torsion_intuition.py
new file mode 100644
index 0000000..31b9a85
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file5_torsion_intuition.py
@@ -0,0 +1,119 @@
+from manimlib.imports import *
+
+class t(SpecialThreeDScene):
+ CONFIG = {
+ "axes_config": {
+ "x_min": -5,
+ "x_max": 5,
+ "y_min": -5,
+ "y_max": 5,
+ "z_min": -4,
+ "z_max": 4,
+ "x_axis_config": {
+ "tick_frequency": 100,
+ },
+ "y_axis_config": {
+ "tick_frequency": 100,
+ },
+ "z_axis_config": {
+ "tick_frequency": 100,
+ },
+ "num_axis_pieces": 1,
+ }
+ }
+ def construct(self):
+
+ text = TextMobject(r'Torsion can be intuitively \\ thought of as the measure \\ of "twisting" of a curve.').scale(0.7).shift(2.5*UP + 4.2*LEFT)
+
+
+ dot = Dot().rotate(PI/2)
+ f1 = ParametricFunction(
+ lambda t: np.array([
+ 2*np.sin(TAU*t),
+ 2*np.cos(TAU*t),
+ 2*t
+ ]), t_min = -2, t_max = 2, color = BLUE
+ ).scale(0.5)
+ d1 = Dot(color = RED).next_to(f1.get_center(), 2*DOWN + LEFT, buff = 0).shift(1.2*UP + 2.4*RIGHT)
+ t1 = self.get_torsion(2, 0.174)
+ t1 = "{:.2f}".format(t1)
+ t1 = TextMobject(fr'At the given point, $\tau = {t1}$').shift(3.5*DOWN).scale(0.7)
+
+ f2 = ParametricFunction(
+ lambda t: np.array([
+ 3*np.sin(TAU*t),
+ 3*np.cos(TAU*t),
+ 2*t
+ ]), t_min = -2, t_max = 2, color = BLUE
+ ).scale(0.5)
+ d2 = Dot(color = RED).next_to(f2.get_center(), 2*DOWN + LEFT, buff = 0).shift(1.2*UP + 2.95*RIGHT)
+ t2 = self.get_torsion(3, 0.1765)
+ t2 = "{:.2f}".format(t2)
+ t2 = TextMobject(fr'At the given point, $\tau = {t2}$').shift(3.5*DOWN).scale(0.7)
+
+ f3 = ParametricFunction(
+ lambda t: np.array([
+ 4*np.sin(TAU*t),
+ 4*np.cos(TAU*t),
+ 2*t
+ ]), t_min = -2, t_max = 2, color = BLUE
+ ).scale(0.5)
+ d3 = Dot(color = RED).next_to(f3.get_center(), 2*DOWN + LEFT, buff = 0).shift(1.2*UP + 3.45*RIGHT)
+ t3 = self.get_torsion(4, 0.179)
+ t3 = "{:.2f}".format(t3)
+ t3 = TextMobject(fr'At the given point, $\tau = {t3}$').shift(3.5*DOWN).scale(0.7)
+
+ f4 = ParametricFunction(
+ lambda t: np.array([
+ 1.5*np.sin(TAU*t),
+ 1.5*np.cos(TAU*t),
+ 2*t
+ ]), t_min = -2, t_max = 2, color = BLUE
+ ).scale(0.5)
+ d4 = Dot(color = RED).next_to(f4.get_center(), 2*DOWN + LEFT, buff = 0).shift(1.215*UP + 2.128*RIGHT)
+ t4 = self.get_torsion(1.5, 0.173)
+ t4 = "{:.2f}".format(t4)
+ t4 = TextMobject(fr'At the given point, $\tau = {t4}$').shift(3.5*DOWN).scale(0.7)
+
+ f5 = ParametricFunction(
+ lambda t: np.array([
+ np.sin(TAU*t),
+ np.cos(TAU*t),
+ 2*t
+ ]), t_min = -2, t_max = 2, color = BLUE
+ ).scale(0.5)
+
+ d5 = Dot(color = RED).next_to(f5.get_center(), 2*DOWN + LEFT, buff = 0).shift(1.3*UP + 1.858*RIGHT)
+ t5 = self.get_torsion(1, 0.17)
+ t5 = "{:.2f}".format(t5)
+ t5 = TextMobject(fr'At the given point, $\tau = {t5}$').shift(3.5*DOWN).scale(0.7)
+
+ axes = ThreeDAxes(**self.axes_config)
+ self.set_camera_orientation(phi = 60*DEGREES, theta=45*DEGREES)
+ self.add_fixed_in_frame_mobjects(t1, text)
+ self.play(FadeIn(VGroup(*[f1, d1, t1, axes, text])))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(t2)
+ self.play(ReplacementTransform(d1, d2), ReplacementTransform(f1, f2), ReplacementTransform(t1, t2))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(t3)
+ self.play(ReplacementTransform(d2, d3), ReplacementTransform(f2, f3), ReplacementTransform(t2, t3))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(t4)
+ self.play(ReplacementTransform(d3, d4), ReplacementTransform(f3, f4), ReplacementTransform(t3, t4))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(t5)
+ self.play(ReplacementTransform(d4, d5), ReplacementTransform(f4, f5), ReplacementTransform(t4, t5))
+ self.wait(2)
+ self.play(FadeOut(VGroup(*[d5, f5, t5, text, axes])))
+
+ def get_torsion(self, a, t):
+ rprime = np.array([a*np.cos(t), -a*np.sin(t), 2])
+ T = rprime / np.sqrt(np.dot(rprime, rprime))
+ rpp = np.array([-a*np.sin(t), -a*np.cos(t), 0])
+ n = rpp / np.dot(rpp, rpp)
+ b = np.cross(T, n)
+ dbdt = np.array([-2*np.sin(t), -2*np.cos(t), 0])
+ tor = np.dot(dbdt, n)
+
+ return tor
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file6_fs2.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file6_fs2.py
new file mode 100644
index 0000000..0c74685
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file6_fs2.py
@@ -0,0 +1,90 @@
+from manimlib.imports import *
+
+class fs2(SpecialThreeDScene):
+ CONFIG = {
+ "x_min": -2,
+ "x_max": 2,
+ "y_min": -6,
+ "y_max": 6,
+ "graph_origin": ORIGIN
+ }
+ def construct(self):
+ axes = ThreeDAxes()
+ # text = TextMobject(r'$\frac{dB}{ds} = -\tau N$ \\ $\frac{dB}{ds}$ gives the direction of N, \\ while $\tau$ gives its magnitude.').scale(0.7).shift(3*UP + 3*LEFT)
+ self.set_camera_orientation(phi = 75*DEGREES, theta=135*DEGREES)
+ # self.move_camera(distance=0)
+
+ # rprime = np.array([2*np.cos(t), -np.sin(t) - (2*np.sin(2*t)), 0])
+ # t = rprime / np.sqrt(np.dot(rprime, rprime))
+ # rpp = np.array([-2*np.sin(t), -np.cos(t) - (4*np.cos(2*t)), 0])
+ # n = rpp / np.dot(rpp, rpp)
+ # b = np.cross(rprime, rpp)
+ text = TextMobject(r'$\frac{dB}{ds}$', r'$= -\tau$', r'$N$').shift(2*UP + 4*LEFT)
+ text.set_color_by_tex_to_color_map({
+ r'$\frac{dB}{ds}$': YELLOW,
+ r'$N$': RED_C
+ })
+
+ dot = Dot().rotate(PI/2)
+ alpha = ValueTracker(0)
+ t = alpha.get_value
+ figure = ParametricFunction(
+ lambda t: np.array([
+ np.sinh(t),
+ np.cosh(t),
+ 2*t
+ ]), t_min = -3, t_max = 3, color=BLUE
+ ).scale(0.5).move_to(ORIGIN)
+ vector_x = self.get_tangent_vector(t()%1, figure,scale=2)
+ vector_y = self.get_normal_vector(t(),figure,scale=2)
+ vector_x.add_updater(
+ lambda m: m.become(
+ self.get_tangent_vector(t()%1,figure,scale=2)
+ )
+ )
+ vector_y.add_updater(
+ lambda m: m.become(
+ self.get_normal_vector(t(),figure,scale=2)
+ )
+ )
+ dot.add_updater(lambda m: m.move_to(vector_y.get_start()))
+
+
+
+ self.add_fixed_in_frame_mobjects(text)
+ self.play(FadeIn(figure), FadeIn(axes), FadeIn(text))
+ self.begin_ambient_camera_rotation(rate = 0.1)
+ self.wait(1)
+ self.add(vector_x, vector_y,dot)
+ self.play(alpha.increment_value, 0.999, run_time=20, rate_func=rush_from)
+ self.wait(1)
+ self.remove(figure, vector_x, vector_y,dot)
+ self.play(FadeOut(figure), FadeOut(axes), FadeOut(text))
+
+ def get_tangent_vector(self, proportion, curve, dx=0.001, scale=1):
+ t = proportion.copy()
+ coord_i = curve.point_from_proportion(proportion)
+ rprime = np.array([np.cosh(t), np.sinh(t), 2])
+ T = rprime / np.sqrt(np.dot(rprime, rprime))
+ rpp = np.array([np.sinh(t), np.cosh(t), 0])
+ n = rpp / np.dot(rpp, rpp)
+ # b = (np.cross(T, n)[0] - 0.5, np.cross(T, n)[1], coord_i[2] + 1)
+ b = np.cross(T, n)
+ # coord_f = curve.point_from_proportion(proportion + dx)
+ coord_f = b
+ reference_line = Line(coord_i,coord_f)
+ unit_vector = reference_line.get_unit_vector() * 1
+ vector = Arrow(coord_i , coord_i + unit_vector, color = YELLOW, buff=0)
+ return vector
+
+ def get_normal_vector(self, proportion, curve, dx=0.001, scale=1):
+ coord_i = curve.point_from_proportion(proportion)
+ coord_f = curve.point_from_proportion(proportion + dx)
+ t = proportion.copy()/7
+ rpp = np.array([np.sinh(t), np.cosh(t), 0])
+ length = np.sqrt(np.dot(rpp, rpp))
+ length = 1/(1 + np.exp(-length))
+ reference_line = Line(coord_i,coord_f).rotate(PI/2).set_width(length).scale(2)
+ unit_vector = reference_line.get_vector() * 0.7
+ vector = Arrow(coord_i, coord_i + unit_vector, color = RED_C, buff=0)
+ return vector
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file7_fs3.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file7_fs3.py
new file mode 100644
index 0000000..698ca74
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/tnb-frame-and-serret-frenet-formulae/file7_fs3.py
@@ -0,0 +1,194 @@
+from manimlib.imports import *
+
+class f(SpecialThreeDScene):
+ CONFIG = {
+ "axes_config": {
+ "x_min": -5,
+ "x_max": 5,
+ "y_min": -5,
+ "y_max": 5,
+ "z_min": -4,
+ "z_max": 4,
+ "x_axis_config": {
+ "tick_frequency": 100,
+ },
+ "y_axis_config": {
+ "tick_frequency": 100,
+ },
+ "z_axis_config": {
+ "tick_frequency": 100,
+ },
+ "num_axis_pieces": 1,
+ }
+ }
+ def construct(self):
+ axes = ThreeDAxes(**self.axes_config)
+ text = TextMobject(r'$r(t) = \left\langle\sinh{t}, \cosh{t}, 2t\right\rangle$').scale(0.7).shift(3*UP + 3*LEFT)
+ self.set_camera_orientation(phi = 75*DEGREES, theta=225*DEGREES)
+
+
+
+ figure = ParametricFunction(
+ lambda t: np.array([
+ np.sinh(t),
+ np.cosh(t),
+ 2*t
+ ]), t_min = -3, t_max = 3, color=ORANGE
+ ).scale(0.5).move_to(ORIGIN)
+
+ dot = Dot(color=RED)
+ alpha = ValueTracker(0)
+ t = alpha.get_value
+
+ vector_x = self.get_binormal_vector(t()%1, figure,scale=2)
+ vector_y = self.get_normal_vector(t(),figure,scale=2)
+ vector_z = self.get_tangent_vector(t(), figure, scale=2)
+
+ vector_x.add_updater(
+ lambda m: m.become(
+ self.get_binormal_vector(t()%1,figure,scale=2)
+ )
+ )
+ vector_y.add_updater(
+ lambda m: m.become(
+ self.get_normal_vector(t(),figure,scale=2)
+ )
+ )
+ vector_z.add_updater(
+ lambda m: m.become(
+ self.get_tangent_vector(t(),figure,scale=2)
+ )
+ )
+ dot.add_updater(
+ lambda m: m.move_to(vector_x.get_start())
+ )
+ def curvature(t):
+ r = np.array([np.sinh(t), np.cosh(t), 2*t])
+ rp = np.array([np.cosh(t), np.sinh(t), 2])
+ rpp = np.array([np.sinh(t), np.cosh(t), 0])
+ cp = np.cross(rp, rpp)
+ k = cp / (np.dot(rp, rp)**1.5)
+ return abs(k[0])
+
+ def torsion(t):
+ r = np.array([np.sinh(t), np.cosh(t), 2*t])
+ rp = np.array([np.cosh(t), np.sinh(t), 2])
+ rpp = np.array([np.sinh(t), np.cosh(t), 0])
+ n = rpp / np.dot(rpp, rpp)
+ dbdt = np.array([2*np.sinh(t), 2*np.cosh(t), 0])
+ tor = np.dot(dbdt, n)
+ return tor
+
+
+
+ k = curvature(0.3)
+ k = "{:.2f}".format(k)
+ tor = torsion(0.3)
+ tor = "{:.2f}".format(tor)
+ kt1 = TextMobject(rf'At the given point, \\ $\kappa =$ {k} \\').scale(0.7).shift(3*UP + 4*RIGHT)
+ kt2 = TextMobject('$\implies \kappa$',r'$T$',r' is scaled as:').scale(0.7).next_to(kt1, DOWN, buff=0.1)
+ kt2.set_color_by_tex_to_color_map({
+ '$T$': YELLOW
+ })
+ tbt1 = TextMobject(rf'At the given point, \\ $\tau =$ {tor} \\').scale(0.7).shift(3*UP + 4*RIGHT)
+ tbt2 = TextMobject(r'$\implies \tau$',r'$B$',r' is scaled as:').scale(0.7).next_to(tbt1, DOWN, buff=0.1)
+ tbt2.set_color_by_tex_to_color_map({
+ '$B$': GREEN_E
+ })
+ ft = TextMobject(r'$\frac{dN}{ds}$',r'$ = -\kappa$',r'$T$', r'$ + \tau$',r'$B$ \\', r'and is given as:').scale(0.7).shift(3*UP + 4*RIGHT)
+ ft.set_color_by_tex_to_color_map({
+ r'$\frac{dN}{ds}$': GREEN_SCREEN,
+ '$T$': YELLOW,
+ r'$B$ \\': GREEN_E
+ })
+
+ self.add_fixed_in_frame_mobjects(text)
+ self.play(FadeIn(figure), FadeIn(axes), FadeIn(text))
+ # self.begin_ambient_camera_rotation(rate = 0.13)
+ self.wait(1)
+ self.add(vector_x, vector_y,vector_z,dot)
+ self.play(alpha.increment_value, 0.3, run_time=10, rate_func=rush_from)
+ self.wait(1)
+ # self.stop_ambient_camera_rotation()
+ # self.move_camera(phi = 75*DEGREES, theta=225*DEGREES)
+ square = Rectangle(width=3.2, fill_color=WHITE, fill_opacity=0.3, color=RED_C).rotate(40*DEGREES).shift(0.8*DOWN+1.2*RIGHT)
+ mat = [[0.7, 0.3], [1.0, -0.7]]
+ square = square.apply_matrix(mat).rotate(17*DEGREES).shift(2.1*DOWN+RIGHT)
+ tl, nl, bl = TextMobject(r'$T$', color=YELLOW).shift(2.8*RIGHT+0.5*DOWN), TextMobject(r'$N$', color=BLUE).shift(RIGHT), TextMobject(r'$B$', color=GREEN_E).shift(0.6*LEFT+0.5*DOWN)
+ self.add_fixed_in_frame_mobjects(tl, nl, bl)
+ self.play(FadeIn(VGroup(*[tl, nl, bl])))
+ self.wait(3)
+ self.add_fixed_in_frame_mobjects(square)
+ self.play(FadeIn(square), FadeOut(VGroup(*[tl, nl, bl])))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(kt1)
+ self.play(FadeIn(kt1))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(kt2)
+ self.play(FadeIn(kt2))
+ self.wait(2)
+ kt = self.get_tangent_vector(0.3, figure, scale = -4*float(k))
+ tb = self.get_binormal_vector(0.3, figure, scale = 2*float(tor))
+ self.play(
+ ReplacementTransform(vector_z, kt)
+ )
+ self.wait(3)
+ self.add_fixed_in_frame_mobjects(tbt1)
+ self.play(FadeOut(VGroup(*[kt1, kt2])), FadeIn(tbt1))
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(tbt2)
+ self.play(FadeIn(tbt2))
+ self.wait(2)
+ self.play(
+ ReplacementTransform(vector_x, tb)
+ )
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(ft)
+ self.play(FadeOut(VGroup(*[tbt1, tbt2])), FadeIn(ft))
+ self.wait(2)
+ dnds = Arrow(dot.get_center() + np.array([-0.1,-0.25,0]), np.array([-4,-1,2]), color=GREEN_SCREEN)
+ dndsl = TextMobject(r'$\frac{dN}{ds}$', color=GREEN_SCREEN).shift(2.5*LEFT + 1.2*UP)
+ self.add_fixed_in_frame_mobjects(dndsl)
+ self.play(FadeIn(dnds), FadeIn(dndsl))
+ self.wait(5)
+ self.play(FadeOut(VGroup(*[square, dot,vector_y, dnds, dndsl, text, ft, tb, kt])))
+ self.play(FadeOut(figure), FadeOut(axes))
+
+
+ def get_binormal_vector(self, proportion, curve, dx=0.001, scale=1):
+ t = proportion
+ coord_i = curve.point_from_proportion(proportion)
+ rprime = np.array([np.cosh(t), np.sinh(t), 2])
+ T = rprime / np.sqrt(np.dot(rprime, rprime))
+ rpp = np.array([np.sinh(t), np.cosh(t), 0])
+ n = rpp / np.dot(rpp, rpp)
+ # b = (np.cross(T, n)[0] - 0.5, np.cross(T, n)[1], coord_i[2] + 1)
+ b = np.cross(T, n)
+ # coord_f = curve.point_from_proportion(proportion + dx)
+ coord_f = b
+ reference_line = Line(coord_i,coord_f)
+ unit_vector = reference_line.get_unit_vector() * scale
+ vector = Arrow(coord_i , coord_i + unit_vector, color = GREEN_E, buff=0)
+ return vector
+
+ def get_normal_vector(self, proportion, curve, dx=0.001, scale=1):
+ coord_i = curve.point_from_proportion(proportion)
+ coord_f = curve.point_from_proportion(proportion + dx)
+ t = proportion.copy()/7
+ rpp = np.array([np.sinh(t), np.cosh(t), 0])
+ length = np.sqrt(np.dot(rpp, rpp))
+ length = 1/(1 + np.exp(-length))
+ reference_line = Line(coord_i,coord_f).rotate(PI/2).set_width(length).scale(2)
+ unit_vector = reference_line.get_unit_vector() * scale
+ vector = Arrow(coord_i, coord_i + unit_vector, color = BLUE, buff=0)
+ return vector
+
+ def get_tangent_vector(self, proportion, curve, dx=0.001, scale=1):
+ coord_i = curve.point_from_proportion(proportion)
+ coord_f = curve.point_from_proportion(proportion + dx)
+ reference_line = Line(coord_i,coord_f).scale(2)
+ if scale < 0:
+ reference_line = Line(coord_i,coord_f).scale(2).rotate(360*DEGREES)
+ unit_vector = reference_line.get_unit_vector() * scale
+ vector = Arrow(coord_i, coord_i + unit_vector, color = YELLOW, buff=0)
+ return vector
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/README.md b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/README.md
new file mode 100644
index 0000000..02678fd
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/README.md
@@ -0,0 +1,2 @@
+**file3_tangent_space_curve.py** <br>
+![file3_tangent_space_curve.py](https://github.com/saarthdeshpande/FSF-mathematics-python-code-archive/blob/master/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file3_tangent_space_curve.gif)
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file1_smooth_curves.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file1_smooth_curves.gif
new file mode 100644
index 0000000..5801796
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file1_smooth_curves.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file2_non_differentiable.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file2_non_differentiable.py
new file mode 100644
index 0000000..a91da6b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file2_non_differentiable.py
@@ -0,0 +1,36 @@
+from manimlib.imports import *
+
+class nd(Scene):
+ def construct(self):
+ ld1 = Line().rotate(20*DEGREES)
+ pd1 = Dot(ld1.get_end(), fill_opacity = 0)
+ pd1.set_stroke(width = 0.5)
+ ld2 = Line().rotate(40*DEGREES).shift(1.4*UP + 1.7*RIGHT)
+ pd2 = Dot(ld2.get_start(), fill_opacity = 1, color = PURPLE)
+ t1 = TextMobject('A discontinuous function.').scale(0.7).shift(UP + 2*RIGHT)
+
+ obj1 = VGroup(*[ld1, pd1, ld2, pd2]).shift(4*LEFT)
+ self.play(FadeIn(obj1), FadeIn(t1))
+ self.wait(2)
+
+ ld3 = ld2.copy().rotate(-60*DEGREES).shift(1.4*DOWN + 0.2*RIGHT)
+ pd3 = Dot(ld1.get_end(), fill_opacity = 1, color = PURPLE)
+ t2 = TextMobject('Graph containing a sharp corner.').scale(0.7).shift( 2*RIGHT)
+
+ obj2 = VGroup(*[ld3, pd3])
+
+ self.play(Transform(VGroup(*[ld2, pd2]), obj2), ReplacementTransform(t1, t2))
+
+ self.wait(2)
+
+ ld4 = Line().rotate(90*DEGREES)
+ pd4 = Dot(ld4.get_center(), color = PURPLE)
+ a1 = Arc(start_angle = -180*DEGREES, angle = 90*DEGREES).move_to(ld4.get_end()).rotate(-90*DEGREES).shift(0.5*(UP+RIGHT))
+ a2 = Arc(start_angle = -180*DEGREES, angle = 90*DEGREES).move_to(ld4.get_start()).rotate(90*DEGREES).shift(0.5*(DOWN+LEFT))
+ t3 = TextMobject('Graph with a vertical line.').scale(0.7).shift(2*RIGHT)
+
+ obj3 = VGroup(*[ld4, pd4, a1, a2]).shift(3*LEFT)
+
+ self.play(FadeOut(obj1), Transform(obj2, obj3), ReplacementTransform(t2, t3))
+ self.wait(2)
+ self.play(FadeOut(obj2), FadeOut(t3))
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file3_tangent_space_curve.gif b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file3_tangent_space_curve.gif
new file mode 100644
index 0000000..06ed70f
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file3_tangent_space_curve.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file3_tangent_space_curve.py b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file3_tangent_space_curve.py
new file mode 100644
index 0000000..c3aecc6
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/geometry-of-planes-and-curves/velocity-and-differentiability/file3_tangent_space_curve.py
@@ -0,0 +1,33 @@
+from manimlib.imports import *
+
+class tangent(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ text = TextMobject(r'Tangent', r' to the ', 'space curve', r' \\ at point ', r'$P_{1}$', ' is given by:').scale(0.7).shift(3*UP + 3.5*LEFT)
+ text.set_color_by_tex_to_color_map({
+ "Tangent": YELLOW,
+ '$P_{1}$': RED,
+ 'space curve': BLUE
+ })
+ text.bg=BackgroundRectangle(text,fill_opacity=1, color = BLACK)
+ text_gr =VGroup(text.bg,text)
+ self.set_camera_orientation(phi = 125*DEGREES, theta = 135*DEGREES)
+ h = ParametricFunction(
+ lambda t: np.array([
+ 4*(t**3) + 5,
+ t**2 + 2*(t**4),
+ -2*np.log(2*t)
+ ]), t_min = -3, t_max = 1.18, color = BLUE
+ ).shift(5*LEFT)
+ tgtR = Line((4,3,-2*np.log(2)), (19.5, 16, -4.772588), color=YELLOW)
+ tgtL =Line((4,3,-2*np.log(2)), (-11.5, -10, 2), color=YELLOW)
+ dot = Dot((4,3,-2*np.log(2)), color=RED, radius=0.08)
+ dotl = TextMobject(r'$P_{1}$', color = RED).scale(0.7).shift(2*DOWN + 5*LEFT)
+ self.add_fixed_in_frame_mobjects(text_gr, dotl)
+ self.play(FadeIn(axes),FadeIn(h), FadeIn(dot), FadeIn(dotl))
+ self.wait(2)
+ self.play(FadeIn(tgtL), FadeIn(tgtR))
+ self.begin_ambient_camera_rotation(rate=0.2)
+ self.play(FadeOut(dotl))
+ self.wait(5)
+ self.play(FadeOut(axes), FadeOut(h), FadeOut(text_gr), FadeOut(dot), FadeOut(tgtL), FadeOut(tgtR))
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/README.md b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/README.md
index a321caf..9115c78 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/README.md
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/README.md
@@ -1 +1,14 @@
FSF2020--Somnath Pandit
+
+# **Topics:**
+
+## Double Integral
+Check the note [here](https://math.animations.fossee.in/contents/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals)
+## Fubini's Theorem
+Check the note [here](https://math.animations.fossee.in/contents/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem)
+## Line Integrals
+Check the note [here](https://math.animations.fossee.in/contents/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals)
+## Fundamental Theorem of Line integrals
+Check the note [here](https://math.animations.fossee.in/contents/calculus-of-several-variables/div,-grad,-curl-and-all-that/the-fundamental-theorem-of-line-integrals)
+## Vector Fields
+Check the note [here](https://math.animations.fossee.in/contents/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields)
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/README.md b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/README.md
new file mode 100644
index 0000000..f86f7e3
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/README.md
@@ -0,0 +1,21 @@
+**file1_area_under_func**
+![file1_area_under_func](gifs/file1_area_under_func.gif)
+
+**file2_volume_under_surface**
+![file2_volume_under_surface](gifs/file2_volume_under_surface.gif)
+
+**file3_y_limit_dependent_on_x**
+![file3_y_limit_dependent_on_x](gifs/file3_y_limit_dependent_on_x.gif)
+
+**file4_non_rect_region**
+![file4_non_rect_region](gifs/file4_non_rect_region.gif)
+
+**file5_elementary_area**
+![file5_elementary_area](gifs/file5_elementary_area.gif)
+
+**file6_doing_integration**
+![file6_doing_integration](gifs/file6_doing_integration.gif)
+
+**file7_int_process_of_example**
+![file7_int_process_of_example](gifs/file7_int_process_of_example.gif)
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/area_under_func.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file1_area_under_func.py
index 773840c..773840c 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/area_under_func.py
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file1_area_under_func.py
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file2_volume_under_surface.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file2_volume_under_surface.py
new file mode 100644
index 0000000..38d41c6
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file2_volume_under_surface.py
@@ -0,0 +1,349 @@
+from manimlib.imports import *
+
+class SurfacesAnimation(ThreeDScene):
+
+ CONFIG = {
+ "axes_config": {
+ "x_min": 0,
+ "x_max": 7,
+ "y_min": 0,
+ "y_max": 7,
+ "z_min": 0,
+ "z_max": 5,
+ "a":1 ,"b": 6, "c":2 , "d":6,
+ "axes_shift":-3*OUT + 5*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: 2+y/4+np.sin(x)
+ }
+
+
+ def construct(self):
+
+ self.setup_axes()
+ self.set_camera_orientation(distance=35,
+ phi=80 * DEGREES,
+ theta=-100 * DEGREES,
+ )
+
+ fn_text=TextMobject(
+ "$z=f(x,y)$",
+ color=PINK,
+ stroke_width=1.5
+ )
+ self.add_fixed_in_frame_mobjects(fn_text)
+ fn_text.to_edge(TOP,buff=MED_SMALL_BUFF)
+
+ riemann_sum_text=TextMobject(
+ r"The volume approximated as\\ sum of cuboids",
+ color=BLUE,
+ stroke_width=1.5
+ )
+ riemann_sum_text.to_corner(UR,buff=.2)
+
+ R=TextMobject("R").set_color(BLACK).scale(3)
+ 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.8,
+ fill_color=PINK,
+ stroke_width=0.8,
+ stroke_color=WHITE,
+ )
+
+
+ self.begin_ambient_camera_rotation(rate=0.06)
+ self.play(Write(surface))
+ # self.add(surface)
+
+ self.get_lines()
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(riemann_sum_text)
+ self.play(Write(riemann_sum_text))
+
+ cuboids1=self.show_the_riemmann_sum(
+ lambda x,y : np.array([x,y,self.Func(x,y)]),
+ fill_opacity=1,
+ dl=.5,
+ start_color=BLUE,
+ end_color=BLUE_E,
+ )
+ self.play(ShowCreation(cuboids1),run_time=5)
+ self.play(FadeOut(surface))
+
+ cuboids2=self.show_the_riemmann_sum(
+ lambda x,y : np.array([x,y,self.Func(x,y)]),
+ fill_opacity=1,
+ dl=.25,
+ start_color=BLUE,
+ end_color=BLUE_E,
+ )
+ self.play(ReplacementTransform(
+ cuboids1,
+ cuboids2
+ ))
+
+ cuboids3=self.show_the_riemmann_sum(
+ lambda x,y : np.array([x,y,self.Func(x,y)]),
+ fill_opacity=1,
+ dl=.1,
+ start_color=BLUE,
+ end_color=BLUE_E,
+ stroke_width=.1,
+ )
+ self.play(
+ FadeOut(cuboids2),
+ ShowCreation(cuboids3),
+ )
+
+ self.wait(3)
+
+
+
+
+ def get_surface(self,axes, func, **kwargs):
+ config = {
+ "u_min": axes.a,
+ "u_max": axes.b,
+ "v_min": axes.c,
+ "v_max": axes.d,
+ "resolution": (
+ (axes.y_max - axes.y_min) // axes.y_axis.tick_frequency,
+ (axes.x_max - axes.x_min) // axes.x_axis.tick_frequency,
+ ),
+ }
+
+ 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
+
+ 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,"#9CDCEB"))
+
+ labels=[
+ (axes.a,0,0),
+ (axes.b,0,0),
+ (0,axes.d,0),
+ (0,axes.c,0)
+ ]
+ self.region_corners[-1]=self.region_corners[0]
+ for start , end in zip(labels,self.region_corners):
+ lines.add(self.draw_lines(start,end,"WHITE"))
+
+ # self.add(lines)
+ 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 show_the_riemmann_sum(
+ self,
+ surface,
+ x_min=None,
+ x_max=None,
+ y_min=None,
+ y_max=None,
+ dl=.5,
+ stroke_width=.5,
+ stroke_color=BLACK,
+ fill_opacity=1,
+ start_color=None,
+ end_color=None,
+ ):
+ x_min = x_min if x_min is not None else self.axes.a
+ x_max = x_max if x_max is not None else self.axes.b
+ y_min = y_min if y_min is not None else self.axes.c
+ y_max = y_max if y_max is not None else self.axes.d
+
+ if start_color is None:
+ start_color = BLUE
+ if end_color is None:
+ end_color = BLUE
+
+ cuboids = VGroup()
+ x_range = np.arange(x_min, x_max, dl)
+ y_range = np.arange(y_min, y_max, dl)
+ colors = color_gradient([start_color, end_color], len(x_range))
+ for x, color in zip(x_range, colors):
+ for y in y_range:
+ sample_base = np.array([x ,y ,0])
+ sample_base_dl = np.array([x + dl, y + dl,0])
+ sample_input = np.array([x +0.5*dl, y +0.5*dl,0])
+
+ base_point = self.axes.c2p(*sample_base)
+ base_dx_point = self.axes.c2p(*sample_base_dl)
+
+ surface_val= surface(*sample_input[:2])
+ surface_point = self.axes.c2p(*surface_val)
+
+ points = VGroup(*list(map(VectorizedPoint, [
+ base_point,
+ surface_point,
+ base_dx_point
+ ])))
+
+ # self.add(points)
+ cuboid = Prism(dimensions=[dl,dl,surface_val[-1]])
+ cuboid.replace(points, stretch=True)
+
+ cuboid.set_fill(color, opacity=fill_opacity)
+ cuboid.set_stroke(stroke_color, width=stroke_width)
+ cuboids.add(cuboid)
+
+ return cuboids
+
+
+#-------------------------------------------------------
+ #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, RIGHT,
+ 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.5,
+ fill_color=TEAL,
+ stroke_width=0,
+ stroke_color=WHITE,
+ )
+
+ axes.input_plane = input_plane
+
+ self.region_corners=[
+ input_plane.get_corner(pos) for pos in (DL,DR,UL,UR)]
+
+ 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),
+ ("b", axes.b),
+ ]
+ tex_vals_y=[
+ ("c", axes.c),
+ ("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)
+ 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.5)
+ 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, RIGHT)
+ z_label.next_to(axes.z_axis.get_zenith(), RIGHT)
+ axes.z_axis.label = z_label
+ for axis in axes:
+ axis.add(axis.label)
+ return axes
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/y_limit_dependent_on_x.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file3_y_limit_dependent_on_x.py
index 4894ebf..f755495 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/y_limit_dependent_on_x.py
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file3_y_limit_dependent_on_x.py
@@ -29,7 +29,7 @@ class YlimitXdependent(GraphScene):
line_eqn=TextMobject("2x+y=2").move_to(self.graph_origin+.8*X+Y).rotate(np.arctan(-2))
self.line=line
- caption=TextMobject(r"See the value of $y$ \\ is changing with $x$").move_to(self.graph_origin+1.2*X+1.8*Y)
+ caption=TextMobject(r"The value of $y$ is\\ changing with $x$").move_to(self.graph_origin+1.2*X+1.8*Y)
self.play(ShowCreation(line),Write(line_eqn))
# self.show_area()
self.show_rects()
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/non_rect_region.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file4_non_rect_region.py
index 793a000..793a000 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/non_rect_region.py
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file4_non_rect_region.py
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/elementary_area.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file5_elementary_area.py
index 362b6f8..362b6f8 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/elementary_area.py
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file5_elementary_area.py
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file6_doing_integration.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file6_doing_integration.py
new file mode 100644
index 0000000..5a8cec0
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file6_doing_integration.py
@@ -0,0 +1,355 @@
+from manimlib.imports import *
+
+class IntegrationProcess(SpecialThreeDScene):
+
+ CONFIG = {
+ "axes_config": {
+ "x_min": 0,
+ "x_max": 7,
+ "y_min": 0,
+ "y_max": 7,
+ "z_min": 0,
+ "z_max": 4,
+ "a":1 ,"b": 6, "c":2 , "d":6,
+ "axes_shift":-3*OUT,
+ "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: 2+y/4+np.cos(x/1.4)
+ }
+
+
+ def construct(self):
+
+ self.setup_axes()
+ axes=self.axes
+
+ self.camera.frame_center.shift(axes.c2p(3,4,1.7))
+ self.set_camera_orientation(distance=35,
+ phi= 80 * DEGREES,
+ theta= -80 * DEGREES,
+ gamma = 0 * DEGREES
+ )
+
+ fn_text=TextMobject("$z=f(x,y)$").set_color(PINK)
+ self.add_fixed_in_frame_mobjects(fn_text)
+
+
+ R=TextMobject("R").set_color(BLACK).scale(3)
+ R.move_to(axes.input_plane,IN)
+ self.add(R)
+
+ # get the surface
+ surface= self.get_surface(
+ axes, lambda x , y:
+ self.Func(x,y)
+ )
+ surface.set_style(
+ fill_opacity=.65,
+ fill_color=PINK,
+ stroke_width=0.8,
+ stroke_color=WHITE,
+ )
+ fn_text.next_to(surface,UP,buff=MED_LARGE_BUFF)
+ slice_curve=(self.get_y_slice_graph(
+ axes,self.Func,5,color=YELLOW))
+
+
+ self.begin_ambient_camera_rotation(rate=0.08)
+ # self.play(Write(surface))
+ self.add(surface)
+
+ self.get_lines()
+
+ self.show_process(axes)
+
+ self.wait(3)
+
+
+
+ def show_process(self,axes):
+ y_tracker = ValueTracker(axes.c)
+ self.y_tracker=y_tracker
+ y=y_tracker.get_value
+
+ graph = always_redraw(
+ lambda: self.get_y_slice_graph(
+ axes, self.Func, y(),
+ stroke_color=YELLOW,
+ stroke_width=4,
+ )
+ )
+ graph.suspend_updating()
+
+
+ plane = always_redraw(lambda: Polygon(
+ *[
+ axes.c2p(x,y(),self.Func(x,y()))
+ for x in np.arange(axes.a,axes.b,0.01)
+ ],
+ *[
+ axes.c2p(x, y(), 0)
+ for x in [ axes.b, axes.a,]
+ ],
+ stroke_width=2,
+ fill_color=BLUE_D,
+ fill_opacity=.4,
+ ))
+
+ plane_side1 = always_redraw(lambda: Polygon(
+ *[
+ axes.c2p(axes.a,y,self.Func(axes.a,y))
+ for y in np.arange(axes.c,y(),0.01)
+ ],
+ *[
+ axes.c2p(axes.a, y, 0)
+ for y in [ y(),axes.c, ]
+ ],
+ stroke_width=2.5,
+ fill_color=BLUE_C,
+ fill_opacity=.2,
+ ))
+ plane_side2 = always_redraw(lambda: Polygon(
+ *[
+ axes.c2p(axes.b,y,self.Func(axes.b,y))
+ for y in np.arange(axes.c,y(),0.01)
+ ],
+ *[
+ axes.c2p(axes.b, y, 0)
+ for y in [y(),axes.c,]
+ ],
+ stroke_width=2.5,
+ fill_color=BLUE_E,
+ fill_opacity=.45,
+ ))
+ plane.suspend_updating()
+ plane_side1.suspend_updating()
+ plane_side2.suspend_updating()
+
+ self.play(Write(VGroup(graph,plane)),run_time=2)
+ self.add(plane.copy(),plane_side1,plane_side2)
+
+
+ plane_side1.resume_updating()
+ plane_side2.resume_updating()
+
+ self.move_camera(
+ distance=30,
+ phi= 85 * DEGREES,
+ theta= -10 * DEGREES,
+ run_time=1.5
+ )
+ self.play(
+ ApplyMethod(
+ y_tracker.set_value, axes.d,
+ rate_func=linear,
+ run_time=6,
+ )
+ )
+ plane.suspend_updating()
+ plane_side1.suspend_updating()
+ plane_side2.suspend_updating()
+
+
+
+ def get_y_slice_graph(self, axes, func, y, **kwargs):
+ config = dict()
+ config.update(self.default_graph_style)
+ config.update({
+ "t_min": axes.a,
+ "t_max": axes.b,
+ })
+ config.update(kwargs)
+ slice_curve=ParametricFunction(
+ lambda x: axes.c2p(
+ x, y, func(x, y)
+ ),
+ **config,
+ )
+ return slice_curve
+
+
+ def get_surface(self,axes, func, **kwargs):
+ config = {
+ "u_min": axes.a,
+ "u_max": axes.b,
+ "v_min": axes.c,
+ "v_max": axes.d,
+ "resolution": (
+ (axes.y_max - axes.y_min) // axes.y_axis.tick_frequency,
+ (axes.x_max - axes.x_min) // axes.x_axis.tick_frequency,
+ ),
+ }
+
+ 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
+
+ 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,"RED"))
+
+ labels=[
+ (axes.a,0,0),
+ (axes.b,0,0),
+ (0,axes.d,0),
+ (0,axes.c,0)
+ ]
+ self.region_corners[-1]=self.region_corners[0]
+ for start , end in zip(labels,
+ self.region_corners):
+ lines.add(self.draw_lines(start,end,"WHITE"))
+ self.add(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, RIGHT,
+ 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.5,
+ fill_color=TEAL,
+ stroke_width=0,
+ stroke_color=WHITE,
+ )
+
+ axes.input_plane = input_plane
+
+ self.region_corners=[
+ input_plane.get_corner(pos) for pos in (DL,DR,UL,UR)]
+
+ 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),
+ ("b", axes.b),
+ ]
+ tex_vals_y=[
+ ("c", axes.c),
+ ("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)
+ 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.5)
+ 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, RIGHT)
+ z_label.next_to(axes.z_axis.get_zenith(), RIGHT)
+ axes.z_axis.label = z_label
+ for axis in axes:
+ axis.add(axis.label)
+ return axes
+
+
+
+ #uploaded by Somnath Pandit.FSF2020_Double_Integral
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file7_int_process_of_example.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file7_int_process_of_example.py
new file mode 100644
index 0000000..f733761
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/file7_int_process_of_example.py
@@ -0,0 +1,366 @@
+from manimlib.imports import *
+
+class IntegrationProcess(SpecialThreeDScene):
+
+ CONFIG = {
+ "axes_config": {
+ "x_min": 0,
+ "x_max": 5,
+ "y_min": 0,
+ "y_max": 7,
+ "z_min": 0,
+ "z_max": 3,
+ "a":0 ,"b":4 , "c":0 , "d":6,
+ "axes_shift":1.5*IN+2*LEFT+4*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: 2*(1+(x+y)/10)
+ }
+
+
+ def construct(self):
+
+ self.setup_axes()
+ axes=self.axes
+ self.set_camera_orientation(#distance=35,
+ phi=60 * DEGREES,
+ theta=10 * DEGREES,
+ )
+
+ fn_text=TextMobject("$z=(1+x+y)$").set_color(PINK)
+ self.add_fixed_in_frame_mobjects(fn_text)
+ fn_text.to_edge(TOP,buff=.1)
+ self.fn_text=fn_text
+
+ R=TextMobject("R").set_color(BLACK).scale(3).rotate(PI/2)
+ R.move_to(axes.input_plane,IN)
+ self.add(R)
+
+ #get the surface
+ surface= self.get_surface(
+ axes, lambda x , y:
+ self.Func(x,y)
+ )
+ surface.set_style(
+ fill_opacity=0.75,
+ fill_color=PINK,
+ stroke_width=0.8,
+ stroke_color=WHITE,
+ )
+
+ slice_curve=(self.get_y_slice_graph(
+ axes,self.Func,5,color=YELLOW))
+
+
+ self.begin_ambient_camera_rotation(rate=0.04)
+ # self.play(Write(surface))
+ self.add(surface)
+
+ self.get_lines()
+
+ self.show_process(axes)
+
+ self.wait()
+
+
+
+ def show_process(self,axes):
+ y_tracker = ValueTracker(axes.c)
+ self.y_tracker=y_tracker
+ y=y_tracker.get_value
+ graph = always_redraw(
+ lambda: self.get_y_slice_graph(
+ axes, self.Func, y(),
+ stroke_color=YELLOW,
+ stroke_width=4,
+ )
+ )
+ graph.suspend_updating()
+
+ plane = always_redraw(lambda: Polygon(
+ *[
+ axes.c2p(x,y(),self.Func(x,y()))
+ for x in np.arange(axes.a,axes.b,0.01)
+ ],
+ *[
+ axes.c2p(x, y(), 0)
+ for x in [ axes.b, axes.a,]
+ ],
+ stroke_width=0,
+ fill_color=BLUE_E,
+ fill_opacity=.65,
+ ))
+ plane_side1 = always_redraw(lambda: Polygon(
+ *[
+ axes.c2p(axes.a,y,self.Func(axes.a,y))
+ for y in np.arange(axes.c,y(),0.01)
+ ],
+ *[
+ axes.c2p(axes.a, y, 0)
+ for y in [ y(),axes.c, ]
+ ],
+ stroke_width=2.5,
+ fill_color=BLUE_C,
+ fill_opacity=.2,
+ ))
+ plane_side2 = always_redraw(lambda: Polygon(
+ *[
+ axes.c2p(axes.b,y,self.Func(axes.b,y))
+ for y in np.arange(axes.c,y(),0.01)
+ ],
+ *[
+ axes.c2p(axes.b, y, 0)
+ for y in [y(),axes.c,]
+ ],
+ stroke_width=2.5,
+ fill_color=BLUE_E,
+ fill_opacity=.45,
+ ))
+ plane.suspend_updating()
+ plane_side1.suspend_updating()
+ plane_side2.suspend_updating()
+
+ first_x_text=TextMobject("First the $x$ integration..",color=YELLOW)
+ first_x_text.to_corner(UR,buff=1.1)
+
+ x_func=TextMobject("$\\frac 3 2 + y$",color=BLUE)
+ '''x_func.next_to(self.fn_text,DOWN)
+ x_func.align_to(self.fn_text,LEFT)'''
+ x_func.to_edge(LEFT,buff=1)
+
+ then_y_text=TextMobject("Then the $y$ integration..",color=YELLOW)
+ then_y_text.to_corner(UR,buff=1.1)
+
+ self.add_fixed_in_frame_mobjects(first_x_text)
+ self.play(Write(first_x_text))
+ self.add_fixed_in_frame_mobjects(x_func)
+ self.play(
+ Write(VGroup(graph,plane,x_func)),
+ run_time=3
+ )
+
+ self.wait()
+ self.remove(first_x_text)
+ self.add_fixed_in_frame_mobjects(then_y_text)
+ self.play(Write(then_y_text))
+ self.add(plane.copy(),plane_side1,plane_side2)
+ graph.resume_updating()
+ plane.resume_updating()
+ plane_side1.resume_updating()
+ plane_side2.resume_updating()
+ self.play(
+ ApplyMethod(
+ y_tracker.set_value, axes.d,
+ rate_func=linear,
+ run_time=6,
+ )
+ )
+
+ graph.suspend_updating()
+ plane.suspend_updating()
+ plane_side1.suspend_updating()
+ plane_side2.suspend_updating()
+
+
+ def get_y_slice_graph(self, axes, func, y, **kwargs):
+ config = dict()
+ config.update(self.default_graph_style)
+ config.update({
+ "t_min": axes.a,
+ "t_max": axes.b,
+ })
+ config.update(kwargs)
+ slice_curve=ParametricFunction(
+ lambda x: axes.c2p(
+ x, y, func(x, y)
+ ),
+ **config,
+ )
+ return slice_curve
+
+
+ def get_surface(self,axes, func, **kwargs):
+ config = {
+ "u_min": axes.a,
+ "u_max": axes.b,
+ "v_min": axes.c,
+ "v_max": axes.d,
+ "resolution": (
+ (axes.y_max - axes.y_min) // axes.y_axis.tick_frequency,
+ (axes.x_max - axes.x_min) // axes.x_axis.tick_frequency,
+ ),
+ }
+
+ 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
+
+ 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,"RED"))
+
+ labels=[
+ (axes.a,0,0),
+ (axes.b,0,0),
+ (0,axes.d,0),
+ (0,axes.c,0)
+ ]
+ self.region_corners[-1]=self.region_corners[0]
+ for start , end in zip(labels,
+ self.region_corners):
+ lines.add(self.draw_lines(start,end,"WHITE"))
+ self.add(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=TEAL,
+ stroke_width=.2,
+ stroke_color=WHITE,
+ )
+
+ axes.input_plane = input_plane
+
+ self.region_corners=[
+ input_plane.get_corner(pos) for pos in (DL,DR,UL,UR)]
+
+ 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=[
+
+ ("2", 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_Double_Integral
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/area_Under_func.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file1_area_under_func.gif
index 223218b..223218b 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/area_Under_func.gif
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file1_area_under_func.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file2_volume_under_surface.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file2_volume_under_surface.gif
new file mode 100644
index 0000000..1455573
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file2_volume_under_surface.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file3_y_limit_dependent_on_x.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file3_y_limit_dependent_on_x.gif
new file mode 100644
index 0000000..dcfacb6
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file3_y_limit_dependent_on_x.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/non_rect_region.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file4_non_rect_region.gif
index c8e7c8c..c8e7c8c 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/non_rect_region.gif
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file4_non_rect_region.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/elementary_area.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file5_elementary_area.gif
index 5c9ac03..5c9ac03 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/elementary_area.gif
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file5_elementary_area.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file6_doing_integration.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file6_doing_integration.gif
new file mode 100644
index 0000000..7a9271b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file6_doing_integration.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file7_int_process_of_example.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file7_int_process_of_example.gif
new file mode 100644
index 0000000..9fbdde8
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/gifs/file7_int_process_of_example.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/surface.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/surface.gif
deleted file mode 100644
index ae23a7b..0000000
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/surface.gif
+++ /dev/null
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/y_limit_dependent_on_x.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/y_limit_dependent_on_x.gif
deleted file mode 100644
index a2bfd9d..0000000
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/y_limit_dependent_on_x.gif
+++ /dev/null
Binary files differ
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/surface1.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file1_surface1.py
index a590a53..a590a53 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's_theorem/surface1.py
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file1_surface1.py
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's_theorem/surface2.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file2_surface2.py
index c998f3b..3160fdb 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's_theorem/surface2.py
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/file2_surface2.py
@@ -63,7 +63,7 @@ class SurfacesAnimation(ThreeDScene):
surface.set_style(
fill_opacity=.5,
fill_color=BLUE_E,
- stroke_width=0.2,
+ stroke_width=0.4,
stroke_color=WHITE,
)
#get boundary curves
@@ -85,17 +85,18 @@ class SurfacesAnimation(ThreeDScene):
self.add(c1,c2,c1_label,c2_label)
- self.begin_ambient_camera_rotation(rate=0.4)
+ self.begin_ambient_camera_rotation(rate=0.24)
self.get_region(self.axes,c1,c2)
self.play(Write(surface))
self.get_lines()
- self.wait(1)
+ 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=2.5
+ run_time=3
)
self.wait(2)
@@ -128,7 +129,7 @@ class SurfacesAnimation(ThreeDScene):
R=TextMobject("R").set_color(PINK).scale(2).rotate(180*DEGREES , OUT)
R.move_to(region,IN+RIGHT)
- self.play(Write(region))
+ self.play(ShowCreation(region))
self.add(R)
def get_surface(self,axes, func, **kwargs):
@@ -279,8 +280,11 @@ class SurfacesAnimation(ThreeDScene):
axes.z_axis.label = z_label
for axis in axes:
axis.add(axis.label)
- return axes
+ 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/surface1.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's-theorem/gifs/file1_surface1.gif
index 8c9fa0a..8c9fa0a 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's_theorem/surface1.gif
+++ 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
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's_theorem/surface2.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's_theorem/surface2.gif
deleted file mode 100644
index ac13f21..0000000
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fubini's_theorem/surface2.gif
+++ /dev/null
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/README.md b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/README.md
new file mode 100644
index 0000000..3cdddae
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/README.md
@@ -0,0 +1,9 @@
+**file1_grad_of_scalar_function**
+![file1_grad_of_scalar_function](gifs/file1_grad_of_scalar_function.gif)
+
+**file2_line_int_independent_of_path**
+![file2_line_int_independent_of_path](gifs/file2_line_int_independent_of_path.gif)
+
+**file3_line_int_example**
+![file3_line_int_example](gifs/file3_line_int_example.gif)
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file1_grad_of_scalar_function.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file1_grad_of_scalar_function.py
new file mode 100644
index 0000000..fd3d9b5
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file1_grad_of_scalar_function.py
@@ -0,0 +1,317 @@
+from manimlib.imports import *
+
+class GradOfScalarFunc(ThreeDScene):
+
+ CONFIG = {
+ "axes_config": {
+ "x_min": -3,
+ "x_max": 3,
+ "y_min": -3,
+ "y_max": 3,
+ "z_min": 0,
+ "z_max": 3,
+ "a":-3 ,"b": 3, "c":-3 , "d":3,
+ "axes_shift": ORIGIN+IN,
+ "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": 5,
+ "stroke_color": WHITE,
+ },
+ "default_vector_field_config": {
+ "delta_x": 1,
+ "delta_y": 1,
+ "x_min": -3,
+ "x_max": 3,
+ "y_min": -3,
+ "y_max": 3,
+ "min_magnitude": 0,
+ "max_magnitude": 3,
+ "colors": [TEAL,GREEN,YELLOW,RED],
+ "length_func": lambda norm : norm*np.exp(-.38*norm)/2,
+ "opacity": 1.0,
+ "vector_config": {
+ "stroke_width":8
+ },
+ },
+ "default_surface_config": {
+ "fill_opacity": 0.5,
+ "checkerboard_colors": [BLUE_E],
+ "stroke_width": .2,
+ "stroke_color": WHITE,
+ "stroke_opacity": 0.5,
+ },
+ }
+
+
+ def construct(self):
+
+ self.setup_axes()
+ axes=self.axes
+
+ self.set_camera_orientation(distance=35,
+ phi=70 * DEGREES,
+ theta=-135 * DEGREES,
+ )
+
+ scalar_fn_text=TexMobject("f(x,y)=","xy").set_color(BLUE)
+ scalar_fn_text.to_corner(UR,buff=.6)
+
+ operator=TexMobject("\\vec\\nabla").next_to(
+ scalar_fn_text,LEFT,buff=.2
+ ).set_color(GOLD)
+
+ grad_text=TexMobject(r"\dfrac{\partial f}{\partial x} \hat i+\dfrac{\partial f}{\partial y} \hat j").set_color(GOLD)
+ grad_text.next_to(scalar_fn_text,DOWN).scale(.9)
+
+ VGroup(
+ grad_text[0][1],
+ grad_text[0][9]
+ ).set_color(BLUE)
+ VGroup(
+ grad_text[0][5:8],
+ grad_text[0][13:16]
+ ).set_color(WHITE)
+
+ vector_field_text=TexMobject("\\vec F=y\hat i+x\hat j").set_color_by_gradient(*self.default_vector_field_config["colors"])
+ vector_field_text.next_to(scalar_fn_text,DOWN)
+
+
+ #always generate the scalar field first
+ s_field1=self.get_scalar_field(
+ func= lambda u ,v : u*v/7
+ )
+ v_field1=self.get_vector_field(
+ lambda v: np.array([
+ v[1],
+ v[0],
+ 0,
+ ]),
+ on_surface=True,
+ )
+
+ self.add_fixed_in_frame_mobjects(scalar_fn_text)
+
+ self.begin_ambient_camera_rotation(rate=.2)
+ self.play(Write(s_field1))
+ self.wait(1)
+ self.stop_ambient_camera_rotation()
+
+ self.add_fixed_in_frame_mobjects(operator)
+ self.play(Write(operator),FadeOut(scalar_fn_text[1]))
+ self.add_fixed_in_frame_mobjects(grad_text)
+ self.play(Write(grad_text))
+ self.wait(2)
+
+
+ show_vects=[
+ FadeIn(v_field1),
+ ]
+
+ self.begin_ambient_camera_rotation(rate=.2)
+ self.move_camera(
+ # distance=20,
+ phi=60 * DEGREES,
+ added_anims=show_vects,
+ run_time=4.5
+ )
+
+ self.play(FadeOut(grad_text))
+ self.wait(2)
+ self.stop_ambient_camera_rotation()
+
+ self.add_fixed_in_frame_mobjects(vector_field_text)
+ vector_field= [
+ FadeOut(s_field1),
+ Write(vector_field_text),
+ ]
+ self.move_camera(
+ # distance=20,
+ phi=0 * DEGREES,
+ theta=-90 * DEGREES,
+ added_anims=vector_field,
+ run_time=2
+ )
+ self.wait(2)
+
+
+
+
+
+ def get_scalar_field(self,func,**kwargs):
+ surface= self.get_surface(
+ lambda x , y:
+ func(x,y),
+ )
+
+ self.surface_points=self.get_points(func)
+ return surface
+
+ def get_points(self,func):
+ axes=self.axes
+ dn=.5
+ x_vals=np.arange(axes.a,axes.b,dn)
+ y_vals=np.arange(axes.c,axes.d,dn)
+ points=[]
+ for x_val in x_vals:
+ for y_val in y_vals:
+ points+=[axes.c2p(x_val,y_val,func(x_val,y_val)+.05)]
+ return points
+
+ def get_vector_field(self,func,on_surface=True,**kwargs):
+ config = dict()
+ config.update(self.default_vector_field_config)
+ config.update(kwargs)
+ vector_field= VectorField(func,**config)
+ vector_field.move_to(self.axes.c2p(0,0,0))
+ self.vector_field=vector_field
+
+ if on_surface:
+ vector_field=self.get_vectors_on_surface()
+
+ return vector_field
+
+
+
+ def get_vectors_on_surface(self):
+ vectors_on_surface = VGroup(*[
+ self.vector_field.get_vector(point)
+ for point in self.surface_points
+ ])
+
+ return vectors_on_surface
+
+
+
+ def get_surface(self, func, **kwargs):
+ axes=self.axes
+ config = {
+ "u_min": axes.a,
+ "u_max": axes.b,
+ "v_min": axes.c,
+ "v_max": axes.d,
+ "resolution": (
+ 2*(axes.y_max - axes.y_min) // axes.y_axis.tick_frequency,
+ (axes.x_max - axes.x_min) // axes.x_axis.tick_frequency,
+ ),
+ }
+
+ config.update(self.default_surface_config)
+ config.update(kwargs)
+ return ParametricSurface(
+ lambda x,y : axes.c2p(
+ x, y, func(x, y)
+ ),
+ **config
+ )
+
+
+
+#-------------------------------------------------------
+ #customize 3D axes
+ def get_three_d_axes(self, include_labels=True, include_numbers=False, **kwargs):
+ config = dict(self.axes_config)
+ config.update(kwargs)
+ axes = ThreeDAxes(**config)
+ axes.set_stroke(width=2)
+ self.axes=axes
+
+ 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),
+ )
+
+ return axes
+
+
+ def setup_axes(self):
+ axes = self.get_three_d_axes(include_labels=True)
+ 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),
+ ("-1", axes.a),
+ ]
+ 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, RIGHT)
+ 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_Fundamental_Theorem_of_Line_Integrals
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file2_line_int_independent_of_path.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file2_line_int_independent_of_path.py
new file mode 100644
index 0000000..b8f7cfa
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file2_line_int_independent_of_path.py
@@ -0,0 +1,174 @@
+from manimlib.imports import *
+
+
+class LineIntegration(GraphScene):
+ CONFIG = {
+ "x_min" : -5,
+ "x_max" : 5,
+ "y_min" : -5,
+ "y_max" : 5,
+ "axes_color":BLACK,
+ "graph_origin": ORIGIN+1.2*DOWN,
+ "x_axis_width": 10,
+ "y_axis_height": 10 ,
+ "x_axis_label": "",
+ "y_axis_label": "",
+ "x_tick_frequency": 1,
+ "y_tick_frequency": 1,
+ "default_vector_field_config": {
+ "delta_x": .6,
+ "delta_y": .6,
+ "min_magnitude": 0,
+ "max_magnitude": .5,
+ "colors": [GREEN,BLUE,BLUE,TEAL],
+ "length_func": lambda norm : .45*sigmoid(norm),
+ "opacity": .75,
+ "vector_config": {
+ "stroke_width":1.5
+ },
+ },
+
+ "a": .45,"b": 2,
+ "path_color": PURPLE
+ }
+
+ 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.X=X ;self.Y=Y
+
+ self.setup_axes(animate=False)
+
+
+
+
+ vector_field=self.get_vector_field(
+ lambda v: np.array([
+ v[1]-self.graph_origin[1],
+ v[0]-self.graph_origin[0],
+ 0,
+ ])
+ )
+ vector_field_text=TexMobject(
+ "\\vec F(x,y)","=y\hat i+x\hat j",
+ stroke_width=1.5
+ ).to_edge(TOP,buff=.2)
+
+ vector_field_text[0][0:2].set_color(TEAL)
+
+ grad_f=TexMobject(
+ "\\vec\\nabla f(x,y)",
+ stroke_width=1.5
+ )
+ grad_f[0][2].set_color(LIGHT_BROWN)
+ grad_f.move_to(vector_field_text[0])
+
+ self.add(vector_field,)
+ self.play(Write(vector_field_text))
+ self.wait()
+ self.play(
+ ReplacementTransform(
+ vector_field_text[0],grad_f
+ )
+ )
+ self.get_endpoints_of_curve()
+ self.wait(.6)
+ vector_field.set_fill(opacity=.4)
+ self.show_line_integral()
+ self.wait(2)
+
+
+
+
+
+ def get_vector_field(self,func,**kwargs):
+ config = dict()
+ config.update(self.default_vector_field_config)
+ config.update(kwargs)
+ vector_field= VectorField(func,**config)
+
+ self.vector_field= vector_field
+
+ return vector_field
+
+
+
+ def get_endpoints_of_curve(self):
+ points=[[-3,0],[2,2]]
+ point_labels= ["P_f","P_i"]
+ for point,label in zip(points,point_labels):
+ dot=Dot(self.coords_to_point(*point)).set_color(RED)
+ dot_label=TexMobject(label)
+ dot_label.next_to(dot,DR,buff=.2)
+ self.play(FadeIn(VGroup(dot,dot_label)))
+ self.wait(.2)
+
+ self.end_points=points
+
+ def show_line_integral(self):
+ int_text=TexMobject(
+ r"\int_{P_i}^{P_f}\vec F \cdot d\vec r",
+ stroke_width=1.5,
+ ).scale(1.2)
+ int_text[0][0].set_color(self.path_color)
+ int_text[0][5:7].set_color(TEAL)
+ int_text.to_edge(RIGHT+UP,buff=1)
+
+ int_value= TexMobject(r"=f(P_i)-f(P_f)",
+ stroke_width=1.5
+ ).next_to(int_text,DOWN)
+ VGroup(int_value[0][1],
+ int_value[0][7]
+ ).set_color(LIGHT_BROWN)
+
+ path_indepent_text=TextMobject(
+ r"Value of the Line Integral is\\ independent of Path",color=GOLD,stroke_width=2,).to_corner(DR,buff=1)
+
+ path_indepent_text[0][-4:].set_color(self.path_color)
+
+
+ self.play(Write(VGroup(
+ int_text,int_value
+ )),
+ run_time=2
+ )
+ self.wait(1.5)
+
+
+ self.show_path([[0,1],[-1,2],[1,3]])
+ self.play(Indicate(int_value))
+ self.play(Uncreate(self.path))
+
+ self.show_path([[0,1]])
+ self.play(Indicate(int_value))
+ self.play(Uncreate(self.path))
+
+ self.show_path([[-1,1],[-1,-2],[-5,0],[-2,3.5],[1,1]])
+ self.play(Indicate(int_value),run_time=2)
+ self.wait(.6)
+
+ self.play(Write(path_indepent_text))
+
+
+
+ def show_path(self,points):
+ points=[self.end_points[0]]+points+[self.end_points[1]]
+
+ path= VMobject()
+ path.set_points_smoothly([
+ self.coords_to_point(*point)
+ for point in points
+ ])
+ path.set_color(self.path_color)
+ self.play(ShowCreation(path),run_time=1.5)
+
+ self.path=path
+
+
+
+
+
+#uploaded by Somnath Pandit. FSF2020_Fundamental_Theorem_of_Line_Integrals
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file3_line_int_example.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file3_line_int_example.py
new file mode 100644
index 0000000..71506a3
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/file3_line_int_example.py
@@ -0,0 +1,149 @@
+from manimlib.imports import *
+
+
+class LineIntegration(GraphScene):
+ CONFIG = {
+ "x_min" : -1,
+ "x_max" : 2,
+ "y_min" : -1,
+ "y_max" : 2,
+ "graph_origin": ORIGIN+3*LEFT+1.5*DOWN,
+ "x_axis_width": 10,
+ "y_axis_height": 10 ,
+ "x_tick_frequency": 1,
+ "y_tick_frequency": 1,
+ "default_vector_field_config": {
+ "delta_x": .5,
+ "delta_y": .5,
+ "min_magnitude": 0,
+ "max_magnitude": .5,
+ "colors": [GREEN,BLUE,BLUE,TEAL],
+ "length_func": lambda norm : .4*sigmoid(norm),
+ "opacity": .75,
+ "vector_config": {
+ "stroke_width":2
+ },
+ },
+
+ "a": .45,"b": 2,
+ }
+
+ 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.X=X ;self.Y=Y
+
+ self.setup_axes(animate=False)
+
+
+
+
+ vector_field=self.get_vector_field(
+ lambda v: np.array([
+ v[1]-self.graph_origin[1],
+ v[0]-self.graph_origin[0],
+ 0,
+ ])
+ )
+ vector_field_text=TexMobject(
+ "\\vec F=y\hat i+x\hat j",
+ stroke_width=2
+ ).to_corner(UR,buff=.75).scale(1.2)
+
+ vector_field_text[0][0:3].set_color(TEAL),
+ self.add(vector_field,)
+ self.play(Write(vector_field_text))
+ self.wait()
+ self.get_endpoints_of_curve()
+ self.wait(.6)
+ self.play(
+ vector_field_text.shift,5*LEFT,
+
+ )
+ vector_field.set_fill(opacity=.2)
+ self.show_line_integral()
+ self.wait(2)
+
+
+
+
+
+ def get_vector_field(self,func,**kwargs):
+ config = dict()
+ config.update(self.default_vector_field_config)
+ config.update(kwargs)
+ vector_field= VectorField(func,**config)
+
+ self.vector_field= vector_field
+
+ return vector_field
+
+
+
+ def get_endpoints_of_curve(self):
+ points=[[1,1],[0,0]]
+ point_labels= ["(1,1)","(0,0)"]
+ for point,label in zip(points,point_labels):
+ dot=Dot(self.coords_to_point(*point)).set_color(RED)
+ dot_label=TexMobject(label)
+ dot_label.next_to(dot,DR)
+ self.add(dot,dot_label)
+ self.end_points=points
+
+ def show_line_integral(self):
+ int_text=TexMobject(
+ "\\int_\\text{\\textbf{path}}\\vec F \\cdot d\\vec r= 1",
+ color=BLUE,
+ stroke_width=1.5
+ ).scale(1.2)
+ int_text[0][0].set_color(RED_C)
+ int_text[0][5:7].set_color(TEAL)
+ int_text.to_edge(RIGHT+UP,buff=1)
+
+ close_int=TexMobject("O").set_color(RED).scale(1.3)
+ close_int.move_to(int_text[0][0],OUT)
+ close_int_val=TexMobject("0",color=BLUE).scale(1.4)
+ close_int_val.move_to(int_text[0][-1],OUT)
+
+ self.play(Write(int_text))
+
+
+ self.show_method([[0,1]])
+ self.play(Indicate(int_text))
+ self.wait()
+
+ self.show_method([[1,0]])
+ self.play(Indicate(int_text))
+ self.wait()
+ self.remove(int_text[0][-1])
+ self.add(close_int)
+
+ for i in range(2):
+ self.play(self.paths[i].rotate,PI)
+ self.play(Indicate(close_int))
+ self.play(Write(close_int_val))
+ self.wait()
+
+
+ def show_method(self,points):
+ points=points+self.end_points
+ paths=[]
+ for i in range(-1,len(points)-2):
+ path=Arrow(
+ self.coords_to_point(*points[i]),
+ self.coords_to_point(*points[i+1]),
+ buff=0
+ ).set_color(BLUE)
+ paths+=VGroup(path)
+ self.play(GrowArrow(path),run_time=1.5)
+
+ self.paths=paths
+
+
+
+
+
+#uploaded by Somnath Pandit. FSF2020_Fundamental_Theorem_of_Line_Integrals
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file1_grad_of_scalar_function.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file1_grad_of_scalar_function.gif
new file mode 100644
index 0000000..1fd2e15
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file1_grad_of_scalar_function.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file2_line_int_independent_of_path.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file2_line_int_independent_of_path.gif
new file mode 100644
index 0000000..8d375bb
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file2_line_int_independent_of_path.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file3_line_int_example.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file3_line_int_example.gif
new file mode 100644
index 0000000..20ed081
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/fundamental-theorem-of-line-integral/gifs/file3_line_int_example.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/README.md b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/README.md
new file mode 100644
index 0000000..7e4299d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/README.md
@@ -0,0 +1,15 @@
+**file1_scalar_line_int_as_sum**
+![file1_scalar_line_int_as_sum](gifs/file1_scalar_line_int_as_sum.gif)
+
+**file2_scalar_line_integral**
+![file2_scalar_line_integral](gifs/file2_scalar_line_integral.gif)
+
+
+**file3_vector_line_int_as_sum**
+![file3_vector_line_int_as_sum](gifs/file3_vector_line_int_as_sum.gif)
+
+**file4_vector_line_integral**
+![file4_vector_line_integral](gifs/file4_vector_line_integral.gif)
+
+**file5_helix**
+![file5_helix](gifs/file5_helix.gif)
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file1_scalar_line_int_as_sum.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file1_scalar_line_int_as_sum.py
new file mode 100644
index 0000000..af32ebf
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file1_scalar_line_int_as_sum.py
@@ -0,0 +1,227 @@
+from manimlib.imports import *
+
+
+class LineIntegrationAsSum(GraphScene):
+ CONFIG = {
+ "x_min" : 0,
+ "x_max" : 10,
+ "y_min" : 0,
+ "y_max" : 6,
+ "graph_origin": ORIGIN+5*LEFT+3*DOWN,
+ "x_axis_width": 10,
+ "y_axis_height": 6 ,
+ "x_tick_frequency": 2,
+ "y_tick_frequency": 2,
+ "Func":lambda x : 1+x**1.3*np.exp(-.12*(x-2)**2)*np.sin(x/4),
+ "a": 1 ,"b": 9, "n": 15,
+ }
+
+ 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.X=X ;self.Y=Y
+
+ self.setup_axes(animate=False)
+
+ curve=self.get_graph(
+ self.Func,
+ x_min=self.a,
+ x_max=self.b,
+ )
+ curve.set_color([BLACK,BLUE,BLUE,BLUE,BLACK])
+ curve_label= self.get_graph_label(
+ curve,
+ label="\\text{path of intgration}",
+ x_val=4,
+ direction=UR,
+ buff=.6,
+ color=BLUE
+ )
+ self.curve=curve
+ self.curve_label=curve_label
+
+ self.play(ShowCreation(VGroup(curve,curve_label)))
+ self.wait(.6)
+ self.break_in_arcs()
+ self.show_the_sum()
+ self.construct_equation()
+ self.wait(2)
+
+
+
+ def break_in_arcs(self):
+
+ self.write_about_breaking()
+
+ dl=0.8
+ self.get_breakers(dl)
+ self.wait(2)
+ self.play(FadeOut(self.upto_break_text))
+ self.dl=dl
+
+ def write_about_breaking(self):
+ breaking_text=TextMobject("\\texttt{..broken}"," into small", "subarcs")
+ breaking_text.set_color_by_tex_to_color_map({
+ "broken":RED,"subarcs": BLUE
+ })
+ breaking_text.next_to(self.curve_label,DOWN)
+ breaking_text.align_to(self.curve_label,LEFT)
+ self.play(
+ Write(breaking_text)
+ )
+
+ self.upto_break_text=VGroup(
+ self.curve_label,
+ breaking_text,
+ )
+
+ def get_breakers(self,dl):
+ point=self.a
+ points=[]
+ while point<(self.b-dl) :
+ start=point
+ end=point+dl
+ points += [end]
+ breaker=Line(
+ self.input_to_graph_point(start,self.curve),
+ self.input_to_graph_point(end,self.curve),
+ stroke_width=2,
+ color=RED,
+ )
+ breaker.rotate(PI/2).scale(.5)
+
+ point=end
+ self.play(FadeIn(breaker),run_time=.2)
+ # self.add(breaker)
+
+ del points[-1]
+ self.points=points
+
+
+ def show_the_sum(self):
+ at_any_points_text=TextMobject("At any ","point", "in each ", "subarc")
+ at_any_points_text.set_color_by_tex_to_color_map({
+ "point":YELLOW , "subarc": BLUE
+ })
+ at_any_points_text.to_edge(TOP,buff=SMALL_BUFF)
+
+ evaluate_text=TextMobject("$f(x,y)$ ", "is evaluated").next_to(at_any_points_text,DOWN)
+ evaluate_text.set_color_by_tex("$f(x,y)$",ORANGE)
+
+ self.at_any_points_text=at_any_points_text
+ self.evaluate_text=evaluate_text
+
+
+ dots=[]
+ for point in self.points:
+
+ dot=Dot(
+ point=self.input_to_graph_point(point,self.curve),
+ radius= .7*DEFAULT_DOT_RADIUS,
+ stroke_width= 0,
+ fill_opacity= 1.0,
+ color= YELLOW,
+ )
+ dots+=[dot]
+
+ self.play(
+ Write(at_any_points_text),
+ FadeIn(VGroup(*dots)),run_time=1.5
+ )
+ self.wait()
+ self.position_of_point_irrelevent()
+ self.multiply_with_function(dots)
+
+
+
+ def multiply_with_function(self,dots):
+ index=-(len(self.points)//3)
+ dot=dots[index]
+
+
+ multiply_text=TexMobject("f(x_i,y_i)", "\\text{ is multiplied with }","\\Delta s_i")
+ multiply_text.set_color_by_tex_to_color_map({
+ "f(x_i,y_i)":ORANGE , "\\Delta s_i": BLUE
+ })
+ multiply_text.to_edge(TOP,buff=MED_SMALL_BUFF)
+
+ point_coord=TextMobject("$(x_i,y_i)$",color=YELLOW)
+ point_coord.next_to(dot,DL,buff=.01).scale(.8)
+
+ func_val=TextMobject("$f(x_i,y_i)$",color=ORANGE)
+ func_val.next_to(dot,UR)
+
+ sum_up_text=TextMobject("and "," summed ", "for all i' s")
+ sum_up_text.set_color_by_tex("summed",PURPLE)
+ sum_up_text.next_to(multiply_text,DOWN)
+
+
+ self.play(FadeIn(VGroup(
+ point_coord,dot
+ )))
+ self.play(Write(self.evaluate_text))
+ self.play(Write(func_val))
+
+ self.wait(2)
+ self.remove(point_coord)
+ self.get_ds(dots,index)
+ self.play(GrowFromCenter(self.ds_brace_group))
+ self.wait(2)
+ self.play(FadeOut(VGroup(
+ self.ds_brace,
+ self.at_any_points_text,
+ self.evaluate_text
+ )))
+ self.play(Write(multiply_text))
+ self.play(ApplyMethod(
+ self.ds_brace_label.next_to,
+ func_val, RIGHT,buff=.2
+ ))
+ self.play(Write(sum_up_text))
+ dot.set_color(ORANGE).scale(1.2)
+ self.play(FadeIn(VGroup(*[
+ dot.set_color(ORANGE).scale(1.4)
+ for dot in dots ]
+ )))
+ self.func_val=func_val
+ self.sum_text_group=VGroup(multiply_text,sum_up_text)
+
+ def position_of_point_irrelevent(self):
+ pass
+
+
+
+ def get_ds(self,dots,index):
+ p1= dots[index]
+ p2= dots[index+1]
+ ds_brace=Brace(VGroup(p1,p2),DL)
+ ds_brace.move_to(p1,UR)
+ ds_brace_label=ds_brace.get_text("$\Delta s_i$", buff = .05)
+ ds_brace_label.set_color(BLUE)
+ self.ds_brace=ds_brace
+ self.ds_brace_label=ds_brace_label
+ self.ds_brace_group=VGroup(ds_brace,ds_brace_label)
+
+
+ def construct_equation(self):
+ sum_eqn=TextMobject("$$\\sum_i^{ } $$").set_color(PURPLE)
+ sum_eqn.move_to(self.graph_origin+7*self.X+4*self.Y)
+
+ line_integral_text=TextMobject("The Value of the line integral is").next_to(self.sum_text_group,IN)
+ approx=TextMobject("$\\approx$",color=RED).next_to(sum_eqn,LEFT)
+ multipled=VGroup(self.func_val,self.ds_brace_label)
+ self.play(FadeIn(sum_eqn))
+ self.play(ApplyMethod(
+ multipled.next_to,sum_eqn,RIGHT
+ ))
+ self.wait()
+ self.play(FadeOut(self.sum_text_group))
+ self.play(Write(line_integral_text))
+ self.play(FadeIn(approx))
+
+
+
+#uploaded by Somnath Pandit.FSF2020_Line Integrals
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file2_scalar_line_integral.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file2_scalar_line_integral.py
new file mode 100644
index 0000000..200f768
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file2_scalar_line_integral.py
@@ -0,0 +1,427 @@
+from manimlib.imports import *
+
+class LineIntegrationProcess(SpecialThreeDScene):
+
+ CONFIG = {
+ "axes_config": {
+ "x_min": -4,
+ "x_max": 4,
+ "y_min": 0,
+ "y_max": 4,
+ "z_min": 0,
+ "z_max": 4,
+ "a":-3 ,"b": 3, "c":0 , "d":3.5,
+ "axes_shift":3*IN,
+ "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.2,
+ "stroke_color": WHITE,
+ "stroke_opacity": 0.75,
+ },
+ "Func": lambda x,y: 1+x**2*y/15
+ }
+
+
+ def construct(self):
+
+ self.setup_axes()
+ axes=self.axes
+
+ self.set_camera_orientation(distance=35,
+ phi=60 * DEGREES,
+ theta=-60 * DEGREES,
+ )
+
+ fn_text=TextMobject("$z=2+x^2y$").set_color(BLUE)
+ fn_text.to_corner(UR,buff=.8).shift(DOWN)
+
+ #get the surface
+ surface= self.get_surface(
+ lambda x , y:
+ self.Func(x,y)
+ )
+ surface.set_style(
+ fill_opacity=0.5,
+ fill_color=BLUE_D,
+ stroke_width=0.5,
+ stroke_color=WHITE,
+ )
+
+
+ # self.play(Write(surface))
+ self.add_fixed_in_frame_mobjects(fn_text)
+ self.play(Write(surface),Write(fn_text))
+ self.get_line_of_int()
+ self.begin_ambient_camera_rotation(rate=-0.035)
+ self.get_field_values_on_line()
+ self.wait(1.5)
+ self.area=self.get_area()
+ area_text=TextMobject("Line"," Integral in the",r" scalar field\\"," means this" ,"area")
+ area_text.set_color_by_tex_to_color_map({
+ "Line": PINK, "scalar":BLUE, "area":TEAL_A
+ })
+ area_text.to_edge(TOP,buff=MED_SMALL_BUFF)
+
+ self.remove(self.values_on_line_text)
+ self.add_fixed_in_frame_mobjects(area_text)
+ self.play(Write(area_text))
+ self.play(Write(self.area),run_time=2)
+ self.play(FadeOut(VGroup(surface,fn_text)))
+ self.move_camera(
+ # distance=20,
+ phi=90 * DEGREES,
+ # theta=-90 * DEGREES,
+ # added_anims=into_graph,
+ run_time=2
+ )
+ self.wait(2)
+
+ self.stop_ambient_camera_rotation()
+ # self.get_lines()
+
+ self.remove(axes,surface)
+ self.trasform_to_graphs()
+ self.wait(2)
+
+
+
+
+ def get_line_of_int(self):
+ line_of_int_text=TextMobject(r"Line of integration is\\","$\\vec r(t)=\cos(t)\hat x+\sin(t)\hat y$")
+ line_of_int_text[1].set_color(PINK)
+ line_of_int_text.to_edge(TOP,buff=SMALL_BUFF)
+
+
+ line_of_int=(self.get_curve(
+ self.Func,on_surface=False
+ ))
+ line_of_int.set_style(
+ stroke_width=5,
+ stroke_color=PINK,
+ )
+
+ self.add_fixed_in_frame_mobjects(line_of_int_text)
+ self.play(Write(line_of_int_text))
+ self.wait()
+ self.play(ShowCreation(line_of_int),run_time=3)
+ # self.add(line_of_int)
+
+ self.line_of_int=line_of_int
+ self.line_of_int_text=line_of_int_text
+
+ def get_field_values_on_line(self):
+ self.remove(self.line_of_int_text)
+
+ values_on_line_text=TextMobject("Values"," of"," function","on the ","line")
+ values_on_line_text.set_color_by_tex_to_color_map({
+ "Values":YELLOW, "function":BLUE,"line":PINK
+ })
+ values_on_line_text.to_edge(TOP,buff=SMALL_BUFF)
+
+ values_on_surface=(self.get_curve(
+ self.Func,on_surface=True
+ ))
+ values_on_surface.set_style(
+ stroke_width=5,
+ stroke_color=YELLOW,
+ )
+
+ self.add_fixed_in_frame_mobjects(values_on_line_text)
+ self.play(Write(values_on_line_text))
+ # self.wait()
+ self.play(ShowCreation(values_on_surface),run_time=3)
+ # self.add(values_on_surface)
+
+ self.values_on_surface=values_on_surface
+ self.values_on_line_text=values_on_line_text
+
+
+ def trasform_to_graphs(self):
+ on_surface_graph=(self.get_graph(
+ self.Func,on_surface=True
+ ))
+ on_surface_graph.set_style(
+ stroke_width=5,
+ stroke_color=YELLOW,
+ )
+
+ line_graph=(self.get_graph(
+ self.Func,on_surface=False
+ ))
+ line_graph.set_style(
+ stroke_width=5,
+ stroke_color=PINK,
+ )
+
+ self.on_surface_graph=on_surface_graph
+ self.line_graph=line_graph
+ graph_area=self.get_area(graph=True)
+
+ into_graph=[
+ ReplacementTransform(
+ self.values_on_surface,
+ on_surface_graph
+ ),
+ ReplacementTransform(
+ self.line_of_int,
+ line_graph
+ ),
+ ReplacementTransform(
+ self.area,
+ graph_area
+ ),
+ ]
+
+ self.move_camera(
+ # distance=20,
+ phi=90 * DEGREES,
+ theta=-90 * DEGREES,
+ added_anims=into_graph,
+ run_time=2
+ )
+
+ def get_area(self,graph=False):
+ axes=self.axes
+ if graph:
+ on_surface=self.on_surface_graph
+ on_base=self.line_graph
+ else:
+ on_surface=self.values_on_surface
+ on_base=self.line_of_int
+ area =Polygon(
+ *[
+ on_surface.get_point_from_function(t)
+ for t in np.arange(0,PI,0.01)
+ ],
+ *[
+ on_base.get_point_from_function(t)
+ for t in np.arange(PI,0,-0.01)
+ ],
+ stroke_width=0,
+ fill_color=TEAL_A,
+ fill_opacity=.6,
+ )
+
+ return area
+
+ def get_curve(self,func,on_surface=False ,**kwargs):
+ config = dict()
+ config.update(self.default_graph_style)
+ config.update({
+ "t_min": 0,
+ "t_max": PI,
+ })
+ config.update(kwargs)
+ r=abs(self.axes.a)
+ curve=ParametricFunction(
+ lambda t: self.axes.c2p(
+ r*np.cos(t),
+ r*np.sin(t),
+ func(r*np.cos(t), r*np.sin(t))*bool(on_surface)
+ ),
+ **config,
+ )
+ return curve
+
+
+ def get_surface(self, func, **kwargs):
+ axes=self.axes
+ config = {
+ "u_min": axes.a-.2,
+ "u_max": axes.b+.2,
+ "v_min": axes.c-.1,
+ "v_max": axes.d,
+ "resolution": (
+ 2*(axes.y_max - axes.y_min) // axes.y_axis.tick_frequency,
+ (axes.x_max - axes.x_min) // axes.x_axis.tick_frequency,
+ ),
+ }
+
+ config.update(self.default_surface_config)
+ config.update(kwargs)
+ return ParametricSurface(
+ lambda x,y : axes.c2p(
+ x, y, func(x, y)
+ ),
+ **config
+ )
+
+ def get_graph(self,func,on_surface=False ,**kwargs):
+ config = dict()
+ config.update(self.default_graph_style)
+ config.update({
+ "t_min": 0,
+ "t_max": PI,
+ })
+ config.update(kwargs)
+ slice_curve=ParametricFunction(
+ lambda t: self.axes.c2p(
+ 4*np.cos(t),
+ 0,
+ 2+func(3*np.cos(t), 3*np.sin(t))*bool(on_surface)
+ ),
+ **config,
+ )
+ return slice_curve
+
+ def get_lines(self):
+ pass
+ 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,"PINK"))
+
+ 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))
+ self.add(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)
+ self.axes=axes
+
+ 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(
+ 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),
+ ("-1", axes.a),
+ ]
+ 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, RIGHT)
+ 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_Line_Integrals
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file3_vector_line_int_as_sum.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file3_vector_line_int_as_sum.py
new file mode 100644
index 0000000..78294cc
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file3_vector_line_int_as_sum.py
@@ -0,0 +1,326 @@
+from manimlib.imports import *
+
+
+class LineIntegrationAsSum(GraphScene):
+ CONFIG = {
+ "x_min" : 0,
+ "x_max" : 10,
+ "y_min" : 0,
+ "y_max" : 6,
+ "graph_origin": ORIGIN+5*LEFT+3*DOWN,
+ "x_axis_width": 10,
+ "y_axis_height": 6 ,
+ "x_tick_frequency": 2,
+ "y_tick_frequency": 2,
+ "Func":lambda x : 1+x**1.3*np.exp(-.12*(x-2)**2)*np.sin(x/4),
+ "a": 1 ,"b": 9, "n": 15,
+ }
+
+ 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.X=X ;self.Y=Y
+
+ self.setup_axes(animate=False)
+
+
+ curve=self.get_graph(
+ self.Func,
+ x_min=self.a,
+ x_max=self.b,
+ )
+ curve.set_color([BLACK,BLUE,BLUE,BLUE,BLACK])
+ curve_label= self.get_graph_label(
+ curve,
+ label="\\text{path of intgration}",
+ x_val=4,
+ direction=UR,
+ buff=.6,
+ color=BLUE
+ )
+ self.curve=curve
+ self.curve_label=curve_label
+
+ self.get_vector_field()
+
+
+ self.play(ShowCreation(VGroup(curve,curve_label)))
+ self.wait(.6)
+ self.break_in_arcs()
+ self.show_the_sum()
+
+ self.wait(2)
+
+
+ def get_vector_field(self):
+ func = lambda v: np.array([
+ v[0], # x
+ -v[1], # y
+ 0 # z
+ ])
+ vector_field= VectorField(
+ func,
+ delta_x=1,
+ delta_y=1,
+ colors=[GREEN_A,GREEN_C],
+ length_func= lambda norm: .8*sigmoid(norm),
+ vector_config={
+ "stroke_width": 2
+ }
+ )
+
+ self.vector_field= vector_field
+
+
+ def break_in_arcs(self):
+
+ self.write_about_breaking()
+
+ dl=0.8
+ self.get_breakers(dl)
+ self.wait(2)
+ self.play(FadeOut(self.upto_break_text))
+ self.dl=dl
+
+ def write_about_breaking(self):
+ breaking_text=TextMobject("\\texttt{..broken}"," into small", "subarcs")
+ breaking_text.set_color_by_tex_to_color_map({
+ "broken":RED,"subarcs": BLUE
+ })
+ breaking_text.next_to(self.curve_label,DOWN)
+ breaking_text.align_to(self.curve_label,LEFT)
+ self.play(
+ Write(breaking_text)
+ )
+
+ self.upto_break_text=VGroup(
+ self.curve_label,
+ breaking_text,
+ )
+
+ def get_breakers(self,dl):
+ point=self.a
+ points=[]
+ while point<(self.b-dl) :
+ start=point
+ end=point+dl
+ points += [end]
+ breaker=Line(
+ self.input_to_graph_point(start,self.curve),
+ self.input_to_graph_point(end,self.curve),
+ stroke_width=2,
+ color=RED,
+ )
+ breaker.rotate(PI/2).scale(.5)
+
+ point=end
+ self.play(FadeIn(breaker),run_time=.2)
+ # self.add(breaker)
+
+ del points[-1]
+ self.points=points
+
+
+ def show_the_sum(self):
+ at_any_points_text=TextMobject("At any ","point", "in each ", "subarc")
+ at_any_points_text.set_color_by_tex_to_color_map({
+ "point":YELLOW , "subarc": BLUE
+ })
+ at_any_points_text.to_edge(TOP,buff=SMALL_BUFF)
+
+ evaluate_text=TextMobject("$\\vec F(x,y)$ ", "is evaluated").next_to(at_any_points_text,DOWN)
+ evaluate_text.set_color_by_tex("$\\vec F(x,y)$",ORANGE)
+
+ multiply_text=TextMobject("...is multiplied with ","$\\Delta s_i$")
+ multiply_text.set_color_by_tex("\\Delta s_i", BLUE)
+ multiply_text.next_to(at_any_points_text,DOWN)
+
+
+
+ self.at_any_points_text=at_any_points_text
+ self.evaluate_text=evaluate_text
+ self.multiply_text=multiply_text
+
+ dots=[]
+ for point in self.points:
+
+ dot=Dot(
+ point=self.input_to_graph_point(point,self.curve),
+ radius= .7*DEFAULT_DOT_RADIUS,
+ stroke_width= 0,
+ fill_opacity= 1.0,
+ color= YELLOW,
+ )
+ dots+=[dot]
+
+ self.play(
+ Write(at_any_points_text),
+ FadeIn(VGroup(*dots)),run_time=1.5
+ )
+ self.dots=dots
+
+ self.wait()
+ self.show_the_dot_product()
+ self.multiply_with_ds()
+ self.construct_equation()
+
+
+ def show_the_dot_product(self):
+ index=-(len(self.points)//3)
+ self.index=index
+
+ dot=self.dots[index]
+
+
+ dot_prod_text=TextMobject("Dot Product of", "$\\vec F(x_i,y_i)$", "and","$\\vec T(x_i,y_i)$")
+ dot_prod_text.set_color_by_tex_to_color_map({
+ "\\vec F(x_i,y_i)":ORANGE ,
+ "\\vec T(x_i,y_i)": "#DC75CD" ,
+ })
+ dot_prod_text.to_edge(TOP,buff=SMALL_BUFF)
+
+
+ point_coord=TextMobject("$(x_i,y_i)$",color=YELLOW)
+ point_coord.next_to(dot,DL,buff=.01).scale(.8)
+
+ func_val=TextMobject("$\\vec F(x_i,y_i)$",color=ORANGE)
+ func_val.next_to(dot,UR).scale(.8)
+
+ self.dot_prod_text=dot_prod_text
+ self.func_val=func_val
+
+ dot.set_color(ORANGE).scale(1.2)
+
+
+ self.play(FadeIn(VGroup(point_coord,dot)))
+ self.play(Write(self.evaluate_text))
+ self.wait(1)
+ self.play(FadeOut(self.vector_field))
+ self.get_vector_and_tangent()
+ self.dot_product()
+
+
+ self.wait(2)
+ self.remove(point_coord)
+
+
+ def get_vector_and_tangent(self):
+ dot=self.dots[self.index]
+ self.show_specific_vectors(dot)
+ self.play(Write(self.func_val))
+ self.wait(1)
+ self.show_tangent(dot)
+ self.play(FadeIn(VGroup(*[
+ dot.set_color(ORANGE).scale(1.4)
+ for dot in self.dots ]
+ )))
+
+
+ def show_specific_vectors(self,dots):
+ for dot in dots:
+ vector=self.vector_field.get_vector(dot.get_center())
+ vector.set_color(ORANGE)
+
+ self.play(Write(vector),run_time=.2)
+
+
+ def show_tangent(self,dot):
+ tangent_sym=TextMobject("$\\vec T(x_i,y_i)$",color="#DC75CD").scale(.8)
+ x=dot.get_center()
+ angle=self.angle_of_tangent(
+ self.point_to_coords(x)[0],
+ self.curve,
+ dx=0.01
+ )
+ vect = Vector().rotate(angle,about_point=x)
+ vect.set_color("#DC75CD")
+ tangent=vect.next_to(x,DR,buff=0)
+ tangent_sym.next_to(tangent,DOWN,buff=.1)
+ self.play(Write(VGroup(tangent,tangent_sym)))
+
+ self.tangent_sym=tangent_sym
+
+ def dot_product(self):
+
+ dot_sym=Dot().next_to(self.func_val,RIGHT)
+
+ self.play(FadeOut(VGroup(
+ self.at_any_points_text,
+ self.evaluate_text
+ )))
+ self.play(Write(self.dot_prod_text))
+ self.play(
+ FadeIn(dot_sym),
+ ApplyMethod(
+ self.tangent_sym.next_to,
+ dot_sym, RIGHT
+ ))
+
+ self.dot_sym=dot_sym
+
+ def multiply_with_ds(self):
+ self.get_ds()
+
+ self.play(GrowFromCenter(self.ds_brace_group))
+ self.wait(2)
+ self.play(Write(self.multiply_text))
+ self.play(ApplyMethod(
+ self.ds_brace_label.next_to,
+ self.tangent_sym, RIGHT,buff=.15
+ ))
+
+
+
+ def get_ds(self):
+ p1= self.dots[self.index]
+ p2= self.dots[self.index+1]
+ ds_brace=Brace(VGroup(p1,p2),DL)
+ ds_brace.move_to(p1,UR)
+ ds_brace_label=ds_brace.get_text("$\Delta s_i$", buff = .05)
+ ds_brace_label.set_color(BLUE)
+ self.ds_brace=ds_brace
+ self.ds_brace_label=ds_brace_label
+ self.ds_brace_group=VGroup(ds_brace,ds_brace_label)
+
+
+ def construct_equation(self):
+ sum_up_text=TextMobject("and"," summed ", "for all i' s")
+ sum_up_text.set_color_by_tex("summed",PURPLE_A)
+ sum_up_text.next_to(self.multiply_text,DOWN,buff=MED_SMALL_BUFF)
+ sum_up_text.shift(LEFT)
+
+ sum_eqn=TextMobject("$$\\sum_i^{ } $$").set_color(PURPLE_A)
+ sum_eqn.move_to(self.graph_origin+6.5*self.X+4*self.Y)
+
+ line_integral_text=TextMobject("The Value of the"," line ","integral is").to_edge(TOP,buff=MED_SMALL_BUFF)
+ line_integral_text.set_color_by_tex("line",BLUE_C)
+ approx=TextMobject("$\\approx$",color=RED).next_to(sum_eqn,LEFT)
+ multipled=VGroup(
+ self.func_val,
+ self.dot_sym,
+ self.tangent_sym,
+ self.ds_brace_label
+ )
+
+
+ self.play(Write(sum_up_text))
+ self.show_specific_vectors(self.dots)
+ self.play(FadeIn(sum_eqn))
+ self.play(ApplyMethod(
+ multipled.next_to,sum_eqn,RIGHT
+ ))
+ self.wait()
+ self.play(FadeOut(VGroup(
+ self.dot_prod_text,
+ self.multiply_text,
+ sum_up_text
+ )))
+ self.play(Write(line_integral_text))
+ self.play(FadeIn(approx))
+
+
+
+#uploaded by Somnath Pandit.FSF2020_Line Integrals
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file4_vector_line_integral.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file4_vector_line_integral.py
new file mode 100644
index 0000000..6730820
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file4_vector_line_integral.py
@@ -0,0 +1,374 @@
+from manimlib.imports import *
+
+class LineIntegrationProcess(GraphScene):
+
+ CONFIG = {
+ "x_min" : -0,
+ "x_max" : 1,
+ "y_min" : -0,
+ "y_max" : 1,
+ "axes_color":WHITE,
+ "graph_origin": ORIGIN+6.3*LEFT+3*DOWN,
+ "x_axis_width": 5.5,
+ "y_axis_height": 5.5,
+ "x_tick_frequency": 1,
+ "y_tick_frequency": 1,
+ "default_vector_field_config": {
+ "delta_x": .5,
+ "delta_y": .5,
+ "min_magnitude": 0,
+ "max_magnitude": 15,
+ "colors": [BLUE],
+ "length_func": lambda norm : norm/35,
+ "opacity": 1.0,
+ "vector_config": {
+ "stroke_width":2
+ },
+ },
+ "default_graph_style": {
+ "stroke_width": 2,
+ "stroke_color": WHITE,
+ },
+ }
+
+
+ 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.X=X ;self.Y=Y
+
+ self.setup_axes(animate=False)
+
+ fn_text=TexMobject(
+ r"\vec F = x^2\hat i-xy\hat j",
+ stroke_width=2.5
+ ).set_color_by_gradient(
+ *self.default_vector_field_config["colors"]
+ )
+ fn_text.to_edge(TOP,buff=.1).shift(2*LEFT)
+
+ origin=self.graph_origin
+ v_field=self.get_vector_field(
+ lambda v: np.array([
+ (v[0]-origin[0])**2,
+ -(v[0]-origin[0])*(v[1]-origin[1]),
+ 0,
+ ]),
+ x_min= -.001+origin[0],
+ x_max= 5.4+origin[0],
+ y_min= -0+origin[1],
+ y_max= 5.5+origin[1],
+ )
+
+ self.add(v_field, fn_text)
+ self.play(Write(fn_text))
+ self.wait(2)
+ self.get_line_of_int()
+ self.get_dot_product_values()
+ self.wait(2)
+ self.remove(v_field,fn_text)
+ self.write_area_as_intgral_value()
+ self.wait(2)
+
+
+ def get_vector_field(self,func,**kwargs):
+ config = dict()
+ config.update(self.default_vector_field_config)
+ config.update(kwargs)
+ vector_field= VectorField(func,**config)
+ self.vector_field=vector_field
+
+ return vector_field
+
+ def get_line_of_int(self):
+ line_of_int_text=TextMobject(
+ r"Line of integration is\\",
+ "$\\vec r(t)=\cos(t)\hat i+\sin(t)\hat j$"
+ )
+ line_of_int_text[1].set_color(PINK)
+ line_of_int_text.to_corner(UR,buff=.8)
+
+
+ line_of_int= self.get_graph(
+ lambda x : np.sqrt(1-x**2),
+ x_min=1,
+ x_max=0,
+ )
+ line_of_int.set_style(
+ stroke_width=3,
+ stroke_color=PINK,
+ )
+
+ self.play(Write(line_of_int_text))
+ self.wait(.5)
+ self.play(ShowCreation(line_of_int),run_time=2)
+ # self.add(line_of_int)
+
+ self.line_of_int=line_of_int
+ self.line_of_int_text=line_of_int_text
+
+
+ def get_dot_product_values(self):
+ t_tracker = ValueTracker(0)
+ self.t_tracker = t_tracker
+ self.get_vector_and_tangent()
+ self.get_dot_product_graph()
+ self.wait(1.5)
+ self.play(ApplyMethod(
+ self.t_tracker.set_value, PI/6,
+ rate_func=linear,
+ run_time=2.5,
+ )
+ )
+ self.wait(1)
+ self.play(ApplyMethod(
+ self.t_tracker.set_value, PI/2,
+ rate_func=linear,
+ run_time=4,
+ )
+ )
+ self.dot_prod_graph.suspend_updating()
+
+ def get_vector_and_tangent(self):
+ vect_tangent_text=TextMobject(
+ "Get the"," vector",r" and\\"," tangent",
+ " on the"," line"
+ )
+ vect_tangent_text.set_color_by_tex_to_color_map({
+ "tangent": ORANGE, "vector": YELLOW, "line":PINK
+ })
+ vect_tangent_text.to_corner(UR,buff=.8)
+ self.vect_tangent_text= vect_tangent_text
+
+ self.play(FadeOut(self.axes))
+ self.remove(self.line_of_int_text)
+ self.play(Write(vect_tangent_text))
+ self.show_vector()
+ self.show_tangent()
+ self.wait(1.3)
+
+ def show_vector(self):
+ t = self.t_tracker.get_value
+ vect_label=TextMobject(
+ "$\\vec F(x_i,y_i)$",
+ color=YELLOW,
+ stroke_width=2
+ ).scale(.8)
+
+ vector = always_redraw( lambda:
+ self.vector_field.get_vector(
+ self.coords_to_point(
+ np.cos(t()), np.sin(t())
+ ),
+ stroke_width=6,
+ max_stroke_width_to_length_ratio= 8,
+ ).set_color(YELLOW),
+ )
+
+ vect_label.next_to(vector,RIGHT,buff=.1)
+ vector_group= VGroup(vector,vect_label)
+
+ # self.add(vector_group)
+ self.play(Write(vector_group),run_time=1)
+ self.wait(.4)
+
+ self.vect_label = vect_label
+ self.vector_group= vector_group
+
+ def show_tangent(self):
+ tangent_label=TextMobject(
+ "$\\vec T(x_i,y_i)$",
+ color=ORANGE,
+ stroke_width=2
+ ).scale(.8)
+
+ t = self.t_tracker.get_value
+
+ tangent = always_redraw(lambda:
+ Vector(
+ color=ORANGE,
+ stroke_width=6,
+ ).scale(1).next_to(
+ self.coords_to_point(
+ np.cos(t()), np.sin(t())
+ ),DR,buff=-.1
+ ).rotate(
+ self.angle_of_tangent(
+ np.cos(t()),
+ self.line_of_int,
+ dx=-0.00001
+ ),
+ about_point=self.coords_to_point(
+ np.cos(t()), np.sin(t())
+ )
+ )
+ )
+ tangent_label.next_to(tangent,UP,buff=.1)
+ tangent_group=VGroup(tangent,tangent_label)
+
+ # self.add(tangent_group)
+ self.play(Write(tangent_group))
+ self.wait(.6)
+
+ self.tangent_label=tangent_label
+ self.tangent_group=tangent_group
+
+ def get_dot_product_graph(self):
+ t = self.t_tracker.get_value
+
+ self.start_x= 1.3 ; self.end_x=2.3
+
+ t_axis= self.get_graph(
+ lambda x : 2.0/5,
+ x_min= self.start_x,
+ x_max= self.end_x,
+ ).set_style(
+ stroke_width=4,
+ )
+
+ dot_prod_axis= Vector(3*UP).next_to(
+ t_axis,LEFT,buff=-.1
+ ).set_color(GREEN)
+ dot_prod_label=TexMobject(
+ "\\vec F","\\cdot","\\vec T",
+ stroke_width= 1.5,
+ ).next_to(dot_prod_axis,UP).scale(.8)
+ dot_prod_label[0].set_color(YELLOW)
+ dot_prod_label[2].set_color(ORANGE)
+
+ dot_prod_graph_axes= VGroup(t_axis,dot_prod_axis)
+
+ self.write_about_graph()
+ self.wait(1)
+ # self.add(dot_prod_graph_axes)
+ self.play(Write(dot_prod_graph_axes))
+ self.show_the_parameter(t,t_axis)
+ self.wait(.6)
+ self.play(ReplacementTransform(
+ self.vect_label,dot_prod_label[0]
+ ))
+ self.play(ReplacementTransform(
+ self.tangent_label,dot_prod_label[1:3]
+ ))
+ self.show_graph_area(t_axis)
+
+ self.dot_prod_graph_axes= dot_prod_graph_axes
+ self.dot_prod_label= dot_prod_label
+
+ def write_about_graph(self):
+ graph_text=TextMobject(
+ "Graph",r" of the "," vector",r" $-$\\ ",
+ r"tangent",r" dot product\\",
+ " with the parameter ","$t$"
+ )
+ graph_text.set_color_by_tex_to_color_map({
+ "Graph":GREEN, "vector": YELLOW,
+ "tangent":ORANGE, "$t$":RED
+ })
+ graph_text.to_corner(UR,buff=.5)
+ self.graph_text=graph_text
+
+ self.remove(self.vect_tangent_text)
+ self.play(Write(graph_text),run_time=4)
+
+ def show_the_parameter(self,t,t_axis):
+ t_dot=Dot(color=RED).next_to(t_axis,LEFT,buff=0)
+ t_dot.add_updater(lambda obj :
+ obj.move_to(self.c2g([t(),0])
+ ))
+ t_text=TextMobject("$t$=").next_to(t_dot,UP,buff=.25)
+ t_val=always_redraw(
+ lambda: DecimalNumber(
+ t()/PI,
+ color=GOLD
+ ).next_to(t_text,RIGHT,buff=0).scale(.8)
+ )
+ t_label=VGroup(
+ t_text,t_val
+ ).set_color(RED)
+
+
+ pi = TexMobject(
+ "\\pi ",
+ color=GOLD,
+ ).next_to(t_val,RIGHT,buff=0.05)
+ t_label.add(pi)
+
+ t_label.add_updater(lambda label :
+ label.next_to(t_dot,UP)
+ )
+
+ t_group=VGroup(t_dot,t_label)
+
+ # self.add(t_group)
+ self.play(Write(t_group))
+
+ self.t_group= t_group
+
+
+ def show_graph_area(self,t_axis):
+ t = self.t_tracker.get_value
+ dot_prod_graph= always_redraw(lambda: Polygon(
+ *[
+ self.c2g([t,-2*np.cos(t)**2*np.sin(t)])
+ for t in np.arange(0,t(),0.01)
+ ],
+ *[
+ self.c2g([t,0])
+ for t in [ t(),0 ]
+ ],
+ stroke_width=2.5,
+ fill_color=TEAL_D,
+ fill_opacity=.6,
+ ))
+
+ self.add(dot_prod_graph)
+
+ self.dot_prod_graph=dot_prod_graph
+
+ def c2g(self,coord):
+ """ get points for the dot product graph
+ from its coordinates"""
+
+ return self.coords_to_point(
+ self.start_x+coord[0]/(PI/2),
+ 2.0/5+coord[1]/2,
+ )
+
+
+ def write_area_as_intgral_value(self):
+ area_text=TextMobject(
+ "Value of the "," line"," integral in the",
+ r"Vector field\\",
+ "is equal to this ","area"
+ )
+ area_text.set_color_by_tex_to_color_map({
+ "Vector field": BLUE, "line":PINK, "area":TEAL_C
+ })
+ area_text.to_edge(TOP,buff=MED_SMALL_BUFF)
+
+
+ self.play(FadeOut(VGroup(
+ self.line_of_int,
+ self.vector_group,
+ self.tangent_group,
+ self.t_group,
+ self.dot_prod_graph_axes,
+ self.dot_prod_label,
+ self.graph_text
+ )
+ ))
+ area= self.dot_prod_graph.copy().scale(1.3)
+ area.next_to(area_text,DOWN,buff=1.5)
+
+ # self.add(area_text)
+ self.play(Write(area_text),run_time=4)
+ self.play(ReplacementTransform(
+ self.dot_prod_graph,
+ area
+ ))
+ self.wait(.5)
+
+ #uploaded by Somnath Pandit.FSF2020_Line_Integrals
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file5_helix.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file5_helix.py
new file mode 100644
index 0000000..50aeb33
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/file5_helix.py
@@ -0,0 +1,245 @@
+from manimlib.imports import *
+
+class ParametricCurve(ThreeDScene):
+
+ CONFIG = {
+ "axes_config": {
+ "x_min": 0,
+ "x_max": 3,
+ "y_min": 0,
+ "y_max": 3,
+ "z_min": 0,
+ "z_max": 4,
+ "a":0 ,"b": 2, "c":0 , "d":2,
+ "axes_shift":2*IN+1.4*RIGHT+1.4*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,
+ },
+ },
+
+ }
+
+
+ def construct(self):
+
+ self.setup_axes()
+
+ self.set_camera_orientation(
+ distance=25,
+ phi=60 * DEGREES,
+ theta=40 * DEGREES,
+ )
+
+ label=TextMobject("Helix",color=PURPLE).scale(1.6)
+ label.to_corner(UR,buff=2)
+ self.add_fixed_in_frame_mobjects(label)
+
+ helix=self.get_helix(
+ radius=1.5,
+ t_min= 0,
+ t_max= 4*PI,
+ color=PURPLE
+ )
+ parameter_label=TextMobject(
+ "Parametric equation: ",
+ color=TEAL
+ ).next_to(label,DOWN,buff=.3
+ )
+ parametric_eqn=TextMobject(
+ "$x=\cos$ (","t",
+ r")\\$y=\sin $(","t",
+ r")\\$z$=","t"
+ ).next_to(parameter_label,DOWN,buff=.1)
+ parametric_eqn.set_color_by_tex("t",RED)
+ self.parametric_eqn=parametric_eqn
+
+ parametriztion=VGroup(
+ parameter_label,
+ parametric_eqn
+ )
+
+
+ self.play(ShowCreation(helix),run_time=2)
+ self.begin_ambient_camera_rotation(.1)
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(parametriztion)
+ self.play(Write(parametriztion))
+ self.wait(1)
+ self.stop_ambient_camera_rotation()
+ self.move_camera(
+ distance=20,
+ phi=85 * DEGREES,
+ # theta=-90 * DEGREES,
+ run_time=3
+ )
+ scale_axes=VGroup(self.axes,helix).scale(1.2)
+ self.show_the_parameter()
+ self.wait(2)
+
+
+
+ def get_helix(self,radius=1, **kwargs):
+ config = {
+ "t_min": 0,
+ "t_max": 2*PI,
+ }
+ config.update(kwargs)
+ helix= ParametricFunction(
+ lambda t : self.axes.c2p(
+ radius*np.cos(t),
+ radius*np.sin(t),
+ t/4
+ ),
+ **config
+ )
+
+ self.helix=helix
+ return helix
+
+ def show_the_parameter(self):
+ t_tracker = ValueTracker(0)
+ t=t_tracker.get_value
+
+ t_label = TexMobject(
+ "t = ",color=RED
+ ).next_to(self.parametric_eqn,DL,buff=.85)
+
+ t_text = always_redraw(
+ lambda: DecimalNumber(
+ t(),
+ color=GOLD,
+ ).next_to(t_label, RIGHT, MED_SMALL_BUFF)
+ )
+ t_text.suspend_updating()
+
+ dot = Sphere(
+ radius= 1.5*DEFAULT_DOT_RADIUS,
+ stroke_width= 1,
+ fill_opacity= 1.0,
+ )
+ dot.set_color(GOLD)
+ dot.add_updater(lambda v: v.move_to(
+ self.helix.get_point_from_function(PI*t())
+ ))
+
+ pi = TexMobject(
+ "\\pi ",
+ color=GOLD,
+ ).next_to(t_text,RIGHT,buff=-.3)
+
+ group = VGroup(t_text,t_label,pi).scale(1.5)
+
+ self.wait(1)
+ self.add_fixed_in_frame_mobjects(group)
+ t_text.resume_updating()
+ self.play(FadeIn(group))
+ self.add(dot)
+ self.play(
+ t_tracker.set_value,2,
+ rate_func=linear,
+ run_time=5
+ )
+
+
+#--------------------------------------------------------
+
+ #customize 3D axes
+ def get_three_d_axes(self, include_labels=True, include_numbers=False, **kwargs):
+ config = dict(self.axes_config)
+ config.update(kwargs)
+ axes = ThreeDAxes(**config)
+ axes.set_stroke(width=1.5)
+
+ 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),
+ )
+
+
+ return axes
+
+
+ def setup_axes(self):
+ axes = self.get_three_d_axes(include_labels=True)
+ 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_Line_integrals
+
+
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file1_scalar_line_int_as_sum.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file1_scalar_line_int_as_sum.gif
new file mode 100644
index 0000000..17ea3f0
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file1_scalar_line_int_as_sum.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file2_scalar_line_integral.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file2_scalar_line_integral.gif
new file mode 100644
index 0000000..f9a8f98
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file2_scalar_line_integral.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file3_vector_line_int_as_sum.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file3_vector_line_int_as_sum.gif
new file mode 100644
index 0000000..46b35bc
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file3_vector_line_int_as_sum.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file4_vector_line_integral.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file4_vector_line_integral.gif
new file mode 100644
index 0000000..1be7e1e
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file4_vector_line_integral.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file5_helix.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file5_helix.gif
new file mode 100644
index 0000000..ceedb1f
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/line-integrals/gifs/file5_helix.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/README.md b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/README.md
new file mode 100644
index 0000000..d8c0956
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/README.md
@@ -0,0 +1,11 @@
+**file1_vector_fields**
+![file1_vector_fields](gifs/file1_vector_fields.gif)
+
+**file2_grad_of_scalar_function**
+![file2_grad_of_scalar_function](gifs/file2_grad_of_scalar_function.gif)
+
+**file3_constructing_vector_field**
+![file3_constructing_vector_field](gifs/file3_constructing_vector_field.gif)
+
+**file4_slope_field**
+![file4_slope_field](gifs/file4_slope_field.gif)
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file1_vector_fields.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file1_vector_fields.py
new file mode 100644
index 0000000..6b1b686
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file1_vector_fields.py
@@ -0,0 +1,350 @@
+from manimlib.imports import *
+
+class VectorFields(ThreeDScene):
+
+ CONFIG = {
+ "axes_config": {
+ "x_min": -4,
+ "x_max": 4,
+ "y_min": -4,
+ "y_max": 4,
+ "z_min": -3,
+ "z_max": 3,
+ "a":-4 ,"b": 4, "c":-4 , "d":4,
+ "axes_shift": ORIGIN+2*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": 10,
+ },
+ "default_graph_style": {
+ "stroke_width": 2,
+ "stroke_color": WHITE,
+ },
+ "default_vector_field_config": {
+ "delta_x": .5,
+ "delta_y": .5,
+ "x_min": -3,
+ "x_max": 3,
+ "y_min": -3,
+ "y_max": 3,
+ "min_magnitude": 0,
+ "max_magnitude": 4,
+ "colors": [BLUE,GREEN,ORANGE,RED],
+ "length_func": lambda norm : .45*sigmoid(norm),
+ "opacity": 1.0,
+ "vector_config": {
+ "stroke_width":3.5,
+ "max_tip_length_to_length_ratio": 0.35,
+ "max_stroke_width_to_length_ratio": 8,
+ },
+ },
+
+ }
+
+
+ def construct(self):
+
+ self.setup_axes()
+ axes=self.axes
+
+ self.set_camera_orientation(distance=35,
+ phi=0 * DEGREES,
+ theta=-90 * DEGREES,
+ )
+ self.move_camera(frame_center=axes.c2p(0,0,0))
+
+ self.show_2d_field()
+ self.wait(3)
+
+ self.show_3d_field()
+ self.begin_ambient_camera_rotation(rate=-.3,)
+ self.wait(1.5)
+ 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),
+ ),
+ self.move_camera(
+ # distance=20,
+ phi=85 * DEGREES,
+ rate_func=linear,
+ run_time=8
+ )
+ self.wait(5)
+
+
+ def show_2d_field(self):
+ d2_field_text=TexMobject(
+ r"\vec F(x,y)=-y\hat i+x\hat j",
+ stroke_width=1.5
+ ).set_color_by_gradient(
+ *self.default_vector_field_config["colors"]
+ )
+ d2_field_text.to_corner(UR,buff=.5)
+
+ d2_field = self.get_vector_field(
+ lambda v: np.array([
+ -v[1],
+ v[0],
+ 0
+ ]),
+ )
+ self.add_fixed_in_frame_mobjects(d2_field_text)
+ # self.add(d2_field)
+ self.play(Write(d2_field_text))
+ self.play(FadeIn(d2_field))
+
+ self.d2_field=d2_field
+ self.d2_field_text=d2_field_text
+
+ def show_3d_field(self):
+ d3_field_text=TexMobject(
+ r"\vec F(x,y,z)=-y\hat i+x\hat j+0 \hat k",
+ stroke_width=1.5
+ ).set_color_by_gradient(
+ *self.default_vector_field_config["colors"]
+ )
+ d3_field_text.to_corner(UR,buff=.5)
+
+ d3_field= self.get_vector_field(
+ lambda v: np.array([
+ -v[1],
+ v[0],
+ 0
+ # v[0]*v[2]
+ ]),
+ z_min=-2,
+ z_max= 2,
+ delta_x= 1,
+ delta_y= 1,
+ delta_z= 1,
+ length_func=lambda norm : .5*sigmoid(norm),
+ opacity= 1,
+ ThreeD=True
+ )
+
+ self.remove(self.d2_field,self.d2_field_text)
+ self.add_fixed_in_frame_mobjects(d3_field_text)
+ # self.add(d3_field)
+ self.play(Write(d3_field_text))
+ self.play(FadeIn(d3_field))
+
+ def get_vector_field(self,func,ThreeD=False,**kwargs):
+ config = dict()
+ config.update(self.default_vector_field_config)
+ config.update(kwargs)
+ if ThreeD:
+ vector_field= VectorField3D(func,**config)
+ else:
+ vector_field= VectorField(func,**config)
+
+ vector_field.move_to(self.axes.c2p(0,0,0))
+ self.vector_field=vector_field
+
+ return vector_field
+
+
+
+#-------------------------------------------------------
+ #customize 3D axes
+ def get_three_d_axes(self, include_labels=True, include_numbers=False, **kwargs):
+ config = dict(self.axes_config)
+ config.update(kwargs)
+ axes = ThreeDAxes(**config)
+ axes.set_stroke(width=2)
+ self.axes=axes
+
+ if include_numbers:
+ self.add_axes_numbers(axes)
+
+ if include_labels:
+ self.add_axes_labels(axes)
+
+ # Adjust axis orientation
+ axes.x_axis.rotate(
+ -0 * DEGREES, LEFT,
+ about_point=axes.c2p(0, 0, 0),
+ )
+ axes.y_axis.rotate(
+ 0 * DEGREES, UP,
+ about_point=axes.c2p(0, 0, 0),
+ )
+
+ return axes
+
+
+ def setup_axes(self):
+ axes = self.get_three_d_axes(include_labels=True)
+ 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, RIGHT)
+ 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
+
+#-----------------------------------------------------------
+
+class VectorField3D(VGroup):
+ CONFIG = {
+ "delta_x": 1,
+ "delta_y": 1,
+ "delta_z": 1,
+ "x_min": int(np.floor(-FRAME_WIDTH / 2)),
+ "x_max": int(np.ceil(FRAME_WIDTH / 2)),
+ "y_min": int(np.floor(-FRAME_HEIGHT / 2)),
+ "y_max": int(np.ceil(FRAME_HEIGHT / 2)),
+ "z_min":-1,
+ "z_max": 1,
+ "min_magnitude": 0,
+ "max_magnitude": 4,
+ "colors": DEFAULT_SCALAR_FIELD_COLORS,
+ # Takes in actual norm, spits out displayed norm
+ "length_func": lambda norm: 0.45 * sigmoid(norm),
+ "opacity": 1.0,
+ "vector_config": {},
+ }
+ '''Position of the tip of vector to be fixed'''
+ def __init__(self, func, **kwargs):
+ VGroup.__init__(self, **kwargs)
+ self.func = func
+ self.rgb_gradient_function = get_rgb_gradient_function(
+ self.min_magnitude,
+ self.max_magnitude,
+ self.colors,
+ flip_alphas=False
+ )
+ x_range = np.arange(
+ self.x_min,
+ self.x_max + self.delta_x,
+ self.delta_x
+ )
+ y_range = np.arange(
+ self.y_min,
+ self.y_max + self.delta_y,
+ self.delta_y
+ )
+ z_range = np.arange(
+ self.z_min,
+ self.z_max + self.delta_z,
+ self.delta_z
+ )
+ for x, y, z in it.product(x_range, y_range, z_range):
+ point = x * RIGHT + y * UP + z * OUT
+ # print(point)
+ self.add(self.get_vector(point))
+ self.set_opacity(self.opacity)
+
+ def get_vector(self, point, **kwargs):
+ output = np.array(self.func(point))
+ norm = get_norm(output)
+ if norm == 0:
+ output *= 0
+ else:
+ output *= self.length_func(norm) / norm
+ # norm=np.linalg.norm(output)
+ vector_config = dict(self.vector_config)
+ vector_config.update(kwargs)
+
+ vect = Vector(
+ output,
+ **vector_config
+ )
+ vect_perp=vect.copy().rotate(PI/2, axis=output)
+ vect= VGroup(vect,vect_perp)
+ # vect= self.position_vector(vect,point,output,norm)
+ vect.shift(point)
+ fill_color = rgb_to_color(
+ self.rgb_gradient_function(np.array([norm]))[0]
+ )
+ vect.set_color(fill_color)
+ return vect
+
+ '''def position_vector(self,vect,point,output,norm):
+ theta,phi=self.get_theta_phi(output,norm)
+ vect.rotate(PI-phi, axis=RIGHT)
+ vect.rotate(theta, axis=IN)
+ # or apply rotation matrix?
+ return vect
+
+ def get_theta_phi(self,output,norm):
+ if norm==0:
+ phi,theta=0,0
+ else:
+ phi= np.arccos(output[-1]/norm)
+ if output[0]!=0:
+ theta= np.arccos(output[0]/(norm*np.sin(phi)))
+ else:
+ theta= 0
+ return phi,theta'''
+
+
+
+ #uploaded by Somnath Pandit. FSF2020_Vector_fields
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file2_grad_of_scalar_function.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file2_grad_of_scalar_function.py
new file mode 100644
index 0000000..231b15c
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file2_grad_of_scalar_function.py
@@ -0,0 +1,320 @@
+from manimlib.imports import *
+
+class GradOfScalarFunc(ThreeDScene):
+
+ CONFIG = {
+ "axes_config": {
+ "x_min": -3,
+ "x_max": 3,
+ "y_min": -3,
+ "y_max": 3,
+ "z_min": 0,
+ "z_max": 3,
+ "a":-3 ,"b": 3, "c":-3 , "d":3,
+ "axes_shift": ORIGIN+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_vector_field_config": {
+ "delta_x": .5,
+ "delta_y": .5,
+ "x_min": -3,
+ "x_max": 3,
+ "y_min": -3,
+ "y_max": 3,
+ "min_magnitude": 0,
+ "max_magnitude": 2,
+ "colors": [BLUE,GREEN,GREEN,ORANGE,RED],
+ "length_func": lambda norm : .45*sigmoid(norm),
+ "opacity": 1.0,
+ "vector_config": {
+ "stroke_width":6
+ },
+ },
+ "default_surface_config": {
+ "fill_opacity": 0.5,
+ "checkerboard_colors": [BLUE_D],
+ "stroke_width": .5,
+ "stroke_color": WHITE,
+ "stroke_opacity": 0.2,
+ },
+ }
+
+
+ def construct(self):
+
+ self.setup_axes()
+ axes=self.axes
+
+ self.set_camera_orientation(distance=35,
+ phi=80 * DEGREES,
+ theta=-80 * DEGREES,
+ )
+
+ scalar_fn_text=TexMobject("f(x,y)=","\cos(xy)").set_color(BLUE)
+ scalar_fn_text.to_corner(UR,buff=.6)
+
+ operator=TexMobject("\\vec\\nabla").next_to(
+ scalar_fn_text,LEFT,buff=.2
+ ).set_color(GOLD)
+
+ grad_text=TexMobject(r"\dfrac{\partial f}{\partial x} \hat i+\dfrac{\partial f}{\partial y} \hat j+\dfrac{\partial f}{\partial z} \hat k").set_color(GOLD)
+ grad_text.next_to(scalar_fn_text,DOWN).scale(.9)
+
+ VGroup(
+ grad_text[0][1],
+ grad_text[0][9],
+ grad_text[0][17]
+ ).set_color(BLUE)
+ VGroup(
+ grad_text[0][5:8],
+ grad_text[0][13:16],
+ grad_text[0][21:23]
+ ).set_color(WHITE)
+
+ vector_field_text=TexMobject(
+ r"\vec F&=-y\sin(xy)\hat i\\ &-x\sin(xy)\hat j"
+ ).set_color_by_gradient(
+ *self.default_vector_field_config["colors"]
+ )
+ vector_field_text.next_to(scalar_fn_text,DOWN)
+
+
+ '''always generate the scalar field first'''
+ s_field=self.get_scalar_field(
+ func= lambda x ,y : np.cos(x*y/2),
+ dn=.25
+ )
+ v_field=self.get_vector_field(
+ lambda v: np.array([
+ -(v[1]-axes.c2p(0,0,0)[1])*np.sin((v[0]-axes.c2p(0,0,0)[0])*(v[1]-axes.c2p(0,0,0)[1])),
+ -(v[0]-axes.c2p(0,0,0)[0])*np.sin((v[0]-axes.c2p(0,0,0)[0])*(v[1]-axes.c2p(0,0,0)[1])),
+ 0,
+ ]),
+ on_surface=True,
+ )
+
+ self.add_fixed_in_frame_mobjects(scalar_fn_text)
+
+ self.begin_ambient_camera_rotation(rate=.2)
+ self.play(Write(s_field),run_time=2)
+ self.wait(4)
+ self.stop_ambient_camera_rotation()
+
+ self.add_fixed_in_frame_mobjects(operator)
+ self.play(Write(operator),FadeOut(scalar_fn_text[1]))
+ self.add_fixed_in_frame_mobjects(grad_text)
+ self.play(Write(grad_text))
+ self.wait(1.5)
+
+ self.play(FadeOut(grad_text))
+ self.add_fixed_in_frame_mobjects(vector_field_text)
+ show_vec_field=[
+ FadeIn(v_field),
+ Write(vector_field_text),
+ ]
+ # self.play(*show_vec_field,run_time=.5)
+ self.begin_ambient_camera_rotation(rate=.2)
+ self.move_camera(
+ # distance=20,
+ phi=50 * DEGREES,
+ added_anims=show_vec_field,
+ run_time=3
+ )
+
+ self.wait(5)
+ self.stop_ambient_camera_rotation()
+
+ fadeout= [FadeOut(s_field)]
+ # self.play(*fadeout)
+ self.move_camera(
+ # distance=20,
+ phi=0 * DEGREES,
+ theta=-90 * DEGREES,
+ added_anims=fadeout,
+ run_time=2
+ )
+ self.wait(2)
+
+
+
+
+
+ def get_scalar_field(self,func,dn=.5):
+ surface= self.get_surface(
+ lambda x , y:
+ func(x,y),
+ )
+
+ self.surface_points=self.get_points(func,dn)
+ return surface
+
+ def get_points(self,func,dn):
+ axes=self.axes
+
+ x_vals=np.arange(axes.a,axes.b,dn)
+ y_vals=np.arange(axes.c,axes.d,dn)
+ points=[]
+ for x_val in x_vals:
+ for y_val in y_vals:
+ points+=[axes.c2p(x_val,y_val,func(x_val,y_val)+.05)]
+ return points
+
+ def get_vector_field(self,func,on_surface=True,**kwargs):
+ config = dict()
+ config.update(self.default_vector_field_config)
+ config.update(kwargs)
+ vector_field= VectorField(func,**config)
+ vector_field.move_to(self.axes.c2p(0,0,0))
+ self.vector_field=vector_field
+
+ if on_surface:
+ vector_field=self.get_vectors_on_surface()
+
+ return vector_field
+
+
+
+ def get_vectors_on_surface(self):
+ vectors_on_surface = VGroup(*[
+ self.vector_field.get_vector(point)
+ for point in self.surface_points
+ ])
+
+ return vectors_on_surface
+
+
+ def get_surface(self, func, **kwargs):
+ axes=self.axes
+ config = {
+ "u_min": axes.a,
+ "u_max": axes.b,
+ "v_min": axes.c,
+ "v_max": axes.d,
+ "resolution": (
+ 4*(axes.y_max - axes.y_min) // axes.y_axis.tick_frequency,
+ 4*(axes.x_max - axes.x_min) // axes.x_axis.tick_frequency,
+ ),
+ }
+
+ config.update(self.default_surface_config)
+ config.update(kwargs)
+ return ParametricSurface(
+ lambda x,y : axes.c2p(
+ x, y, func(x, y)
+ ),
+ **config
+ )
+
+
+#-------------------------------------------------------
+ #customize 3D axes
+ def get_three_d_axes(self, include_labels=True, include_numbers=False, **kwargs):
+ config = dict(self.axes_config)
+ config.update(kwargs)
+ axes = ThreeDAxes(**config)
+ axes.set_stroke(width=2)
+ self.axes=axes
+
+ 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),
+ )
+
+ return axes
+
+
+ def setup_axes(self):
+ axes = self.get_three_d_axes(include_labels=True)
+ 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),
+ ("-1", axes.a),
+ ]
+ 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, RIGHT)
+ 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_Vector_fields
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file3_constructing_vector_field.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file3_constructing_vector_field.py
new file mode 100644
index 0000000..fc56306
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file3_constructing_vector_field.py
@@ -0,0 +1,196 @@
+from manimlib.imports import *
+
+
+class VectorFields(GraphScene):
+ CONFIG = {
+ "x_min" : -4,
+ "x_max" : 4,
+ "y_min" : -4,
+ "y_max" : 4,
+ "graph_origin": ORIGIN+2.5*LEFT,
+ "x_axis_width": 7,
+ "y_axis_height": 7,
+ "x_tick_frequency": 1,
+ "y_tick_frequency": 1,
+ "default_vector_field_config": {
+ "delta_x": .5,
+ "delta_y": .5,
+ "min_magnitude": 0,
+ "max_magnitude": 4,
+ "colors": [GREEN,GREEN,YELLOW,RED],
+ "length_func": lambda n: n/2.5,
+ "opacity": .75,
+ "vector_config": {
+ "stroke_width":6,
+ "max_stroke_width_to_length_ratio":4
+ },
+ },
+
+ "a":-3.5 ,"b": 4, "c": -3.5 ,"d": 4,
+ }
+
+ 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.X=X ;self.Y=Y
+
+ self.setup_axes(animate=False)
+ vector_function = lambda v: np.array([
+ (v[0]-self.graph_origin[0])*(v[1]-self.graph_origin[1]),
+ -(v[0]-self.graph_origin[0]),
+ 0,
+ ])
+
+ vector_field=self.get_vector_field(
+ vector_function,
+ colors= [GREEN]
+ )
+
+ self.show_points()
+ self.wait(.5)
+ self.show_func_machine()
+ self.wait(1)
+ self.produce_vectors(vector_field)
+ self.wait(.5)
+ self.scale_down_vectors(vector_function)
+ self.wait(2)
+
+
+
+ def show_points(self):
+ dn=1
+ x_vals=np.arange(self.a,self.b,dn)
+ y_vals=np.arange(self.c,self.d,dn)
+ dots=VGroup()
+ for x_val in x_vals:
+ for y_val in y_vals:
+ dot=Dot(
+ self.coords_to_point(x_val,y_val),
+ radius=.05,
+ color=TEAL,
+ )
+ dots.add(dot)
+ self.play(ShowCreation(dots, run_time=1))
+ self.dots=dots
+
+ def show_func_machine(self):
+ machine=RoundedRectangle(
+ height=2,
+ width=3.5,
+ color=PURPLE,
+ stroke_width=8
+ ).to_edge(RIGHT, buff=.4)
+
+ machine_label=TexMobject(
+ r"\vec F=xy\hat i-x\hat j",
+ stroke_width=1.5,
+ ).set_color_by_gradient(
+ *self.default_vector_field_config["colors"]
+ ).next_to(machine,IN)
+
+ machine=VGroup(machine,machine_label)
+ self.add(machine)
+
+ self.func_machine=machine
+
+
+ def produce_vectors(self,vector_field):
+ count,i=3,0
+ self.run_time=1
+ non_scaled_vectors=VGroup()
+ for dot in self.dots:
+ if i==count:
+ self.run_time=.05
+ position=dot.get_center()
+ vect= vector_field.get_vector(position)
+ self.go_to_machine(dot)
+ self.take_vec_from_machine(vect,position)
+ non_scaled_vectors.add(vect)
+ i+=1
+
+ self.non_scaled_vectors=non_scaled_vectors
+
+ def go_to_machine(self,dot):
+ if self.run_time>.5:
+ self.play(ApplyMethod(
+ dot.next_to,
+ self.func_machine,4*UP,
+ ),
+ run_time=self.run_time
+ )
+ self.dot=dot
+
+ def take_vec_from_machine(self,vect,position):
+ vect.next_to(self.func_machine,DOWN,buff=.1)
+
+ if self.run_time>.5:
+ point_coord=TexMobject(
+ "(x_i,y_i)"
+ ).next_to(self.dot,RIGHT,buff= .01).scale(.75)
+ input_point=VGroup(point_coord, self.dot)
+ self.play(
+ ApplyMethod(
+ input_point.shift,DOWN,
+ run_time=self.run_time
+ )),
+ self.play(
+ FadeOut(input_point),
+ run_time=.2
+ )
+ self.play(
+ FadeIn(vect),
+ run_time=.4
+ )
+ else:
+ self.remove(self.dot)
+ self.add(vect)
+ self.wait(1.0/15)
+
+ self.play(
+ vect.move_to,position,
+ run_time=self.run_time
+ )
+
+ def scale_down_vectors(self,vector_function):
+ scale_down_text=TextMobject(
+ r"Vectors are rescaled\\ for clarity\\ and \\",
+ r"colors are used to \\ indicate magnitudes",
+ stroke_width=1.2
+ )
+ scale_down_text[0][:7].set_color(BLUE)
+ scale_down_text[1].set_color_by_gradient(
+ *self.default_vector_field_config["colors"]
+ )
+ scale_down_text.to_corner(UR).shift(DOWN)
+ scaled_vector_field= self.get_vector_field(
+ vector_function,
+ length_func= lambda norm : .75*sigmoid(norm)
+ )
+ for vector in self.non_scaled_vectors:
+ scaled_vect= scaled_vector_field.get_vector(vector.get_center())
+ vector.target= scaled_vect
+
+ self.play(FadeOut(self.func_machine))
+ self.play(Write(scale_down_text))
+ self.wait(1.2)
+ self.play(LaggedStartMap(
+ MoveToTarget, self.non_scaled_vectors,
+ run_time=3
+ ))
+
+ def get_vector_field(self,func,**kwargs):
+ config = dict()
+ config.update(self.default_vector_field_config)
+ config.update(kwargs)
+ vector_field= VectorField(func,**config)
+
+ return vector_field
+
+
+
+
+
+#uploaded by Somnath Pandit. FSF2020_Vector_fields
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file4_slope_field.py b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file4_slope_field.py
new file mode 100644
index 0000000..8ebb6f5
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/file4_slope_field.py
@@ -0,0 +1,247 @@
+from manimlib.imports import *
+
+
+class SlopeFields(GraphScene):
+ CONFIG = {
+ "x_min" : -2,
+ "x_max" : 2,
+ "y_min" : -2,
+ "y_max" : 2,
+ "graph_origin": ORIGIN+2.5*LEFT,
+ "x_axis_width": 7,
+ "y_axis_height": 7,
+ "x_tick_frequency": 1,
+ "y_tick_frequency": 1,
+ "default_slope_field_config": {
+ "delta_x": .2,
+ "delta_y": .2,
+ "opacity": 1,
+ "color": BLUE_A,
+ "slope_length_factor": .2,
+ "line_config": {
+ "stroke_width":2.5,
+ },
+ },
+
+ "a":-1.9 ,"b": 2, "c": -1.9 ,"d": 2,
+ }
+
+ 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.X=X ;self.Y=Y
+
+ self.setup_axes(animate=False)
+
+ slope_field=self.get_slope_field(
+ lambda x,y:-2.0*(x-self.graph_origin[0])*(y-self.graph_origin[1]),
+ x_min=self.graph_origin[0]+self.a,
+ x_max=self.graph_origin[0]+self.b,
+ y_min=self.graph_origin[1]+self.c,
+ y_max=self.graph_origin[1]+self.d,
+ color= GREEN_B
+ )
+
+ self.show_points()
+ self.wait(.5)
+ self.show_func_machine()
+ self.wait(1)
+ self.produce_slopes(slope_field)
+ # self.add(slope_field)
+ self.glimpse_of_solutions()
+ self.wait(2)
+
+
+
+
+ def show_points(self):
+ dn=1.0/5
+ x_vals=np.arange(self.a,self.b,dn)
+ y_vals=np.arange(self.c,self.d,dn)
+ dots=VGroup()
+ for x_val in x_vals:
+ for y_val in y_vals:
+ dot=Dot(
+ self.coords_to_point(x_val,y_val),
+ radius=.04,
+ color=TEAL,
+ )
+ dots.add(dot)
+ self.play(ShowCreation(dots, run_time=1))
+ self.dots=dots
+
+ def show_func_machine(self):
+ machine=RoundedRectangle(
+ height=3,
+ width=4,
+ color=PURPLE,
+ stroke_width=8
+ ).to_edge(RIGHT, buff=.4)
+
+ machine_label=TextMobject(
+ r"Line segment\\ with slope\\"," $y'=-2xy$",
+ stroke_width=1.2,
+ color=BLUE
+ ).next_to(machine,IN)
+ machine_label[1].set_color(GREEN)
+ machine=VGroup(machine, machine_label)
+ self.play(FadeIn(machine))
+
+ self.func_machine = machine
+
+
+ def produce_slopes(self,slope_field):
+ count,i=3,0
+ self.run_time=1
+ for dot in self.dots:
+ if i==count:
+ self.run_time=.05
+ position=dot.get_center()
+ line= slope_field.get_slope(position)
+ self.go_to_machine(dot)
+ self.take_line_from_machine(line,position)
+ i+=1
+
+ def go_to_machine(self,dot):
+ if self.run_time>.5:
+ self.play(ApplyMethod(
+ dot.next_to,
+ self.func_machine,4*UP,
+ ),
+ run_time=self.run_time
+ )
+ self.dot=dot
+
+ def take_line_from_machine(self,vect,position):
+
+ if self.run_time>.5:
+ vect.next_to(self.func_machine,DOWN,buff=.1)
+ self.play(
+ ApplyMethod(
+ self.dot.shift,DOWN,
+ run_time=self.run_time
+ )),
+ self.play(
+ FadeOut(self.dot),
+ run_time=.2
+ )
+ self.play(
+ FadeIn(vect),
+ run_time=.4
+ )
+ self.play(
+ ApplyMethod(
+ vect.move_to,position
+ ),
+ run_time=self.run_time
+ )
+ else:
+ self.remove(self.dot)
+ self.add(vect)
+ vect.move_to(position)
+
+
+ def get_slope_field(self,func,**kwargs):
+ config = dict()
+ config.update(self.default_slope_field_config)
+ config.update(kwargs)
+ slope_field= SlopeField(func,**config)
+
+ return slope_field
+
+ def glimpse_of_solutions(self):
+ sol_text= TextMobject(
+ r"The solution curves\\ seem to be like...",
+ color= BLUE,
+ stroke_width=1.2
+ )
+ sol_text.to_corner(UR, buff=1)
+ condition_text= TextMobject(
+ r"for different\\ initial conditions",
+ color= GOLD,
+ stroke_width=1.1
+ )
+ condition_text.next_to(sol_text,DOWN,buff=1)
+ solution1 = self.get_graph(
+ lambda x : np.exp(-x**2),
+ x_min = self.a,
+ x_max = self.b,
+ color = PINK)
+ solution2 = self.get_graph(
+ lambda x : .5*np.exp(-x**2),
+ x_min = self.a,
+ x_max = self.b,
+ color = YELLOW)
+ solution3 = self.get_graph(
+ lambda x : 1.5*np.exp(-x**2),
+ x_min = self.a,
+ x_max = self.b,
+ color = BLUE)
+ solution4 = self.get_graph(
+ lambda x : -np.exp(-x**2),
+ x_min = self.a,
+ x_max = self.b,
+ color = RED_E)
+
+ self.play(FadeOut(self.func_machine))
+ self.play(Write(sol_text))
+ self.wait(.6)
+ self.play(ShowCreation(solution1))
+ self.play(Write(condition_text))
+ self.play(ShowCreation(solution2))
+ self.wait(.5)
+ self.play(ShowCreation(solution3))
+ self.wait(.5)
+ self.play(ShowCreation(solution4))
+
+
+class SlopeField(VGroup):
+ CONFIG = {
+ "delta_x": 0.5,
+ "delta_y": 0.5,
+ "x_min": int(np.floor(-FRAME_WIDTH / 2)),
+ "x_max": int(np.ceil(FRAME_WIDTH / 2)),
+ "y_min": int(np.floor(-FRAME_HEIGHT / 2)),
+ "y_max": int(np.ceil(FRAME_HEIGHT / 2)),
+ "opacity": 1.0,
+ "color": WHITE,
+ "slope_length_factor": .25,
+ "line_config": {},
+ }
+
+ def __init__(self, func, **kwargs):
+ VGroup.__init__(self, **kwargs)
+ self.func = func
+
+ x_range = np.arange(
+ self.x_min,
+ self.x_max + self.delta_x,
+ self.delta_x
+ )
+ y_range = np.arange(
+ self.y_min,
+ self.y_max + self.delta_y,
+ self.delta_y
+ )
+ for x, y in it.product(x_range, y_range):
+ point = x * RIGHT + y * UP
+ self.add(self.get_slope(point))
+ self.set_opacity(self.opacity)
+
+ def get_slope(self, point, **kwargs):
+ slope = self.func(*point[:2])
+ line_config = dict(self.line_config)
+ line_config.update(kwargs)
+ line = Line(ORIGIN,self.slope_length_factor*RIGHT, **line_config)
+ line.move_to(point).rotate(np.arctan(slope/3.2))
+
+ line.set_color(self.color)
+ return line
+
+
+
+
+#uploaded by Somnath Pandit. FSF2020_Vector_fields
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file1_vector_fields.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file1_vector_fields.gif
new file mode 100644
index 0000000..96e50ac
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file1_vector_fields.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file2_grad_of_scalar_function.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file2_grad_of_scalar_function.gif
new file mode 100644
index 0000000..c1ab66a
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file2_grad_of_scalar_function.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file3_constructing_vector_field.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file3_constructing_vector_field.gif
new file mode 100644
index 0000000..6a57cab
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file3_constructing_vector_field.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file4_slope_field.gif b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file4_slope_field.gif
new file mode 100644
index 0000000..c39ec54
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/vector-fields/gifs/file4_slope_field.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/README.md b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/README.md
new file mode 100644
index 0000000..17fcde0
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/README.md
@@ -0,0 +1,4 @@
+**file1_flux@_various_points.py**
+![file1_flux@_various_points](file1_flux@_various_points.gif)
+**file2_different_valuesof_Div.py**
+![file2_different_valuesof_Div](file2_different_valuesof_Div.gif)
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file1_flux@_various_points.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file1_flux@_various_points.gif
new file mode 100644
index 0000000..6c32b94
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file1_flux@_various_points.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file1_flux@_various_points.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file1_flux@_various_points.py
new file mode 100644
index 0000000..6727982
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file1_flux@_various_points.py
@@ -0,0 +1,60 @@
+from manimlib.imports import *
+def pendulum_vector_field_func(point):
+ #theta, omega = point[:2]
+ return np.array([
+ 5*point[0]+point[1],
+ 3*point[1]+3*point[1],
+ 0,
+ ])
+class SF(Scene):
+ CONFIG = {
+ #"func": cylinder_flow_vector_field,
+ "flow_time": 5,
+ }
+ def initialize_vector_field(self):
+ self.vector_field = VectorField(
+ pendulum_vector_field_func,
+ )
+ self.vector_field.sort(get_norm)
+ def construct(self):
+ # plane = NumberPlane(color=RED)
+ # plane.add(plane.get_axis_labels())
+ # self.add(plane)
+
+ A=TextMobject("The net flux through the green circular region is zero",tex_to_color_map={"green": GREEN})
+ B=TextMobject("The net flux through the blue circular region is non-zero",tex_to_color_map={"blue": BLUE})
+
+ c1=Circle(color=GREEN, radius=1.5)
+ c1.shift(4*LEFT+2.2*UP)
+ c2=Circle(color=BLUE, radius=1.5)
+
+
+
+
+ self.play(ShowCreation(A))
+ self.wait(0.5)
+ self.play(ApplyMethod(A.shift, (0.8*UP+0.2*LEFT)))
+ self.play(ShowCreation(B))
+ # self.play(ApplyMethod(B.shift, (2*UP)))
+ self.wait(2)
+ self.play(FadeOut(A),FadeOut(B))
+ self.initialize_vector_field()
+ field = self.vector_field
+ self.play(ShowCreation(field), run_time=4)
+ self.play(ShowCreation(c1))
+ self.play(ShowCreation(c2))
+ self.wait(1)
+ lines = StreamLines(
+ pendulum_vector_field_func,
+ virtual_time=3,
+ min_magnitude=0,
+ max_magnitude=2,
+ )
+ self.add(AnimatedStreamLines(
+ lines,
+ line_anim_class=ShowPassingFlash
+ ))
+ self.wait(2)
+ phase_point = VectorizedPoint(1*UP+1*RIGHT)
+ self.add(move_along_vector_field(phase_point, pendulum_vector_field_func))
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file2_different_valuesof_Div.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file2_different_valuesof_Div.gif
new file mode 100644
index 0000000..477c311
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file2_different_valuesof_Div.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file2_different_valuesof_Div.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file2_different_valuesof_Div.py
new file mode 100644
index 0000000..921047d
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/divergence-gauss-theorem/file2_different_valuesof_Div.py
@@ -0,0 +1,91 @@
+from manimlib.imports import *
+class Div(Scene):
+ def construct(self):
+ one=TextMobject(r"Div$ \vec{F} < 0$ ").set_color(RED)
+ two=TextMobject(r"Div$ \vec{F} = 0$ ").set_color(BLUE)
+ three=TextMobject(r"Div$ \vec{F} > 0$ ").set_color(YELLOW)
+
+ one.shift(2.3*DOWN)
+ two.shift(2.3*DOWN)
+ three.shift(2.3*DOWN)
+
+
+ a=Dot(color=RED)
+ a.shift(0.1*LEFT)
+ b=Dot(color=BLUE)
+ b.shift(0.1*LEFT)
+ c=Dot(color=YELLOW)
+ c.shift(0.1*LEFT)
+
+ rot=[0*DEGREES,45*DEGREES,90*DEGREES,135*DEGREES,180*DEGREES,225*DEGREES,270*DEGREES,315*DEGREES]
+ rot2=[180*DEGREES,180*DEGREES,180*DEGREES,180*DEGREES,180*DEGREES,180*DEGREES,180*DEGREES,180*DEGREES]
+ shift=[RIGHT,0.7*RIGHT+0.7*UP,UP,0.7*LEFT+0.7*UP,LEFT,0.7*LEFT+0.7*DOWN,DOWN,0.7*RIGHT+0.7*DOWN]
+ shift2=[RIGHT,RIGHT+UP,RIGHT+DOWN,UP,DOWN,LEFT,LEFT+UP,LEFT+DOWN]
+
+
+
+ u=[Vector(color=RED),Vector(color=RED),Vector(color=RED),Vector(color=RED),
+ Vector(color=RED),Vector(color=RED),Vector(color=RED),Vector(color=RED)]
+
+
+ [u[i].rotate(rot[i]) for i in range(8) ]
+ [u[i].rotate(rot2[i]) for i in range(8) ]
+ [u[i].shift(shift[i]) for i in range(8) ]
+
+
+ divone=VGroup(*u)
+ divone.shift(0.6*LEFT)
+
+
+ v=[Vector(color=BLUE),Vector(color=BLUE),Vector(color=BLUE),Vector(color=BLUE),
+ Vector(color=BLUE),Vector(color=BLUE),Vector(color=BLUE),Vector(color=BLUE)]
+
+
+ [v[i].rotate(45*DEGREES) for i in range(8)]
+ [v[i].shift(shift2[i]) for i in range(8) ]
+
+ divtwo=VGroup(*v)
+ divtwo.shift(0.6*LEFT)
+
+
+ w=[Vector(color=YELLOW),Vector(color=YELLOW),Vector(color=YELLOW),Vector(color=YELLOW),
+ Vector(color=YELLOW),Vector(color=YELLOW),Vector(color=YELLOW),Vector(color=YELLOW)]
+
+
+ [w[i].rotate(rot[i]) for i in range(8)]
+ [w[i].shift(shift[i]) for i in range(8) ]
+
+
+ divthree=VGroup(*w)
+ divthree.shift(0.6*LEFT)
+
+
+
+
+ self.play(ShowCreation(a),ShowCreation(divone))
+ self.play(ShowCreation(one))
+ self.wait(1)
+ self.play(FadeOut(a),FadeOut(divone),FadeOut(one))
+
+ self.play(ShowCreation(b),ShowCreation(divtwo))
+ self.play(ShowCreation(two))
+ self.wait(1)
+ self.play(FadeOut(b),FadeOut(divtwo),FadeOut(two))
+
+
+ self.play(ShowCreation(c),ShowCreation(divthree))
+ self.play(ShowCreation(three))
+ self.wait(1)
+ self.play(FadeOut(c),FadeOut(divthree),FadeOut(three))
+ self.wait(0.5)
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/README.md b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/README.md
new file mode 100644
index 0000000..97d6d10
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/README.md
@@ -0,0 +1,6 @@
+**file1_flux_through_circle.py**
+![file1_flux_through_circle](file1_flux_through_circle.gif)
+**file3_normal_vector.py**
+![file3_normal_vector](file3_normal_vector.gif)
+**file4_cube_surface.py**
+![file4_cube_surface](file4_cube_surface.gif)
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file1_flux_through_circle.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file1_flux_through_circle.gif
new file mode 100644
index 0000000..c00076b
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file1_flux_through_circle.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file1_flux_through_circle.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file1_flux_through_circle.py
new file mode 100644
index 0000000..e418a96
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file1_flux_through_circle.py
@@ -0,0 +1,43 @@
+from manimlib.imports import *
+def pendulum_vector_field_func(point):
+ #theta, omega = point[:2]
+ return np.array([
+ point[0],
+ point[1],
+ point[2],
+ ])
+class F2D(Scene):
+ CONFIG = {
+ # "func": cylinder_flow_vec or_field,
+ "flow_time": 5,
+ }
+ def initialize_vector_field(self):
+ self.vector_field = VectorField(
+ pendulum_vector_field_func,
+ )
+ self.vector_field.sort(get_norm)
+ def construct(self):
+ # plane = NumberPlane(color=RED)
+ # plane.add(plane.get_axis_labels())
+ # self.add(plane)
+ self.initialize_vector_field()
+
+ field = self.vector_field
+ c1=Circle(radius=3,color=BLUE)
+ self.play(ShowCreation(field), run_time=7)
+ self.play(ShowCreation(c1))
+ self.wait(3)
+ lines = StreamLines(
+ pendulum_vector_field_func,
+ virtual_time=3,
+ min_magnitude=0,
+ max_magnitude=2,
+ )
+ self.add(AnimatedStreamLines(
+ lines,
+ line_anim_class=ShowPassingFlash
+ ))
+ self.wait(2)
+ phase_point = VectorizedPoint(1*UP+1*RIGHT)
+ self.add(move_along_vector_field(phase_point, pendulum_vector_field_func))
+ self.wait(2)
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file3_normal_vector.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file3_normal_vector.gif
new file mode 100644
index 0000000..a8f2990
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file3_normal_vector.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file3_normal_vector.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file3_normal_vector.py
new file mode 100644
index 0000000..a959210
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file3_normal_vector.py
@@ -0,0 +1,47 @@
+from manimlib.imports import *
+class S(ThreeDScene):
+ def construct(self):
+ axes=ThreeDAxes()
+
+ sphere=Sphere(radius=2,checkerboard_colors=[BLUE_C,BLUE_B],fill_opacity=0.75)
+
+
+ v1=Vector(color=YELLOW,buff=5)
+ v1.rotate(PI/4,axis=DOWN)
+ v1.shift(1.5*RIGHT+1.5*OUT)
+
+ v2=Vector(color=RED,buff=5)
+ v2.rotate(PI/4,axis=DOWN)
+ v2.rotate(PI,axis=DOWN)
+ v2.shift(0.77*RIGHT+0.77*OUT)
+
+
+
+
+ n1=TextMobject(r"$\vec{n}$",color=YELLOW)
+ n2=TextMobject(r"$-\vec{n}$",color= RED)
+ n1.rotate(PI/2,axis=RIGHT)
+ n1.shift(2*RIGHT+2*OUT)
+ n2.rotate(PI/2,axis=RIGHT)
+ n2.shift(0.42*RIGHT+0.42*OUT)
+
+
+
+ self.set_camera_orientation(phi=75 * DEGREES,theta=-45*DEGREES)
+ # self.add(mobius)
+ # self.play(ShowCreation(axes))
+ self.play(ShowCreation(axes))
+ # self.play(ShowCreation(vg))
+ self.play(ShowCreation(sphere))
+ self.wait(0.7)
+ self.play(ShowCreation(v1, run_time=2))
+ self.play(ShowCreation(n1))
+ self.wait(1)
+ self.begin_ambient_camera_rotation(rate=0.65)
+ self.wait(2)
+ self.play(ShowCreation(v2, run_time=3))
+ self.wait(3)
+ self.play(ShowCreation(n2))
+
+ self.stop_ambient_camera_rotation()
+ self.wait(1.2)
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file4_cube_surface.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file4_cube_surface.gif
new file mode 100644
index 0000000..001edb8
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file4_cube_surface.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file4_cube_surface.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file4_cube_surface.py
new file mode 100644
index 0000000..146d955
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/flux/file4_cube_surface.py
@@ -0,0 +1,196 @@
+from manimlib.imports import*
+class cuber(ThreeDScene):
+ def construct(self):
+
+ axes=ThreeDAxes()
+ cube=Cube()
+ # cube.scale(1)
+ cube.shift(RIGHT+DOWN+OUT)
+
+
+
+ sq3=Square(color=RED, fill_opacity=0.85)
+ sq3.rotate(PI/2, axis=UP)
+ sq3.shift(DOWN+OUT+2*RIGHT)
+
+ x=TextMobject("x")
+ y=TextMobject("y")
+ z=TextMobject("z")
+
+ x.rotate(PI/2, axis=RIGHT)
+ x.rotate(PI/4,axis=OUT)
+ x.shift(5.8*DOWN)
+
+ y.rotate(PI/2, axis=RIGHT)
+ y.rotate(PI/8,axis=OUT)
+ y.shift(5.8*RIGHT)
+
+ z.rotate(PI/2, axis=RIGHT)
+ z.rotate(PI/5,axis=OUT)
+ z.shift(3.2*OUT+0.4*LEFT)
+ axis_label=VGroup(x,y,z)
+
+ v1=Vector(color=YELLOW,buff=15)
+ v1.rotate(PI/4,axis=RIGHT)
+ v1.shift(2*RIGHT+1*DOWN+1*OUT)
+
+
+ n1=TextMobject(r"$\vec{n}$",color=YELLOW)
+ n1.scale(0.8)
+ n1.rotate(PI/2,axis=RIGHT)
+ n1.rotate(PI,axis=OUT)
+ n1.shift(3*RIGHT+1.3*OUT+DOWN)
+
+ spaceloc = [[0,0,2],[1,0,2],[-1,0,2],[2,0,2],[-2,0,2],[3,0,2],[-3,0,2],
+ [0,1,2],[1,1,2],[-1,1,2],[2,1,2],[-2,1,2],[3,1,2],[-3,1,2],
+ [0,-1,2],[1,-1,2],[-1,-1,2],[2,-1,2],[-2,-1,2],[3,-1,2],[-3,-1,2],
+ [0,2,2],[1,2,2],[-1,2,2],[2,2,2],[-2,2,2],[3,2,2],[-3,2,2],
+ [0,-2,2],[1,-2,2],[-1,-2,2],[2,-2,2],[-2,-2,2],[3,-2,2],[-3,-2,2],
+ [0,3,2],[1,3,2],[-1,3,2],[2,3,2],[-2,3,2],[3,3,2],[-3,3,2],
+ [0,3,2],[1,3,2],[-1,3,2],[2,3,2],[-2,3,2],[3,3,2],[-3,3,2],
+ [0,4,2],[1,4,2],[-1,4,2],[2,4,2],[-2,4,2],[3,4,2],[-3,4,2],
+ [0,4,2],[1,4,2],[-1,4,2],[2,4,2],[-2,4,2],[3,4,2],[-3,4,2],
+ [0,5,2],[1,5,2],[-1,5,2],[2,5,2],[-2,5,2],[3,5,2],[-3,5,2],
+ [0,5,2],[1,5,2],[-1,5,2],[2,5,2],[-2,5,2],[3,5,2],[-3,5,2],
+ [0,6,2],[1,6,2],[-1,6,2],[2,6,2],[-2,6,2],[3,6,2],[-3,6,2],
+ [0,1.5,2],[1,1.5,2],[-1,1.5,2],[2,1.5,2],[-2,1.5,2],[3,1.5,2],[-3,1.5,2],
+ [0,3,2],[1,3,2],[-1,3,2],[2,3,2],[-2,3,2],[3,3,2],[-3,3,2]]
+
+
+ veclist1=[Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY)]
+
+
+
+
+
+ [veclist1[i].rotate(PI/4,axis=RIGHT) for i in range(42)]
+ [veclist1[i].rotate(PI/6,axis=OUT) for i in range(42)]
+ [veclist1[i].rotate(PI/8,axis=DOWN) for i in range(42)]
+ vectorfield1=VGroup(*veclist1)
+ [veclist1[i].shift(spaceloc[i]) for i in range(42)]
+
+
+
+
+ veclist2=[Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY)]
+
+
+
+
+
+ [veclist2[i].rotate(PI/4,axis=RIGHT) for i in range(42)]
+ [veclist2[i].rotate(PI/4,axis=RIGHT) for i in range(42)]
+ [veclist2[i].rotate(PI/6,axis=OUT) for i in range(42)]
+ [veclist2[i].rotate(PI/8,axis=DOWN) for i in range(42)]
+ vectorfield2=VGroup(*veclist2)
+ [veclist2[i].shift(spaceloc[i]) for i in range(42)]
+
+
+
+ veclist3=[Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY)]
+
+
+
+
+
+ [veclist3[i].rotate(PI/4,axis=RIGHT) for i in range(42)]
+ [veclist3[i].rotate(PI/4,axis=RIGHT) for i in range(42)]
+ [veclist3[i].rotate(PI/6,axis=OUT) for i in range(42)]
+ [veclist3[i].rotate(PI/8,axis=DOWN) for i in range(42)]
+ vectorfield3=VGroup(*veclist3)
+ [veclist3[i].shift(spaceloc[i]) for i in range(42)]
+
+
+
+
+ veclist4=[Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY)]
+
+
+
+
+
+ [veclist4[i].rotate(PI/4,axis=RIGHT) for i in range(42)]
+ [veclist4[i].rotate(PI/4,axis=RIGHT) for i in range(42)]
+ [veclist4[i].rotate(PI/6,axis=OUT) for i in range(42)]
+ [veclist4[i].rotate(PI/8,axis=DOWN) for i in range(42)]
+ vectorfield4=VGroup(*veclist4)
+ [veclist4[i].shift(spaceloc[i]) for i in range(42)]
+
+
+ vectorfield1.shift(1.5*DOWN)
+ vectorfield2.shift(IN+1.5*DOWN)
+ vectorfield3.shift(2*IN+1.5*DOWN)
+ vectorfield4.shift(3*IN+1.5*DOWN)
+
+
+ vectors=[vectorfield1,vectorfield2,vectorfield3,vectorfield4]
+ vectorfield=VGroup(*vectors)
+ vectorfield.scale(1.3)
+
+
+ fv=[Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),Vector(color=GREY),
+ Vector(color=GREY)
+ ]
+
+ spaceloc2 = [[1.5,0.5,0.5],[1.5,1,0.5],[1.5,1.5,0.5],
+ [1.5,0.5,1],[1.5,1,1],[1.5,1.5,1],
+ [1.5,0.5,1.5],[1.5,1,1.5],[1.5,1.5,1.5]
+ ]
+ [fv[i].rotate(PI/4,axis=RIGHT) for i in range(9)]
+ [fv[i].rotate(PI/6,axis=OUT) for i in range(9)]
+ [fv[i].rotate(PI/8,axis=DOWN) for i in range(9)]
+ [fv[i].shift(spaceloc2[i]) for i in range(9)]
+ fvfield=VGroup(*fv)
+ fvfield.shift(2*DOWN)
+ fvfield.scale(1.3)
+
+ flux=TextMobject("Flux through one side of the cube").set_color(GOLD)
+ flux.shift(3.5*UP+0.5*LEFT)
+
+
+ alll=[vectorfield1,vectorfield2,vectorfield3,vectorfield4,fvfield]
+ alllvectors=VGroup(*alll)
+
+
+
+ self.set_camera_orientation(phi=70 * DEGREES,theta=-75*DEGREES)
+ self.play(ShowCreation(axes),ShowCreation(axis_label))
+ self.begin_ambient_camera_rotation(rate=0.2)
+ self.play(ShowCreation(alllvectors))
+ # self.add(fvfield)
+
+ self.play(ShowCreation(cube, run_time=1))
+
+ self.wait(1)
+ self.play(ShowCreation(sq3))
+ self.wait(1)
+ self.play(FadeOut(cube))
+ self.play(FadeOut(vectorfield))
+ self.add_fixed_in_frame_mobjects(flux)
+ # self.play(ShowCreation(flux))
+ self.wait(1)
+ self.play(ShowCreation(v1),ShowCreation(n1))
+ self.wait(5)
+ self.stop_ambient_camera_rotation()
+ self.wait(1)
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/strokes-theorem/README.md b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/strokes-theorem/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/strokes-theorem/README.md
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/README.md b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/README.md
new file mode 100644
index 0000000..a1de8b5
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/README.md
@@ -0,0 +1,10 @@
+**file1_projection.py**
+![file1_projection](projection.gif)
+**file2_cube.py**
+![file2_cube](cube.gif)
+**file3_cube_sideC.py**
+![file3_cube_sideC](sideC.gif)
+**file4_pauseandponder.py**
+![file4_pauseandponder](pauseandponder.gif)
+**file5_surface.py**
+![file5_surface](file5_surface.gif)
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/cube.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/cube.gif
new file mode 100644
index 0000000..2035d7a
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/cube.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file1_projection.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file1_projection.py
new file mode 100644
index 0000000..2d6f067
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file1_projection.py
@@ -0,0 +1,89 @@
+from manimlib.imports import *
+
+class Surface(ThreeDScene):
+
+ def construct(self):
+ axes=ThreeDAxes()
+ x=TextMobject("X")
+ y=TextMobject("Y")
+ z=TextMobject("Z")
+
+ x.rotate(PI/2, axis=RIGHT)
+ x.rotate(PI/4,axis=OUT)
+ x.shift(5.8*DOWN)
+
+ y.rotate(PI/2, axis=RIGHT)
+ y.rotate(PI/8,axis=OUT)
+ y.shift(5.8*RIGHT)
+
+ z.rotate(PI/2, axis=RIGHT)
+ z.rotate(PI/5,axis=OUT)
+ z.shift(3.2*OUT+0.4*LEFT)
+ axis_label=VGroup(x,y,z)
+
+
+
+
+
+ para_hyp = ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ 2+u/4+np.sin(v)
+ ]),v_min=-3,v_max=-0.4,u_min=-1,u_max=1,
+ resolution=(15, 32)).scale(1)
+ para_hyp.scale(0.3)
+ para_hyp.shift(1.2*RIGHT + 0.2*OUT + 0.4*DOWN)
+ para_hyp.rotate(PI,axis=RIGHT)
+ para_hyp.scale(2.5)
+ # para_hyp.rotate(PI/3.2,axis=OUT)
+ para_hyp2= ParametricSurface(
+ lambda u, v: np.array([
+ u,
+ v,
+ 2+u/4+np.sin(v)
+ ]),v_min=-3,v_max=-0.4,u_min=-1,u_max=1,
+ resolution=(15, 32)).scale(1)
+ para_hyp2.scale(0.3)
+ para_hyp2.shift(1.2*RIGHT + 0.2*OUT + 0.4*DOWN)
+ para_hyp2.rotate(PI,axis=RIGHT)
+ para_hyp2.scale(2.5)
+
+ rec=Rectangle(height=2.11, width=1.58, color=RED, fill_opacity=0.66)
+ rec.shift(1.3*RIGHT + 2.295*DOWN)
+ # rec.scale(2.5)
+
+
+ l1=DashedLine(start=0.5*RIGHT+1.1*DOWN+1.55*OUT,end=0.5*RIGHT+1.1*DOWN)
+ l2=DashedLine(start=2.1*RIGHT+1.1*DOWN+1.25*OUT,end=2.1*RIGHT+1.1*DOWN)
+ l3=DashedLine(start=2.1*RIGHT+3.4*DOWN+1.6*OUT,end=2.1*RIGHT+3.4*DOWN)
+ l4=DashedLine(start=0.5*RIGHT+3.4*DOWN+2*OUT,end=0.5*RIGHT+3.4*DOWN)
+ l=VGroup(l1,l2,l3,l4)
+
+
+
+ s=TextMobject("S",tex_to_color_map={"S": YELLOW})
+ s.rotate(PI/4,axis=RIGHT)
+ s.rotate(PI/15,axis=OUT)
+ s.shift(RIGHT + 2*OUT + 1.5*DOWN)
+ d=TextMobject("D",tex_to_color_map={"D": YELLOW})
+ d.scale(0.85)
+ d.shift(1.26*RIGHT + 2.45*DOWN)
+
+
+
+
+
+ self.set_camera_orientation(phi=75 * DEGREES,theta=-60*DEGREES)
+ self.begin_ambient_camera_rotation(rate=-0.02)
+ self.play(ShowCreation(axes),ShowCreation(axis_label))
+ self.wait(1.3)
+ self.play(ShowCreation(para_hyp))
+ self.play(ShowCreation(s))
+ self.add(para_hyp2)
+ self.play(Transform(para_hyp,rec),run_time=2)
+ self.play(ShowCreation(d))
+
+ self.wait(3)
+
+
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file2_cube.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file2_cube.py
new file mode 100644
index 0000000..2a094c8
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file2_cube.py
@@ -0,0 +1,75 @@
+from manimlib.imports import*
+class cuber(ThreeDScene):
+
+ def construct(self):
+
+ axes=ThreeDAxes()
+ cube=Cube(color=RED)
+ # cube.scale(1)
+ cube.shift(RIGHT+DOWN+OUT)
+
+ sq1=Square(side_length=2,color=RED, fill_opacity=0.5)
+ sq1.shift(RIGHT+DOWN)
+ # sq1.scale(1.2)
+ sq2=Square(color=YELLOW, fill_opacity=0.5)
+ sq2.rotate(PI/2,axis=RIGHT)
+ sq2.shift(RIGHT+OUT)
+
+ sq3=Square(color=GREEN , fill_opacity=0.5)
+ sq3.rotate(PI/2, axis=UP)
+ sq3.shift(DOWN+OUT)
+
+ a=TextMobject("side A",tex_to_color_map={"side A": BLACK})
+ b=TextMobject("side B",tex_to_color_map={"side B": BLACK})
+ c=TextMobject("side C",tex_to_color_map={"side C": BLACK})
+ a.rotate(PI/2, axis=RIGHT)
+ a.shift(RIGHT+OUT+2*DOWN)
+ b.rotate(PI/2, axis=OUT)
+ b.rotate(PI/2, axis=UP)
+ b.shift(2*RIGHT+DOWN+OUT)
+ c.shift(RIGHT+DOWN+2*OUT)
+ c.rotate(PI/4, axis=OUT)
+
+
+ axes=ThreeDAxes()
+ x=TextMobject("X")
+ y=TextMobject("Y")
+ z=TextMobject("Z")
+
+ x.rotate(PI/2, axis=RIGHT)
+ x.rotate(PI/4,axis=OUT)
+ x.shift(5.8*DOWN)
+
+ y.rotate(PI/2, axis=RIGHT)
+ y.rotate(PI/8,axis=OUT)
+ y.shift(5.8*RIGHT)
+
+ z.rotate(PI/2, axis=RIGHT)
+ z.rotate(PI/5,axis=OUT)
+ z.shift(3.2*OUT+0.4*LEFT)
+ axis_label=VGroup(x,y,z)
+
+
+
+
+
+
+ self.set_camera_orientation(phi=75 * DEGREES,theta=-67*DEGREES)
+ self.play(ShowCreation(axes),ShowCreation(axis_label))
+ self.play(ShowCreation(cube))
+ self.begin_ambient_camera_rotation(rate=0.04)
+ self.wait(0.7)
+ self.play(ShowCreation(sq1))
+ self.play(ShowCreation(sq2))
+
+ self.play(ShowCreation(sq3))
+ self.wait(0.6)
+ self.play(ShowCreation(a))
+
+ self.play(ShowCreation(b))
+ self.move_camera(phi=60*DEGREES,run_time=1)
+ self.play(ShowCreation(c))
+ self.wait(1)
+ self.wait(2)
+
+
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file3_cube_sideC.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file3_cube_sideC.py
new file mode 100644
index 0000000..0e6fdaa
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file3_cube_sideC.py
@@ -0,0 +1,96 @@
+from manimlib.imports import*
+
+
+
+class cuber(ThreeDScene):
+
+ def construct(self):
+
+ axes=ThreeDAxes()
+ cube=Cube(color=RED)
+ # cube.scale(1)
+ cube.shift(RIGHT+DOWN+OUT)
+
+ sq1=Square(side_length=1.95,color=BLUE, fill_opacity=1)
+ sq1.shift(RIGHT+DOWN+2*OUT)
+ # sq1.scale(1.2)
+
+ sq12=Square(side_length=1.95,color=BLUE, fill_opacity=1)
+ sq12.shift(RIGHT+DOWN+2*OUT)
+
+ sq2=Square(side_length=1.95,color=RED, fill_opacity=0.6)
+ sq2.shift(RIGHT+DOWN)
+
+ sq2w=Square(side_length=1.95,color=WHITE, fill_opacity=0.9)
+ sq2w.shift(RIGHT+DOWN)
+
+
+ c=TextMobject("side C",tex_to_color_map={"side C": BLACK})
+
+ dxdy=TextMobject(r"$dxdy$",tex_to_color_map={r"$dxdy$": WHITE})
+ dxdy.scale(0.7)
+ dxdy.rotate(PI/2, axis=RIGHT)
+ dxdy.rotate(PI/7, axis=OUT)
+ dxdy.shift(0.85*RIGHT+0.65*DOWN)
+
+
+
+ c.shift(RIGHT+DOWN+2*OUT)
+ c.rotate(PI/4, axis=OUT)
+
+
+
+ x=TextMobject("X")
+ y=TextMobject("Y")
+ z=TextMobject("Z")
+
+ x.rotate(PI/2, axis=RIGHT)
+ x.rotate(PI/4,axis=OUT)
+ x.shift(5.8*DOWN)
+
+ y.rotate(PI/2, axis=RIGHT)
+ y.rotate(PI/8,axis=OUT)
+ y.shift(5.8*RIGHT)
+
+ z.rotate(PI/2, axis=RIGHT)
+ z.rotate(PI/5,axis=OUT)
+ z.shift(3.2*OUT+0.4*LEFT)
+ axis_label=VGroup(x,y,z)
+
+ v=Vector(color=YELLOW)
+ # v.scale(2)
+ v.rotate(PI/2,axis=DOWN)
+ v.shift(0.4*RIGHT+0.9*DOWN+2.5*OUT)
+
+
+
+
+
+
+ self.set_camera_orientation(phi=60 * DEGREES,theta=-67*DEGREES)
+ self.begin_ambient_camera_rotation(rate=0.008)
+ self.add(axes)
+ self.add(axis_label)
+
+ self.add(cube)
+ # self.move_camera(phi=150*DEGREES,theta=-45*DEGREES, run_time=3)
+ self.wait(1.2)
+ self.add(sq1)
+ self.add(sq12)
+ self.play(ShowCreation(c))
+ self.wait(0.7)
+ self.play(FadeOut(cube))
+ self.wait(0.7)
+ # self.move_camera(phi=75*DEGREES,run_time=2)
+ self.play(ShowCreation(v))
+ self.wait(1)
+ self.play(Transform(sq1,sq2))
+ self.wait(0.7)
+ self.play(ApplyMethod(sq2w.scale, 0.08))
+ self.play(ShowCreation(dxdy))
+ self.wait(2)
+
+
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file4_pauseandponder.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file4_pauseandponder.py
new file mode 100644
index 0000000..a8b5070
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file4_pauseandponder.py
@@ -0,0 +1,77 @@
+from manimlib.imports import *
+
+class Surface(ThreeDScene):
+ def construct(self):
+ axes=ThreeDAxes()
+ cylinder = ParametricSurface(
+ lambda u, v: np.array([
+ np.cos(TAU * v),
+ v,
+ u
+ ]),
+ resolution=(6, 32)).fade(0.5) #Resolution of the surfaces
+
+
+ x=TextMobject("X")
+ y=TextMobject("Y")
+ z=TextMobject("Z")
+
+ x.rotate(PI/2, axis=RIGHT)
+ x.rotate(PI/4,axis=OUT)
+ x.shift(5.8*DOWN)
+
+ y.rotate(PI/2, axis=RIGHT)
+ y.rotate(PI/8,axis=OUT)
+ y.shift(5.8*RIGHT)
+
+ z.rotate(PI/2, axis=RIGHT)
+ z.rotate(PI/5,axis=OUT)
+ z.shift(3.2*OUT+0.4*LEFT)
+ axis_label=VGroup(x,y,z)
+
+
+
+ cylinder.rotate(PI/2, axis=RIGHT)
+ cylinder.shift(2*RIGHT+OUT+DOWN)
+ cylinder.scale(1.5)
+
+ self.set_camera_orientation(phi=75 * DEGREES,theta=-85*DEGREES)
+ self.begin_ambient_camera_rotation(rate=0.1)
+ self.play(ShowCreation(axes),ShowCreation(axis_label))
+ self.play(ShowCreation(cylinder))
+ # self.wait(0.7)
+
+
+
+ self.wait(2)
+ self.stop_ambient_camera_rotation()
+ self.wait(0.7)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file5_surface.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file5_surface.gif
new file mode 100644
index 0000000..27dcac8
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file5_surface.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/surface.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file5_surface.py
index a794f46..3c2e145 100644
--- a/FSF-2020/calculus-of-several-variables/integrals-of-multivariable-functions/double-integrals/surface.py
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/file5_surface.py
@@ -1,6 +1,6 @@
from manimlib.imports import *
-class SurfacesAnimation(ThreeDScene):
+class Surf(ThreeDScene):
CONFIG = {
"axes_config": {
@@ -10,7 +10,7 @@ class SurfacesAnimation(ThreeDScene):
"y_max": 8,
"z_min": 0,
"z_max": 6,
- "a":1 ,"b": 6, "c":2 , "d":6,
+ "a":2 ,"b": 6, "c":1 , "d":6,
"axes_shift":-3*OUT + 5*LEFT,
"x_axis_config": {
"tick_frequency": 1,
@@ -49,11 +49,11 @@ class SurfacesAnimation(ThreeDScene):
theta=-80 * DEGREES,
)
- fn_text=TextMobject("$z=f(x,y)$").set_color(PINK)
+ fn_text=TextMobject("$S$").set_color(BLUE)
self.add_fixed_in_frame_mobjects(fn_text)
fn_text.to_edge(TOP,buff=MED_SMALL_BUFF)
- R=TextMobject("R").set_color(BLACK).scale(3)
+ R=TextMobject("D").set_color(BLACK).scale(3)
R.move_to(self.axes.input_plane,IN)
self.add(R)
@@ -64,26 +64,28 @@ class SurfacesAnimation(ThreeDScene):
)
surface.set_style(
fill_opacity=0.8,
- fill_color=PINK,
+ fill_color=YELLOW,
stroke_width=0.8,
stroke_color=WHITE,
)
- self.begin_ambient_camera_rotation(rate=0.07)
+ self.begin_ambient_camera_rotation(rate=0.05)
self.play(Write(surface))
# self.play(LaggedStart(ShowCreation(surface)))
self.get_lines()
# self.play(FadeIn(self.axes.input_plane))
- self.wait(3)
+ self.wait(2)
+ self.stop_ambient_camera_rotation()
+ self.wait(1)
def get_surface(self,axes, func, **kwargs):
config = {
- "u_min": axes.a,
- "u_max": axes.b,
- "v_min": axes.c,
- "v_max": axes.d,
+ "u_min": axes.c,
+ "u_max": axes.d,
+ "v_min": axes.a,
+ "v_max": axes.b,
"resolution": (
(axes.y_max - axes.y_min) // axes.y_axis.tick_frequency,
(axes.x_max - axes.x_min) // axes.x_axis.tick_frequency,
@@ -112,7 +114,7 @@ class SurfacesAnimation(ThreeDScene):
lines=VGroup()
for start , end in zip(surface_corners,
self.region_corners):
- lines.add(self.draw_lines(start,end,"RED"))
+ lines.add(self.draw_lines(start,end,"WHITE"))
for start , end in zip(labels,
self.region_corners):
@@ -153,7 +155,7 @@ class SurfacesAnimation(ThreeDScene):
# Add xy-plane
input_plane = self.get_surface(
- axes, lambda x, t: 0
+ axes, lambda x, t: 1e-5
)
input_plane.set_style(
fill_opacity=0.5,
@@ -214,23 +216,22 @@ class SurfacesAnimation(ThreeDScene):
return axes
def add_axes_labels(self, axes):
- x_label = TexMobject("x")
+ 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 = 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 = TextMobject("Z")
z_label.rotate(90 * DEGREES, RIGHT)
z_label.next_to(axes.z_axis.get_zenith(), RIGHT)
axes.z_axis.label = z_label
for axis in axes:
axis.add(axis.label)
return axes
+ ######Code_by_Somnath_Pandit_https://github.com/panditsomnath10016git#########
-
-#uploaded by Somnath Pandit.FSF2020_Double_Integral
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/pauseandponder.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/pauseandponder.gif
new file mode 100644
index 0000000..4308c60
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/pauseandponder.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/projection.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/projection.gif
new file mode 100644
index 0000000..c0ca611
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/projection.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/sideC.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/sideC.gif
new file mode 100644
index 0000000..17b72ff
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/surface-integrals/sideC.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/README.md b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/README.md
new file mode 100644
index 0000000..2166a79
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/README.md
@@ -0,0 +1,6 @@
+**file1_3D_crossproduct.py**
+![file1_3D_crossproduct](file1_3D_crossproduct.gif)
+**file2_cylindrical_coordinates.py**
+![file2_cylindrical_coordinates](file2_cylindrical_coordinates.gif)
+**file2_spherical_coordinates.py**
+![file2_spherical_coordinates](file2_spherical_coordinates.gif)
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file1_3D_crossproduct.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file1_3D_crossproduct.gif
new file mode 100644
index 0000000..9bde5a1
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file1_3D_crossproduct.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file1_3D_crossproduct.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file1_3D_crossproduct.py
new file mode 100644
index 0000000..6720e7e
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file1_3D_crossproduct.py
@@ -0,0 +1,120 @@
+from manimlib.imports import*
+
+
+
+class TripleBox(ThreeDScene):
+
+ def construct(self):
+
+ axes=ThreeDAxes()
+ cube=Cube(fill_color=RED,fill_opacity=0.5)
+ cube.scale(0.5)
+ cube.shift(0.5*RIGHT+0.5*DOWN+0.5*OUT)
+ cube.shift(2*RIGHT+2*DOWN+1*OUT)
+
+
+
+ x=TextMobject("x")
+ y=TextMobject("y")
+ z=TextMobject("z")
+
+ x.rotate(PI/2, axis=RIGHT)
+ x.rotate(PI/4,axis=OUT)
+ x.shift(5.8*DOWN)
+
+ y.rotate(PI/2, axis=RIGHT)
+ y.rotate(PI/8,axis=OUT)
+ y.shift(5.8*RIGHT)
+
+ z.rotate(PI/2, axis=RIGHT)
+ z.rotate(PI/5,axis=OUT)
+ z.shift(3.2*OUT+0.4*LEFT)
+ axis_label=VGroup(x,y,z)
+
+
+
+
+ a=TextMobject("a")
+ b=TextMobject("b")
+ c=TextMobject("c")
+ d=TextMobject("d")
+ e=TextMobject("e")
+ f=TextMobject("f")
+
+
+
+ a.rotate(PI/2, axis=RIGHT)
+ a.rotate(PI/2, axis=OUT)
+ a.shift(2*DOWN+0.3*OUT+0.3*LEFT)
+
+ b.rotate(PI/2, axis=RIGHT)
+ b.rotate(PI/2, axis=OUT)
+ b.shift(3*DOWN+0.3*OUT+0.3*LEFT)
+
+
+ c.rotate(PI/2, axis=RIGHT)
+ c.shift(2*RIGHT+0.3*OUT)
+
+ d.rotate(PI/2, axis=RIGHT)
+ d.shift(3*RIGHT+0.3*OUT)
+
+
+ e.rotate(PI/2, axis=RIGHT)
+ e.rotate(PI/4, axis=OUT)
+ e.shift(1*OUT+0.3*DOWN+0.2*LEFT)
+
+
+ f.rotate(PI/2, axis=RIGHT)
+ f.rotate(PI/4, axis=OUT)
+ f.shift(2*OUT+0.3*DOWN+0.2*LEFT)
+
+
+
+ rec1=Rectangle(height=1, width=8,color=RED, fill_color=RED_C, fill_opacity=0.40)
+ rec1.shift(2.5*DOWN+4*RIGHT)
+
+ rec2=Rectangle(height=1, width=14,color=RED, fill_color=RED_C, fill_opacity=0.40)
+ rec2.rotate(PI/2, axis=OUT)
+ rec2.shift(7*DOWN+2.5*RIGHT)
+
+
+ sq=Square(color=RED,fill_opacity=60,side_length=1)
+ sq.shift(2.5*RIGHT+2.5*DOWN)
+
+
+
+ self.set_camera_orientation(phi=70 * DEGREES,theta=-70*DEGREES)
+ self.play(ShowCreation(axes),ShowCreation(axis_label))
+ self.begin_ambient_camera_rotation(rate=0.04)
+ self.play(ShowCreation(a),ShowCreation(b))
+ self.wait(0.5)
+ self.play(ShowCreation(rec1))
+ self.play(ShowCreation(c),ShowCreation(d))
+ self.play(ShowCreation(rec2))
+ self.add(sq)
+ self.wait(0.5)
+
+ self.play(FadeOut(rec1),FadeOut(rec2))
+ self.wait(1)
+
+ self.play(ShowCreation(e),ShowCreation(f))
+ self.wait(0.5)
+ self.play(ApplyMethod(sq.shift, 1*OUT))
+ self.wait(0.5)
+ self.play(Transform(sq,cube))
+
+
+ self.wait(0.5)
+
+
+
+ self.wait(0.5)
+
+
+
+
+ self.wait(3)
+ self.stop_ambient_camera_rotation()
+ self.wait(1.5)
+
+
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_cylindrical_coordinates.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_cylindrical_coordinates.gif
new file mode 100644
index 0000000..e913750
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_cylindrical_coordinates.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_cylindrical_coordinates.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_cylindrical_coordinates.py
new file mode 100644
index 0000000..d441dc0
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_cylindrical_coordinates.py
@@ -0,0 +1,164 @@
+from manimlib.imports import*
+class Cy(ThreeDScene):
+
+ def construct(self):
+
+ axes=ThreeDAxes()
+ x=TextMobject("X")
+ y=TextMobject("Y")
+ z=TextMobject("Z")
+
+ x.rotate(PI/2, axis=RIGHT)
+ x.rotate(PI/4,axis=OUT)
+ x.shift(5.8*DOWN)
+
+ y.rotate(PI/2, axis=RIGHT)
+ y.rotate(PI/8,axis=OUT)
+ y.shift(5.8*RIGHT)
+
+ z.rotate(PI/2, axis=RIGHT)
+ z.rotate(PI/5,axis=OUT)
+ z.shift(3.2*OUT+0.4*LEFT)
+ axis_label=VGroup(x,y,z)
+
+
+
+
+
+
+
+ x1=TextMobject("$x_{1}$")
+ y1=TextMobject("$y_{1}$")
+ z1=TextMobject("$z_{1}$")
+
+
+
+
+ x1.rotate(PI/2, axis=RIGHT)
+ x1.rotate(PI/2, axis=OUT)
+ x1.shift(2*DOWN+0.3*OUT+0.3*LEFT)
+
+ y1.rotate(PI/2, axis=RIGHT)
+ y1.shift(2*RIGHT+0.3*OUT)
+
+ z1.rotate(PI/2, axis=RIGHT)
+ z1.rotate(PI/4, axis=OUT)
+ z1.shift(2*OUT+0.3*DOWN+0.2*LEFT)
+
+
+ d1=Dot(color=RED,radius=0.05)
+ d2=Dot(color=RED,radius=0.05)
+ d3=Dot(color=RED,radius=0.05)
+
+
+ d1.shift(2*DOWN)
+ d1.rotate(PI/2,axis=UP)
+
+ d2.rotate(PI/2, axis=RIGHT)
+ d2.shift(2*RIGHT)
+
+ d3.rotate(PI/2, axis=RIGHT)
+ d3.rotate(PI/4, axis=OUT)
+ d3.shift(2*OUT)
+
+
+
+ l1=DashedLine(color=RED)
+ l1.scale(5)
+ l1.shift(2*DOWN+5*RIGHT)
+
+ l2=DashedLine(color=RED)
+ l2.scale(5)
+ l2.rotate(PI/2, axis=IN)
+ l2.shift(2*RIGHT+5*DOWN)
+
+ l3=DashedLine(color=RED)
+ l3.scale(5)
+ l3.rotate(PI/4,axis=IN)
+ l3.shift(2*OUT+4*RIGHT+4*DOWN)
+
+ point=Sphere(radius=0.02, checkerboard_colors=[BLUE,BLUE])
+ point.shift(2*RIGHT+2*DOWN)
+
+ proj=Line()
+ proj.scale(1.414)
+ proj.rotate(PI/4,axis=IN)
+ proj.shift(1*RIGHT+1*DOWN)
+
+
+ projl=DashedLine()
+ projl.rotate(PI/2, axis=DOWN)
+ projl.shift(1*OUT+2*RIGHT+2*DOWN)
+
+ p=TextMobject("$P(x,y,z)$")
+ p.scale(0.6)
+ p.rotate(PI/2, axis=RIGHT)
+ p.rotate(PI/9, axis=OUT)
+ p.shift(2.9*RIGHT+2.5*DOWN+2.3*OUT)
+
+ rho=TextMobject(r"$\rho$",tex_to_color_map={r"$\rho$": YELLOW})
+ rho.rotate(PI/2, axis=RIGHT)
+ rho.shift(1.5*RIGHT+1.36*DOWN+0.2*OUT)
+
+
+
+
+ carrow=CurvedArrow(start_point=1*DOWN, end_point=0.5*RIGHT+0.5*DOWN)
+
+
+ phi=TextMobject(r"$\phi$",tex_to_color_map={"$\phi$": YELLOW})
+ phi.scale(0.93)
+ phi.rotate(PI/2, axis=RIGHT)
+ phi.shift(0.3*RIGHT+1.3*DOWN)
+
+
+
+
+
+
+
+
+
+
+ self.set_camera_orientation(phi=70 * DEGREES,theta=-15*DEGREES)
+ self.play(ShowCreation(axes),ShowCreation(axis_label))
+ self.begin_ambient_camera_rotation(rate=-0.1)
+
+ self.play(ShowCreation(x1),ShowCreation(d1))
+ self.wait(0.5)
+ self.play(ShowCreation(l1))
+ self.wait(1)
+ self.play(ShowCreation(y1),ShowCreation(d2))
+ self.wait(0.5)
+ self.play(ShowCreation(l2))
+ self.wait(1)
+ self.add(point)
+ self.wait(0.5)
+ self.play(FadeOut(l1),FadeOut(l2))
+ self.wait(0.5)
+ self.play(ShowCreation(proj))
+ self.wait(0.64)
+ self.stop_ambient_camera_rotation()
+ self.play(ShowCreation(rho))
+ self.wait(1)
+
+ self.play(ShowCreation(z1),ShowCreation(d3))
+ self.wait(0.5)
+ self.play(ShowCreation(l3))
+ self.wait(1)
+ self.play(ApplyMethod(point.shift, 2*OUT), ShowCreation(projl))
+ self.play(FadeOut(l3))
+ self.play(ShowCreation(p),FadeOut(projl))
+ self.wait(0.5)
+ # self.play(ShowCreation(vec))
+
+
+
+
+
+ self.wait(1)
+ self.play(ShowCreation(carrow),ShowCreation(phi))
+
+ self.wait(5)
+
+
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_spherical_coordinates.gif b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_spherical_coordinates.gif
new file mode 100644
index 0000000..6dc8b17
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_spherical_coordinates.gif
Binary files differ
diff --git a/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_spherical_coordinates.py b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_spherical_coordinates.py
new file mode 100644
index 0000000..7dcc81a
--- /dev/null
+++ b/FSF-2020/calculus-of-several-variables/triple-and-surface-integrals/triple-integrals/file2_spherical_coordinates.py
@@ -0,0 +1,159 @@
+from manimlib.imports import*
+class Sp(ThreeDScene):
+
+ def construct(self):
+
+ axes=ThreeDAxes()
+ x=TextMobject("X")
+ y=TextMobject("Y")
+ z=TextMobject("Z")
+
+ x.rotate(PI/2, axis=RIGHT)
+ x.rotate(PI/4,axis=OUT)
+ x.shift(5.8*DOWN)
+
+ y.rotate(PI/2, axis=RIGHT)
+ y.rotate(PI/8,axis=OUT)
+ y.shift(5.8*RIGHT)
+
+ z.rotate(PI/2, axis=RIGHT)
+ z.rotate(PI/5,axis=OUT)
+ z.shift(3.2*OUT+0.4*LEFT)
+ axis_label=VGroup(x,y,z)
+
+
+
+
+
+
+
+ x1=TextMobject("$x_{1}$")
+ y1=TextMobject("$y_{1}$")
+ z1=TextMobject("$z_{1}$")
+
+
+
+
+ x1.rotate(PI/2, axis=RIGHT)
+ x1.rotate(PI/2, axis=OUT)
+ x1.shift(2*DOWN+0.3*OUT+0.3*LEFT)
+
+ y1.rotate(PI/2, axis=RIGHT)
+ y1.shift(2*RIGHT+0.3*OUT)
+
+ z1.rotate(PI/2, axis=RIGHT)
+ z1.rotate(PI/4, axis=OUT)
+ z1.shift(2*OUT+0.3*DOWN+0.2*LEFT)
+
+
+ d1=Dot(color=RED,radius=0.05)
+ d2=Dot(color=RED,radius=0.05)
+ d3=Dot(color=RED,radius=0.05)
+
+
+ d1.shift(2*DOWN)
+ d1.rotate(PI/2,axis=UP)
+
+ d2.rotate(PI/2, axis=RIGHT)
+ d2.shift(2*RIGHT)
+
+ d3.rotate(PI/2, axis=RIGHT)
+ d3.rotate(PI/4, axis=OUT)
+ d3.shift(2*OUT)
+
+
+
+ l1=DashedLine(color=RED)
+ l1.scale(5)
+ l1.shift(2*DOWN+5*RIGHT)
+
+ l2=DashedLine(color=RED)
+ l2.scale(5)
+ l2.rotate(PI/2, axis=IN)
+ l2.shift(2*RIGHT+5*DOWN)
+
+ l3=DashedLine(color=RED)
+ l3.scale(5)
+ l3.rotate(PI/4,axis=IN)
+ l3.shift(2*OUT+4*RIGHT+4*DOWN)
+
+ point=Sphere(radius=0.02, checkerboard_colors=[RED,RED])
+
+
+ proj=DashedLine(color=RED_C)
+ proj.scale(1.414)
+ proj.rotate(PI/4,axis=IN)
+ proj.shift(1*RIGHT+1*DOWN)
+
+
+ projl=DashedLine()
+ projl.rotate(PI/2, axis=UP)
+ projl.shift(1*OUT+2*RIGHT+2*DOWN)
+
+ p=TextMobject("$P(x,y,z)$")
+ p.scale(0.6)
+ p.rotate(PI/2, axis=RIGHT)
+ p.rotate(PI/9, axis=OUT)
+ p.shift(2.65*RIGHT+2.5*DOWN+2.3*OUT)
+
+ rho=TextMobject(r"$\rho$",tex_to_color_map={r"$\rho$": YELLOW})
+ rho.rotate(PI/2, axis=RIGHT)
+ rho.shift(1.45*RIGHT+1.9*DOWN+1.94*OUT)
+
+
+
+
+
+ carrow=ArcBetweenPoints(start=1*DOWN, end=0.5*RIGHT+0.5*DOWN)
+ carrow2=ArcBetweenPoints(start=0.5*RIGHT+0.5*DOWN+0.5*OUT, end=0.4*OUT)
+ # carrow2.rotate(PI/2, axis=LEFT)
+ # carrow2.rotate(PI/2, axis=UP)
+
+ theta=TextMobject(r"$\theta$",tex_to_color_map={r"$\theta$": YELLOW})
+ theta.shift((0.75*OUT+0.2*RIGHT))
+ theta.rotate(PI/2,axis=RIGHT)
+ theta.scale(0.9)
+
+
+
+
+ phi=TextMobject(r"$\phi$",tex_to_color_map={"$\phi$": YELLOW})
+ phi.scale(0.93)
+ phi.rotate(PI/2, axis=RIGHT)
+ phi.shift(0.42*RIGHT+1.3*DOWN)
+
+
+
+
+
+
+
+
+
+
+ self.set_camera_orientation(phi=70 * DEGREES,theta=-85*DEGREES)
+ self.play(ShowCreation(axes),ShowCreation(axis_label))
+ self.begin_ambient_camera_rotation(rate=0.009)
+ self.wait(1)
+ self.add(point)
+ self.play(ApplyMethod(point.shift, 2*RIGHT+2*DOWN+2*OUT))
+ self.wait(0.5)
+ self.play(ShowCreation(p))
+ self.wait(0.5)
+ self.play(ShowCreation(vec),ShowCreation(rho))
+ self.wait(1.5)
+ self.play(ApplyMethod(point.shift,2*IN), ShowCreation(projl))
+ self.wait(1)
+ self.play(ShowCreation(proj))
+ self.wait(1.2)
+ self.play(ShowCreation(carrow))
+ self.wait(0.64)
+ self.play(ShowCreation(phi))
+ self.wait(1.3)
+ self.play(ShowCreation(carrow2))
+ self.wait(0.5)
+ self.play(ShowCreation(theta))
+ self.wait(3)
+
+
+
diff --git a/FSF-2020/calculus/intro-to-calculus/README.md b/FSF-2020/calculus/intro-to-calculus/README.md
index e69de29..a417361 100644
--- a/FSF-2020/calculus/intro-to-calculus/README.md
+++ b/FSF-2020/calculus/intro-to-calculus/README.md
@@ -0,0 +1,8 @@
+Contributor: Aryan Singh
+Subtopics covered
+ - When do limits exist?
+ - How Fast am I going?-An intro to derivatives
+ - Infinte sums in a nutshell(Riemann integrals)
+ - Fundamental Theorem of calculus
+ - Volume and surface area of Gabriel's Horn
+ - Infinite sequences and series
diff --git a/FSF-2020/calculus/intro-to-calculus/fundamental-theorem-of-calculus/README.md b/FSF-2020/calculus/intro-to-calculus/fundamental-theorem-of-calculus/README.md
new file mode 100644
index 0000000..c77d886
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/fundamental-theorem-of-calculus/README.md
@@ -0,0 +1,3 @@
+funda1
+![funda1](https://user-images.githubusercontent.com/61246381/87968966-e31b7780-cade-11ea-8b94-361460261a21.gif)
+
diff --git a/FSF-2020/calculus/intro-to-calculus/fundamental-theorem-of-calculus/fundamental1.py b/FSF-2020/calculus/intro-to-calculus/fundamental-theorem-of-calculus/fundamental1.py
new file mode 100644
index 0000000..fd40347
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/fundamental-theorem-of-calculus/fundamental1.py
@@ -0,0 +1,72 @@
+from manimlib.imports import *
+
+class funda1(GraphScene, MovingCameraScene):
+ def setup(self):
+ MovingCameraScene.setup(self)
+ GraphScene.setup(self)
+ CONFIG = {
+ "y_max": 5,
+ "x_max": 8,
+ "x_min": 0,
+ "y_min": 0,
+ "x_axis_width": 10,
+ "y_axis_height": 5,
+ "init_dx":0.5,
+ "x_axis_label":"$t$",
+ "y_axis_label":"$F(x)$",
+ "graph_origin": ORIGIN+2*DOWN+6*LEFT,
+ }
+ def construct(self):
+ self.setup_axes()
+ def func(x):
+ return 0.1*(x)*(x-3)*(x-7)+3
+
+ graph1 = self.get_graph(func, x_min = 0, x_max = 7)
+ graph2 = self.get_graph(func, x_min = 5, x_max = 6)
+ sqr = Square(side_length = 15.0).move_to(np.array([0.5,-1.5,0]))
+ line1 = self.get_vertical_line_to_graph(1,graph1,DashedLine, color = PINK)
+ line2 = self.get_vertical_line_to_graph(5,graph1,DashedLine, color = PINK)
+ line3 = self.get_vertical_line_to_graph(6,graph1,DashedLine, color = PINK)
+ line4 = self.get_vertical_line_to_graph(5.01,graph1,DashedLine, color = PINK)
+ t1 = TextMobject("a").next_to(line1, DOWN)
+ t2 = TextMobject("x").next_to(line2, DOWN)
+ t3 = TextMobject("x+h").next_to(line3, DOWN)
+ text1 = TexMobject(r"\int _{ a }^{ x+h }{ f(t)dt }").move_to(np.array([3,2,0])).scale(0.7)
+ text2 = TexMobject(r"\int _{ a }^{ x }{ f(t)dt }").move_to(np.array([1,2,0])).scale(0.7)
+ text3 = TexMobject(r"= \int _{ x }^{ x+h }{ f(t)dt }").move_to(np.array([3,2,0])).scale(0.7)
+ text4 = TexMobject(r"h \rightarrow 0").move_to(np.array([1,-1.5,0])).scale(0.8)
+ text5 = TexMobject(r"F^{ ' }\left( x \right)=\lim _{ h\rightarrow 0 }{ \frac { f(x).h }{ h } }").move_to(np.array([1,-1.5,0])).scale(0.2)
+ text6 = TexMobject(r"F^{ ' }\left( x \right)=f(x)").move_to(np.array([1,-1.5,0])).scale(0.2)
+ minus = TextMobject("-").move_to(np.array([0.2,2,0]))
+ group = VGroup(line1, line2, line3, t1, t2, t3)
+ brace1 = Brace(line2, LEFT).scale(0.35)
+ br1text = brace1.get_text(r"$f(x)$").next_to(brace1, 1.001*LEFT+1*RIGHT).scale(0.1)
+ brgrp = VGroup(brace1, br1text)
+ flat_rectangles1 = self.get_riemann_rectangles(self.get_graph(lambda x : 0),dx=self.init_dx,start_color=invert_color(PURPLE),end_color=invert_color(ORANGE))
+ riemann_rectangles_list3 = self.get_riemann_rectangles_list(graph1, 8, max_dx=self.init_dx, power_base=2, start_color = GREEN, end_color=GREEN, x_min =1, x_max = 6)
+ riemann_rectangles_list1 = self.get_riemann_rectangles_list(graph1,8,max_dx=self.init_dx,power_base=2,start_color=PURPLE,end_color=BLUE_A,x_min = 1, x_max = 5)
+ riemann_rectangles_list2 = self.get_riemann_rectangles_list(graph1,8,max_dx=self.init_dx,power_base=2,start_color=RED,end_color=RED,x_min = 5, x_max = 6)
+ riemann_rectangles_list4 = self.get_riemann_rectangles_list(graph1,8,max_dx=self.init_dx,power_base=2,start_color=RED,end_color=RED,x_min = 5, x_max = 5.01)
+
+ self.add(graph1)
+ self.play(ReplacementTransform(flat_rectangles1,riemann_rectangles_list3[7]), ShowCreation(text1))
+ self.wait(3)
+ self.play(ShowCreation(group))
+ self.wait(1)
+ self.play(ReplacementTransform(flat_rectangles1,riemann_rectangles_list2[7]), ReplacementTransform(flat_rectangles1,riemann_rectangles_list1[7]))
+ self.play(FadeOut(riemann_rectangles_list3[7]))
+ self.wait(2)
+ self.play(ApplyMethod(text1.shift, 4*LEFT), ShowCreation(minus), ShowCreation(text2), ShowCreation(text3))
+ self.play(FadeOut(riemann_rectangles_list1[7]))
+ self.wait(3)
+ self.camera_frame.save_state()
+ self.play(self.camera_frame.set_width,2.25,self.camera_frame.move_to,sqr,run_time = 2)
+ self.wait(2)
+ self.play(ReplacementTransform(riemann_rectangles_list2[7], riemann_rectangles_list4[7]), FadeOut(riemann_rectangles_list2[7]), ReplacementTransform(line3, line4), FadeOut(line3), ShowCreation(text4))
+ self.wait(2)
+ self.play(ShowCreation(brgrp))
+ self.wait(2)
+ self.play(ReplacementTransform(text4, text5))
+ self.wait(2)
+ self.play(ReplacementTransform(text5, text6))
+ self.wait(5) \ No newline at end of file
diff --git a/FSF-2020/calculus/intro-to-calculus/gabriels-horn/README.md b/FSF-2020/calculus/intro-to-calculus/gabriels-horn/README.md
new file mode 100644
index 0000000..ed548cb
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/gabriels-horn/README.md
@@ -0,0 +1,8 @@
+horn
+![horn](https://user-images.githubusercontent.com/61246381/87972654-e9145700-cae4-11ea-80d8-06fde63b2a41.gif)
+
+volume
+![volume](https://user-images.githubusercontent.com/61246381/87972967-722b8e00-cae5-11ea-86eb-99ef7acd21b3.gif)
+
+surface area
+![surface](https://user-images.githubusercontent.com/61246381/87970986-4064f800-cae2-11ea-89b0-632864285e4b.gif)
diff --git a/FSF-2020/calculus/intro-to-calculus/gabriels-horn/gabriel1.py b/FSF-2020/calculus/intro-to-calculus/gabriels-horn/gabriel1.py
new file mode 100644
index 0000000..16aeba9
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/gabriels-horn/gabriel1.py
@@ -0,0 +1,65 @@
+from manimlib.imports import *
+class sphere(GraphScene, ThreeDScene):
+ CONFIG = {
+ 'x_min': 0,
+ 'x_max': 10,
+ 'y_min': -3,
+ 'y_max': 3,
+ 'graph_origin': ORIGIN,
+ "x_axis_width": 10,
+ "y_axis_height": 10,
+ "default_graph_style": {
+ "stroke_width": 2,
+ "stroke_color": WHITE,
+ }
+ }
+ def construct(self):
+ XTD = self.x_axis_width/(self.x_max- self.x_min)
+ YTD = self.y_axis_height/(self.y_max- self.y_min)
+
+ text1 = TexMobject(r"y=\frac { 1 }{ x }").move_to(np.array([3,2,0]))
+ text1a = TexMobject(r"y=\frac { 1 }{ x }, x \ge 1").move_to(np.array([3,2,0]))
+ text2 = TexMobject(r"y=\frac { 1 }{ x }", r"\text{ is rotated in 3-dimensions}").to_corner(UL)
+ text3 = TextMobject("For calculating volume, consider a disc as shown").to_corner(UL)
+ text4 = TextMobject("Imagine the disc to move along the length of the horn").to_corner(UL)
+ text5 = TextMobject("In this way complete volume is covered").to_corner(UL)
+ arrow = Vector(np.array([0, np.sin(60*DEGREES), np.cos(60*DEGREES)])).shift(1*RIGHT)
+ text6 = TexMobject(r"\text{Area of circle is }", r"\pi {r}^{2}").to_corner(UL)
+ text7 = TextMobject("The disc moves along the length of hyperbolic curve").to_corner(UL)
+
+ axes = ThreeDAxes(**self.CONFIG)
+ self.setup_axes()
+ graph1 = self.get_graph(lambda x : 1/x, x_min = 1, x_max = 10)
+ graph2 = self.get_graph(lambda x : 1/x, x_min = 0.1, x_max = 10)
+ self.play(FadeIn(self.axes))
+ self.play(ShowCreation(graph2), FadeIn(text1))
+ self.wait(3)
+ self.play(Transform(graph2, graph1), ReplacementTransform(text1, text1a))
+ axes = ThreeDAxes(**self.CONFIG)
+ self.move_camera(phi = 90*DEGREES, theta=0*DEGREES,distance = 200, run_time=5)
+ horn2 = ParametricSurface(lambda u, v : np.array([1*u, (1*np.cos(TAU*v))/u,(1*np.sin(TAU*v))/u]), u_min = 1, v_min = 0.001, u_max = 10, fill_opacity = 0.1)
+ self.play(Transform(graph2, horn2), FadeOut(text1), FadeOut(graph2), ShowCreation(text2), FadeOut(text1a))
+ self.wait(2)
+ self.play(FadeOut(text2))
+ self.add_fixed_in_frame_mobjects(text3)
+ self.wait(1)
+ disc = ParametricSurface(lambda u, v : np.array([0, 1*v*np.sin(TAU*u), 1*v*np.cos(TAU*u)]), fill_opacity = 1, fill_color = PINK).shift(1*RIGHT)
+ self.play(ShowCreation(disc), ShowCreation(arrow))
+ self.play(FadeOut(text3))
+ self.add_fixed_in_frame_mobjects(text6)
+ self.wait(3)
+ self.play(FadeOut(text6))
+ self.add_fixed_in_frame_mobjects(text7)
+ self.wait(2)
+ self.move_camera(phi = 60*DEGREES, theta= -45*DEGREES, distance = 200, run_time=5)
+ k=0
+ while k<9:
+ disc1 = ParametricSurface(lambda u, v : np.array([0, (1/(1+k))*v*np.sin(TAU*u), (1/(1+k))*v*np.cos(TAU*u)]), fill_opacity = 0.5, fill_color = PINK).shift((1+k)*RIGHT)
+ self.play(FadeIn(disc1), run_time = 0.1)
+ k = k+0.1
+ self.play(FadeOut(text7))
+ self.add_fixed_in_frame_mobjects(text5)
+ self.wait(2)
+ self.begin_ambient_camera_rotation(rate = 0.4)
+ self.wait(10)
+ self.stop_ambient_camera_rotation() \ No newline at end of file
diff --git a/FSF-2020/calculus/intro-to-calculus/gabriels-horn/gabriel2.py b/FSF-2020/calculus/intro-to-calculus/gabriels-horn/gabriel2.py
new file mode 100644
index 0000000..1e2a820
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/gabriels-horn/gabriel2.py
@@ -0,0 +1,43 @@
+from manimlib.imports import *
+class surface(GraphScene, ThreeDScene):
+ CONFIG = {
+ 'x_min': 0,
+ 'x_max': 10,
+ 'y_min': -3,
+ 'y_max': 3,
+ 'graph_origin': ORIGIN,
+ "x_axis_width": 10,
+ "y_axis_height": 10,
+ "default_graph_style": {
+ "stroke_width": 2,
+ "stroke_color": RED,
+ }
+ }
+ def construct(self):
+ XTD = self.x_axis_width/(self.x_max- self.x_min)
+ YTD = self.y_axis_height/(self.y_max- self.y_min)
+
+ self.setup_axes()
+ text1 = TexMobject(r"y=\frac { 1 }{ x }").move_to(np.array([3,2,0]))
+ text2 = TexMobject(r"\int _{ 1 }^{ \infty }{ \frac { 1 }{ x } dx }", r"\text{ diverges}").to_corner(UL)
+ text3 = TexMobject(r"\text{Hence }", r"\int _{ 1 }^{ \infty }{ \frac { 1 }{ x } dx=\infty }").to_corner(UL)
+ text4 = TextMobject("Which means surface area is infinity").to_corner(UL)
+ graph1 = self.get_graph(lambda x : 1/x, x_min = 1, x_max = 10)
+ self.play(FadeIn(self.axes))
+ self.play(ShowCreation(graph1), FadeIn(text1))
+ self.wait(5)
+ axes = ThreeDAxes(**self.CONFIG)
+ self.move_camera(phi = 60*DEGREES, theta=45*DEGREES,distance = 200, run_time=5)
+ horn2 = ParametricSurface(lambda u, v : np.array([1*u, (1*np.cos(TAU*v))/u,(1*np.sin(TAU*v))/u]), u_min = 1, v_min = 0.001, u_max = 10, fill_opacity = 0.1)
+ horn3 = ParametricSurface(lambda u, v : np.array([1*u, (1*np.cos(TAU*v))/u,(1*np.sin(TAU*v))/u]), u_min = 1, v_min = 0.001, u_max = 10, fill_opacity = 1)
+ self.play(Transform(graph1, horn2))
+ self.play(FadeOut(text1))
+ self.add_fixed_in_frame_mobjects(text2)
+ self.wait(3)
+ self.play(FadeOut(text2))
+ self.add_fixed_in_frame_mobjects(text3)
+ self.wait(3)
+ self.play(ShowCreation(horn3))
+ self.play(FadeOut(text3))
+ self.add_fixed_in_frame_mobjects(text4)
+ self.wait(5) \ No newline at end of file
diff --git a/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/README.md b/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/README.md
new file mode 100644
index 0000000..1a735f9
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/README.md
@@ -0,0 +1,8 @@
+convergence
+![convergence](https://user-images.githubusercontent.com/61246381/87969916-9cc71800-cae0-11ea-8792-fd44b5823279.gif)
+
+divergence
+![divergence](https://user-images.githubusercontent.com/61246381/87970033-cbdd8980-cae0-11ea-9ba6-47f48898dab2.gif)
+
+taylor series
+![taylor](https://user-images.githubusercontent.com/61246381/87970112-e9125800-cae0-11ea-9a19-edcaaf91d7b6.gif)
diff --git a/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/convergence.py b/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/convergence.py
new file mode 100644
index 0000000..fcbcfb4
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/convergence.py
@@ -0,0 +1,57 @@
+from manimlib.imports import *
+def GetCenters(width,center,n):
+ d = width / 4
+ list = [center + [0,d,0]]
+ if n > 1:
+ list.append(center + [-d,-d,0])
+ if n > 2:
+ list.extend(GetCenters(width / 2, center + [d,-d,0],n-2))
+ return list
+END_CENTERS = [ORIGIN]
+END_CENTERS.extend(GetCenters(3, 3 * RIGHT, 24))
+color_list = ['#00931F','#A93226','#D68910','#17A589','#2471A3','#884EA0','#E74C3C','#D4AC0D']
+COLORS = [color_list[i % len(color_list)] for i in range(50)]
+class RectangleFromSequence(Rectangle):
+ CONFIG = {
+ "sequence_number": 0,
+ "center": ORIGIN
+ }
+ def __init__(self, **kwargs):
+ digest_config(self, kwargs)
+ Rectangle.__init__(self,height = 3 * (1/2) ** ((self.sequence_number + 1) // 2),width = 3 * (1/2) ** ((self.sequence_number) // 2),**kwargs)
+ if self.sequence_number < 6:
+ if self.sequence_number == 0:
+ label = TexMobject("1")
+ else:
+ label = TexMobject("1/",str(2 ** self.sequence_number))
+ label.scale(0.8 ** self.sequence_number)
+ self.add(label)
+ self.label = label
+ self.set_fill(COLORS[self.sequence_number],1)
+ self.set_stroke(width = 1)
+ self.move_to(self.center)
+equation = TexMobject("\\sum_{n=0}^\\infty \\frac{1}{2^n} =","1","+","\\frac{1}{2}","+","\\frac{1}{4}","+","\\frac{1}{8}","+","\\frac{1}{16}","+ \\ldots","= 2")
+class Proof1(Scene):
+ def construct(self):
+ equation.to_edge(UL)
+ self.play(Write(equation[0:-1]))
+ rects = VGroup(*[RectangleFromSequence(sequence_number = i)for i in range(25)])
+ rects.arrange(RIGHT, buff=0.5)
+ left_center = 5*LEFT
+ rects.shift(left_center-rects[0].get_center())
+ for rect in rects:
+ rect.shift(DOWN*rect.get_top()+UP*3 / 2)
+ for i in range(25):
+ rects[i].generate_target()
+ rects[i].target.move_to(left_center+END_CENTERS[i])
+ self.wait()
+ for i in range(5):
+ self.play(GrowFromPoint(rects[i] , equation[2*i+1].get_center()))
+ self.play(*[GrowFromPoint(rects[i] , equation[-2].get_center())for i in range(5,25)])
+ self.wait()
+ for i in range(1,8):
+ self.play(MoveToTarget(rects[i]))
+ self.play(*[MoveToTarget(rects[i]) for i in range(8,25)])
+ self.wait(0.5)
+ self.play(Write(equation[-1]))
+ self.wait(3) \ No newline at end of file
diff --git a/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/divergence.py b/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/divergence.py
new file mode 100644
index 0000000..4f4bf7c
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/divergence.py
@@ -0,0 +1,111 @@
+from manimlib.imports import *
+class divergence(GraphScene):
+ CONFIG = {
+ "y_max" : 2,
+ "y_min" : -2,
+ "x_max" : 20,
+ "x_min" : 0,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color" : WHITE,
+ "num_graph_anchor_points": 3000,
+ "graph_origin" : ORIGIN+6*LEFT,
+ "x_labeled_nums": None,
+ "y_labeled_nums": [-2,-1,1,2],
+ "x_axis_label":r"${(-1)}^{n}$",
+ "y_axis_label":"$Sum$",
+ "x_axis_width": 10,
+ "y_axis_height": 4,
+ }
+ def construct(self):
+ XTD = self.x_axis_width/(self.x_max - self.x_min)
+ YTD = self.y_axis_height/(self.y_max - self.y_min)
+ text1 = TextMobject("Consider the series 1-1+1-1+1-1+1-......")
+ self.add(text1)
+ self.wait(3)
+ self.play(FadeOut(text1))
+ self.setup_axes()
+ rangeo = (20)//self.x_axis_width
+ for i in range(0,2):
+ texta = TextMobject(str((-1)**i)).move_to(self.graph_origin+0.2*(rangeo*i)*RIGHT+0.5*DOWN+0.5*RIGHT)
+ self.add(texta)
+ for i in range(2,4):
+ texta = TextMobject(str((-1)**i)).move_to(self.graph_origin+0.2*(rangeo*i)*RIGHT+0.5*DOWN+0.65*RIGHT)
+ self.add(texta)
+ for i in range(4,6):
+ texta = TextMobject(str((-1)**i)).move_to(self.graph_origin+0.2*(rangeo*i)*RIGHT+0.5*DOWN+0.8*RIGHT)
+ self.add(texta)
+ for i in range(6,8):
+ texta = TextMobject(str((-1)**i)).move_to(self.graph_origin+0.2*(rangeo*i)*RIGHT+0.5*DOWN+0.95*RIGHT)
+ self.add(texta)
+ for i in range(8,10):
+ texta = TextMobject(str((-1)**i)).move_to(self.graph_origin+0.2*(rangeo*i)*RIGHT+0.5*DOWN+1.1*RIGHT)
+ self.add(texta)
+ for i in range(10,12):
+ texta = TextMobject(str((-1)**i)).move_to(self.graph_origin+0.2*(rangeo*i)*RIGHT+0.5*DOWN+1.35*RIGHT)
+ self.add(texta)
+ for i in range(12,14):
+ texta = TextMobject(str((-1)**i)).move_to(self.graph_origin+0.2*(rangeo*i)*RIGHT+0.5*DOWN+1.5*RIGHT)
+ self.add(texta)
+ for i in range(14,16):
+ texta = TextMobject(str((-1)**i)).move_to(self.graph_origin+0.2*(rangeo*i)*RIGHT+0.5*DOWN+1.65*RIGHT)
+ self.add(texta)
+ for i in range(16,18):
+ texta = TextMobject(str((-1)**i)).move_to(self.graph_origin+0.2*(rangeo*i)*RIGHT+0.5*DOWN+1.8*RIGHT)
+ self.add(texta)
+ for i in range(18,20):
+ texta = TextMobject(str((-1)**i)).move_to(self.graph_origin+0.2*(rangeo*i)*RIGHT+0.5*DOWN+1.95*RIGHT)
+ self.add(texta)
+
+ text2 = TextMobject("Number of purple lines denotes the number of terms added").move_to(1*UP).scale(0.8)
+ self.play(ShowCreation(text2))
+ self.wait(4)
+ self.play(FadeOut(text2))
+ for i in range(0,2):
+ horline = Line(np.array([-5.5+i,1,0]), np.array([-5+i,1,0]), color = PINK)
+ verline = DashedVMobject(Line(np.array([-5+i,1,0]), np.array([-5+i,0,0])))
+ botline = Line(np.array([-6+i,0,0]), np.array([-5.5+i,0,0]), color = PINK)
+ upline = DashedVMobject(Line(np.array([-5.5+i,0,0]), np.array([-5.5+i,1,0])))
+ self.play(ShowCreation(botline), run_time = 0.2)
+ self.play(ShowCreation(upline), run_time = 0.2)
+ self.play(ShowCreation(horline), run_time = 0.2)
+ self.play(ShowCreation(verline), run_time = 0.2)
+
+ text3 = TextMobject("For even number of terms, sum is 0").move_to(1*UP).scale(0.8)
+ self.play(FadeIn(text3))
+ self.wait(4)
+ self.play(FadeOut(text3))
+ for i in range(2,4):
+ horline = Line(np.array([-5.5+i,1,0]), np.array([-5+i,1,0]), color = PINK)
+ verline = DashedVMobject(Line(np.array([-5+i,1,0]), np.array([-5+i,0,0])))
+ botline = Line(np.array([-6+i,0,0]), np.array([-5.5+i,0,0]), color = PINK)
+ upline = DashedVMobject(Line(np.array([-5.5+i,0,0]), np.array([-5.5+i,1,0])))
+ self.play(ShowCreation(botline), run_time = 0.2)
+ self.play(ShowCreation(upline), run_time = 0.2)
+ self.play(ShowCreation(horline), run_time = 0.2)
+ self.play(ShowCreation(verline), run_time = 0.2)
+ botline = Line(np.array([-6+4,0,0]), np.array([-5.5+4,0,0]), color = PINK)
+ upline = DashedVMobject(Line(np.array([-5.5+4,0,0]), np.array([-5.5+4,1,0])))
+ self.play(ShowCreation(botline))
+ self.play(ShowCreation(upline))
+ text4 = TextMobject("For odd number of terms, sum is 1").move_to(1.5*UP).scale(0.8)
+ self.play(FadeIn(text4))
+ self.wait(3)
+ for i in range(4,10):
+ horline = Line(np.array([-5.5+i,1,0]), np.array([-5+i,1,0]), color = PINK)
+ verline = DashedVMobject(Line(np.array([-5+i,1,0]), np.array([-5+i,0,0])))
+ botline = Line(np.array([-6+i,0,0]), np.array([-5.5+i,0,0]), color = PINK)
+ upline = DashedVMobject(Line(np.array([-5.5+i,0,0]), np.array([-5.5+i,1,0])))
+ self.play(ShowCreation(botline), run_time = 0.2)
+ self.play(ShowCreation(upline), run_time = 0.2)
+ self.play(ShowCreation(horline), run_time = 0.2)
+ self.play(ShowCreation(verline), run_time = 0.2)
+ text5 = TextMobject("The sum is oscillating between 1 and 0").move_to(1.5*UP).scale(0.8)
+ self.play(ReplacementTransform(text4, text5))
+ self.wait(4)
+ text6 = TextMobject("It does not coerce to a particular finite value").move_to(1.5*UP).scale(0.8)
+ self.play(ReplacementTransform(text5, text6))
+ self.wait(4)
+ text7 = TextMobject("Hence it diverges").move_to(1.5*UP).scale(0.8)
+ self.play(ReplacementTransform(text6, text7))
+ self.wait(3) \ No newline at end of file
diff --git a/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/taylorseries.py b/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/taylorseries.py
new file mode 100644
index 0000000..2e9d423
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/infinite-seq-and-series/taylorseries.py
@@ -0,0 +1,67 @@
+from manimlib.imports import *
+class conv(GraphScene):
+ CONFIG = {
+ "y_max" : 10,
+ "y_min" : 0,
+ "x_max" : 5,
+ "x_min" : -1,
+ "y_tick_frequency" : 5,
+ "x_tick_frequency" : 1,
+ "axes_color" : WHITE,
+ "num_graph_anchor_points": 3000,
+ "graph_origin" : ORIGIN+2*DOWN+6*LEFT,
+ "x_labeled_nums": list(range(0,6)),
+ "y_labeled_nums": list(range(0,11))[::1],
+ "x_axis_label":"x",
+ "y_axis_label":"$f(x)$",
+ "x_axis_width": 9,
+ "y_axis_height": 5,
+ }
+ def construct(self):
+ XTD = self.x_axis_width/(self.x_max - self.x_min)
+ YTD = self.y_axis_height/(self.y_max - self.y_min)
+ texta = TexMobject(r"\text{Expressing }", r"{e}^{x}", r"\text{ as its Taylor series}")
+ self.play(FadeIn(texta))
+ self.wait(3)
+ self.play(FadeOut(texta))
+ self.setup_axes()
+ graph1 = self.get_graph(lambda x : (np.e)**x, x_min = -1, x_max = 5, color = PINK)
+ graph2 = self.get_graph(lambda x : 1+x, x_min = -1, x_max = 5, color = GREEN_SCREEN)
+ graph3 = self.get_graph(lambda x : 1+(x)+(x**2)/2, x_min = -1, x_max = 5, color = GREEN_SCREEN)
+ graph4 = self.get_graph(lambda x : 1+(x)+(x**2)/2+(x**3)/6, x_min = -1, x_max = 5, color = GREEN_SCREEN)
+ graph5 = self.get_graph(lambda x : 1+(x)+(x**2)/2+(x**3)/6+(x**4)/24, x_min = -1, x_max = 5, color = GREEN_SCREEN)
+ graph6 = self.get_graph(lambda x : 1+(x)+(x**2)/2+(x**3)/6+(x**4)/24+(x**5)/120, x_min = -1, x_max = 5, color = GREEN_SCREEN)
+ graph7 = self.get_graph(lambda x : 1+(x)+(x**2)/2+(x**3)/6+(x**4)/24+(x**5)/120+(x**6)/720, x_min = -1, x_max = 5, color = GREEN_SCREEN)
+ graph8 = self.get_graph(lambda x : 1+(x)+(x**2)/2+(x**3)/6+(x**4)/24+(x**5)/120+(x**6)/720+(x**7)/5040, x_min = -1, x_max = 5, color = GREEN_SCREEN)
+ texta = TexMobject(r"{e}^{x}").move_to(self.graph_origin+ 1*RIGHT+2*UP)
+ textb = TexMobject(r"\therefore {e}^{x}=").move_to(3.5*LEFT+0.5*DOWN)
+ text1 = TexMobject(r"1+x").move_to(4*RIGHT)
+ text2 = TexMobject(r"+\frac{{x}^{2}}{2!}").move_to(4*RIGHT)
+ text3 = TexMobject(r"+\frac{{x}^{3}}{3!}").move_to(4*RIGHT)
+ text4 = TexMobject(r"+\frac{{x}^{4}}{4!}").move_to(4*RIGHT)
+ text5 = TexMobject(r"+\frac{{x}^{5}}{5!}").move_to(4*RIGHT)
+ text6 = TexMobject(r"+\frac{{x}^{6}}{6!}").move_to(4*RIGHT)
+ text7 = TexMobject(r"+\frac{{x}^{7}}{7!}+...").move_to(4.5*RIGHT)
+
+ self.play(ShowCreation(texta))
+ self.play(ShowCreation(graph1))
+ self.wait(3)
+ self.play(FadeOut(texta))
+ self.play(ShowCreation(graph2))
+ self.play(ShowCreation(text1))
+ self.wait(3)
+ self.play(ReplacementTransform(graph2, graph3), ApplyMethod(text1.shift, 1*LEFT), ShowCreation(text2))
+ self.wait(3)
+ self.play(ReplacementTransform(graph3, graph4), ApplyMethod(text1.shift, 1*LEFT), ApplyMethod(text2.shift, 1*LEFT), ShowCreation(text3))
+ self.wait(3)
+ self.play(ReplacementTransform(graph4, graph5), ApplyMethod(text1.shift, 1*LEFT), ApplyMethod(text2.shift, 1*LEFT), ApplyMethod(text3.shift, 1*LEFT), ShowCreation(text4))
+ self.wait(3)
+ self.play(ReplacementTransform(graph5, graph6), ApplyMethod(text1.shift, 1*LEFT), ApplyMethod(text2.shift, 1*LEFT), ApplyMethod(text3.shift, 1*LEFT), ApplyMethod(text4.shift, 1*LEFT), ShowCreation(text5))
+ self.wait(3)
+ self.play(ReplacementTransform(graph6, graph7), ApplyMethod(text1.shift, 1*LEFT), ApplyMethod(text2.shift, 1*LEFT), ApplyMethod(text3.shift, 1*LEFT), ApplyMethod(text4.shift, 1*LEFT), ApplyMethod(text5.shift, 1*LEFT), ShowCreation(text6))
+ self.wait(3)
+ self.play(ReplacementTransform(graph7, graph8),ApplyMethod(text1.shift, 1*LEFT), ApplyMethod(text2.shift, 1*LEFT), ApplyMethod(text3.shift, 1*LEFT), ApplyMethod(text4.shift, 1*LEFT), ApplyMethod(text5.shift, 1*LEFT), ApplyMethod(text6.shift, 1*LEFT), ShowCreation(text7))
+ self.wait(3)
+ grp = VGroup(text1, text2, text3, text4, text5, text6, text7)
+ self.play(ApplyMethod(grp.shift, 0.5*DOWN), FadeIn(textb))
+ self.wait(5) \ No newline at end of file
diff --git a/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/README.md b/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/README.md
new file mode 100644
index 0000000..294f716
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/README.md
@@ -0,0 +1,8 @@
+derivative1
+![derivative1](https://user-images.githubusercontent.com/61246381/87973783-aeabb980-cae6-11ea-8b7a-e0dd089ebf09.gif)
+
+derivative2
+![derivative2](https://user-images.githubusercontent.com/61246381/87973861-c5eaa700-cae6-11ea-87e7-4915d68ab04f.gif)
+
+derivative3
+![derivative3](https://user-images.githubusercontent.com/61246381/87973900-d69b1d00-cae6-11ea-9459-c51564dbc35d.gif)
diff --git a/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative1.py b/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative1.py
new file mode 100644
index 0000000..79a6fc6
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative1.py
@@ -0,0 +1,55 @@
+from manimlib.imports import *
+class derivative1(GraphScene, Scene):
+ def setup(self):
+ GraphScene.setup(self)
+ CONFIG = {
+ "y_max" : 4,
+ "y_min" : -2,
+ "x_max" : 4,
+ "x_min" : -2,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color" : WHITE,
+ "num_graph_anchor_points": 3000, #this is the number of points that graph manim
+ "graph_origin" : ORIGIN+2*DOWN+4*LEFT,
+ "x_labeled_nums": list(range(-2,5)),
+ "y_labeled_nums": list(range(-2,5)),
+ "x_axis_label":"$x$",
+ "y_axis_label":r"$f(x)=y= 3-\frac { 3 }{ 2 } x$",
+ "x_axis_width": 5,
+ "y_axis_height": 5,
+ }
+ def construct(self):
+ #XTD = self.x_axis_width/(self.x_max - self.x_min)
+ #YTD = self.y_axis_height/(self.y_max - self.y_min)
+
+ text1 = TextMobject("")
+ text2 = TexMobject("{y}_{2}-{y}_{1}")
+ text2 = TexMobject("{x}_{2}-{x}_{1}")
+ text3 = TexMobject(r"m\quad =\frac { { y }_{ 2 }-{ y }_{ 1 } }{ { x }_{ 2 }-{ x }_{ 1 } }").move_to(np.array([3,0,0]))
+ text4 = TexMobject(r"m\quad =\frac { 3 }{ -2 }").move_to(np.array([3,0,0]))
+ text5 = TexMobject(r"m\quad =\quad -1.5").move_to(np.array([3,0,0]))
+ self.setup_axes()
+ graph_1 = self.get_graph(lambda x : 3-1.5*x, color = GREEN_SCREEN, x_min = -1, x_max = 3)
+ graph_2 = self.get_graph(lambda x : 3.1-1.5*x, color = ORANGE, x_min = 0, x_max = 2)
+ dot1 = Dot()
+ dot2 = SmallDot(self.graph_origin+1.7*RIGHT, color = PINK)
+ dot3 = SmallDot(self.graph_origin+2.5*UP, color = RED_B)
+ vec1 = Vector(2.5*DOWN, color = PINK).shift(self.graph_origin+2.5*UP)
+ vec2 = Vector(1.7*RIGHT, color = RED_B).shift(self.graph_origin)
+ brace1 = Brace(vec1, LEFT)
+ brace2 = Brace(vec2, DOWN)
+ br1text = brace1.get_text(r"${y}_{2}-{y}_{1}$").next_to(brace1, LEFT)
+ br2text = brace2.get_text(r"${x}_{2}-{x}_{1}$").next_to(brace2, DOWN)
+ self.play(ShowCreation(graph_1), ShowCreation(dot2), ShowCreation(dot3))
+ self.play(MoveAlongPath(dot1, graph_2), ShowCreation(vec1), ShowCreation(vec2), run_time = 3)
+ self.wait(1)
+ self.play(ShowCreation(brace1), ShowCreation(brace2))
+ self.play(ShowCreation(br1text), ShowCreation(br2text))
+ self.wait(2)
+ self.play(GrowFromCenter(text3))
+ self.wait(2.5)
+ self.play(ReplacementTransform(text3, text4))
+ self.wait(2)
+ self.play(ReplacementTransform(text4, text5))
+ self.wait(2)
diff --git a/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative2.py b/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative2.py
new file mode 100644
index 0000000..d6aab15
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative2.py
@@ -0,0 +1,78 @@
+from manimlib.imports import *
+class derivative2(GraphScene, MovingCameraScene):
+ def setup(self):
+ GraphScene.setup(self)
+ MovingCameraScene.setup(self)
+ CONFIG = {
+ "y_max" : 100,
+ "y_min" : 0,
+ "x_max" : 10,
+ "x_min" : 0,
+ "y_tick_frequency" : 100,
+ "x_tick_frequency" : 10,
+ "axes_color" : WHITE,
+ "num_graph_anchor_points": 3000, #this is the number of points that graph manim
+ "graph_origin" : ORIGIN,
+ "x_labeled_nums": None,#list(range(0,11)),
+ "y_labeled_nums": None,#list(range(0,101))[::10],
+ "x_axis_label":"$x$",
+ "y_axis_label":"$f(x)$",
+ "x_axis_width": 5,
+ "y_axis_height": 5,
+ "start_x" : 2,
+ "start_dx" : 6,
+ "df_color" : YELLOW,
+ "dx_color" : GREEN,
+ "secant_line_color" : MAROON_B,
+ "zoomed_camera_frame_starting_position": ORIGIN+2*DOWN+6*LEFT,
+ }
+ def construct(self):
+ self.setup()
+ self.camera_frame.save_state()
+ self.graph_origin = ORIGIN+2*DOWN+6*LEFT
+ self.setup_axes()
+ graph23 = self.get_graph(lambda x : x**2+7, color = GREEN_SCREEN, x_min = 0, x_max = 10)
+ graph24 = self.get_graph(lambda x : x**2+7, color = GREEN_SCREEN, x_min = 8, x_max = 2.01)
+ line_1 = DashedVMobject(Line(np.array([-5,-2,0]), np.array([-5,-1.42,0])))
+ textdef = TextMobject("")
+ text1 = TexMobject("{ x }_{ 0 }").move_to(np.array([-5,-2.2,0]))
+ text2 = TextMobject("The line becomes tangential to the curve").move_to(self.graph_origin+RIGHT+0.5*UP).scale(0.01)
+ text3 = TexMobject(r"\frac { df }{ dx } =\frac { f({ x }_{ 0 }+h)-f({ x }_{ 0 }) }{ h-0 }").move_to(2*RIGHT)
+ text4 = TexMobject(r"\frac { df }{ dx } =\lim _{ h\rightarrow 0 }{ \frac { f({ x }_{ 0 }+h)-f({ x }_{ 0 }) }{ h } }").move_to(2*RIGHT)
+ squareobj = Square(side_length = 15).move_to(self.graph_origin+RIGHT+0.53*UP)
+ ss_group = self.get_secant_slope_group(
+ self.start_x, graph23,
+ dx = self.start_dx,
+ dx_label = "h",
+ df_label = "df",
+ df_line_color = self.df_color,
+ dx_line_color = self.dx_color,
+ secant_line_color = self.secant_line_color,
+ dot_df_top = True,
+ dot_dx_start = True,
+ dot_df_top_label = "Q",
+ dot_dx_start_label = "P",
+ secant_line_length = 8
+ )
+ self.play(ShowCreation(graph23))
+ self.wait()
+ self.play(ShowCreation(ss_group.secant_line))
+ self.add(text1)
+ self.play(ShowCreation(line_1))
+ self.wait(3)
+ self.play(ShowCreation(ss_group.dx_line))
+ self.play(ShowCreation(ss_group.dx_label))
+ self.play(ShowCreation(ss_group.df_line))
+ self.play(Write(ss_group.df_label))
+ self.play(ShowCreation(ss_group.dot_df_top), ShowCreation(ss_group.dot_dx_start))
+ self.play(ShowCreation(ss_group.dot_df_top_label), ShowCreation(ss_group.dot_dx_start_label))
+ self.wait()
+ self.play(ShowCreation(text3))
+ self.wait(2)
+ self.play(ReplacementTransform(text3, text4))
+ self.animate_secant_slope_group_change(ss_group, target_dx = 0.01, run_time = 5)
+ self.wait(2)
+ self.play(self.camera_frame.set_width,0.2,self.camera_frame.move_to,squareobj,run_time = 2)
+ self.wait()
+ self.play(ShowCreation(text2))
+ self.wait(3)
diff --git a/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative3.py b/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative3.py
new file mode 100644
index 0000000..ebbacb1
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/intro-to-derivative/derivative3.py
@@ -0,0 +1,57 @@
+from manimlib.imports import *
+class derivative3(GraphScene, Scene):
+ def setup(self):
+ Scene.setup(self)
+ #ZoomedScene.setup(self)
+ CONFIG = {
+ "y_max" : 8,
+ "y_min" : 0,
+ "x_max" : 11,
+ "x_min" : 0,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color" : WHITE,
+ "num_graph_anchor_points": 3000, #this is the number of points that graph manim
+ "graph_origin" : ORIGIN+3*DOWN+6.5*LEFT,
+ "x_labeled_nums": list(range(0,12))[::1],
+ "y_labeled_nums": list(range(0,9))[::1],
+ "x_axis_label":"$t$",
+ "y_axis_label":"$s$",
+ "x_axis_width": 5,
+ "y_axis_height": 5,
+ }
+ def construct(self):
+ XTD = self.x_axis_width/(self.x_max - self.x_min)
+ YTD = self.y_axis_height/(self.y_max - self.y_min)
+
+ self.setup_axes()
+ graph_1 = self.get_graph(lambda x : -(x-2)**2+4, color = GOLD_A, x_min = 0, x_max = 1.5)
+ graph_2 = self.get_graph(lambda x : 1*x+2.25, color = GOLD_A, x_min = 1.5, x_max = 5)
+ graph_3 = self.get_graph(lambda x : 7.25, color = GOLD_A, x_min = 5, x_max = 8)
+ graph_4 = self.get_graph(lambda x : -3.625*x + 36.25, color = GOLD_A, x_min = 8, x_max = 10)
+
+ self.y_max = 5
+ self.x_max = 10
+ self.x_min = 0
+ self.y_min = -5
+ self.x_labeled_nums = list(range(0,11))
+ self.y_labeled_nums = list(range(-5,6))[::1]
+ self.x_axis_label = r"$t$"
+ self.y_axis_label = r"$v$"
+ self.y_tick_frequency = 1
+ self.x_tick_frequency = 1
+ self.graph_origin = ORIGIN+1*RIGHT
+ self.setup_axes()
+ graph_5 = self.get_graph(lambda x : 2*(x-2)+4, color = GREEN_SCREEN, x_min = 0, x_max = 1.5)
+ graph_6 = self.get_graph(lambda x : 3, color = GREEN_SCREEN, x_min = 1.5, x_max = 5)
+ graph_7 = self.get_graph(lambda x : 0, color = GREEN_SCREEN, x_min = 5, x_max = 8)
+ graph_8 = self.get_graph(lambda x : -3.625, color = GREEN_SCREEN, x_min = 8, x_max = 10)
+ line1 = DashedVMobject(Line(self.graph_origin+2.5*RIGHT, self.graph_origin+2.5*RIGHT+1.5*UP))
+ line2 = DashedVMobject(Line(self.graph_origin+4*RIGHT, self.graph_origin+4*RIGHT+1.835*DOWN))
+ self.play(ShowCreation(graph_1), ShowCreation(graph_5), run_time = 3)
+ self.play(ShowCreation(graph_2), ShowCreation(graph_6), run_time = 3)
+ self.add(line1)
+ self.play(ShowCreation(graph_3), ShowCreation(graph_7), run_time = 3)
+ self.add(line2)
+ self.play(ShowCreation(graph_4), ShowCreation(graph_8), run_time = 3)
+ self.wait(3)
diff --git a/FSF-2020/calculus/intro-to-calculus/limit/README.md b/FSF-2020/calculus/intro-to-calculus/limit/README.md
new file mode 100644
index 0000000..d56950e
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/limit/README.md
@@ -0,0 +1,18 @@
+Test1
+![Test1](https://user-images.githubusercontent.com/61246381/87964777-57065180-cad8-11ea-8938-8758481ea38f.gif)
+
+Test2
+![Test2](https://user-images.githubusercontent.com/61246381/87964839-6daca880-cad8-11ea-9b8e-9b60b3d162ae.gif)
+
+limit1
+![limit1](https://user-images.githubusercontent.com/61246381/87966913-9b472100-cadb-11ea-8d9b-ce469f8d1379.gif)
+
+limit3
+![limit3](https://user-images.githubusercontent.com/61246381/87967364-51ab0600-cadc-11ea-9e1e-fd89f6db8f9d.gif)
+
+limitfin1
+![limitfin1](https://user-images.githubusercontent.com/61246381/87964053-46091080-cad7-11ea-8bae-7affe799ffbf.gif)
+
+limitfin2
+![limitfin2](https://user-images.githubusercontent.com/61246381/87964169-7355be80-cad7-11ea-8682-2e8cdd403426.gif)
+
diff --git a/FSF-2020/calculus/intro-to-calculus/limit/Test1.py b/FSF-2020/calculus/intro-to-calculus/limit/Test1.py
new file mode 100644
index 0000000..bd7d2a6
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/limit/Test1.py
@@ -0,0 +1,34 @@
+from manimlib.imports import *
+class Test1(GraphScene):
+ CONFIG = {
+ "y_max" : 5,
+ "y_min" : -5,
+ "x_max" : 5,
+ "x_min" : -5,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color" : BLUE,
+ "num_graph_anchor_points": 3000, #this is the number of points that graph manim
+ "graph_origin" : ORIGIN,
+ "x_labeled_nums": list(range(-5,6)),
+ "y_labeled_nums": list(range(-5,6)),
+ "x_axis_label":"$x$",
+ "y_axis_label":"${ f }_{ 1 }(x)$"
+ }
+ def construct(self):
+ self.setup_axes()
+ cir1 = Circle(radius = 0.1, color = BLUE)
+ graph_1 = self.get_graph(lambda x : x+2,
+ color = GREEN,
+ x_min = -5, # Domain 1
+ x_max = +1.9
+ )
+ graph_2 =self.get_graph(lambda x : x+2,
+ color = GREEN,
+ x_min = 2.1, # Domain 2
+ x_max = 5
+ )
+ cir1.move_to(np.array([1,2,0]))
+ self.play(ShowCreation(graph_1))
+ self.play(ShowCreation(cir1))
+ self.play(ShowCreation(graph_2))
diff --git a/FSF-2020/calculus/intro-to-calculus/limit/Test2.py b/FSF-2020/calculus/intro-to-calculus/limit/Test2.py
new file mode 100644
index 0000000..0efb565
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/limit/Test2.py
@@ -0,0 +1,26 @@
+from manimlib.imports import *
+class Test2(GraphScene):
+ CONFIG = {
+ "y_max" : 5,
+ "y_min" : -5,
+ "x_max" : 5,
+ "x_min" : -5,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color" : BLUE,
+ "num_graph_anchor_points": 3000, #this is the number of points that graph manim
+ "graph_origin" : ORIGIN,
+ "x_labeled_nums": list(range(-5,6)),
+ "y_labeled_nums": list(range(-5,6)),
+ "x_axis_label":"$x$",
+ "y_axis_label":"${ f }_{ 1 }(x)$"
+ }
+ def construct(self):
+ self.setup_axes()
+ graph_1 = self.get_graph(lambda x : x+2,
+ color = GREEN,
+ x_min = -5, # Domain 1
+ x_max = +5
+ )
+ self.play(ShowCreation(graph_1))
+ self.wait()
diff --git a/FSF-2020/calculus/intro-to-calculus/limit/limit1.py b/FSF-2020/calculus/intro-to-calculus/limit/limit1.py
new file mode 100644
index 0000000..fe5cb1e
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/limit/limit1.py
@@ -0,0 +1,105 @@
+from manimlib.imports import *
+class limit1(GraphScene,MovingCameraScene):
+ def setup(self):
+ GraphScene.setup(self)
+ MovingCameraScene.setup(self)
+ CONFIG = {
+ "y_max" : 1,
+ "y_min" : 0,
+ "x_max" : 1,
+ "x_min" : -1,
+ "y_tick_frequency" : 0.2,
+ "x_tick_frequency" : 0.2,
+ "axes_color" : WHITE,
+ "num_graph_anchor_points": 3000, #this is the number of points that graph manim
+ "graph_origin" : ORIGIN+3*DOWN,
+ "x_labeled_nums": list(range(-1,2)),
+ "y_labeled_nums": list(range(0,2)),
+ "x_axis_label":"$x$",
+ "y_axis_label":"$f(x)$",
+ "x_axis_width": 10,
+ "y_axis_height": 5,
+ }
+ def construct(self):
+ XTD = self.x_axis_width/(self.x_max - self.x_min)
+ YTD = self.y_axis_height/(self.y_max - self.y_min)
+
+ dot1 = SmallDot(np.array([0.025,-2.975,0]))
+ dot2 = SmallDot(np.array([-0.025,-2.975,0]))
+ sqr = Square(side_length = 15.0).move_to(np.array([0,-3,0]))
+ brline1 = DashedVMobject(Line(np.array([0.15,-3,0]), np.array([0.15,-2.85,0])))
+ brline2 = DashedVMobject(Line(np.array([0.025,-3,0]), np.array([0.025,-2.975,0])))
+ brline3 = DashedVMobject(Line(np.array([-0.15,-3,0]), np.array([-0.15,-2.85,0])))
+ brline4 = DashedVMobject(Line(np.array([-0.025,-3,0]), np.array([-0.025,-2.975,0])))
+ textdef = TextMobject("")
+ text003 = TextMobject("0.03").move_to(np.array([0.15,-3.05,0])).scale(0.1)
+ textazero1 = TexMobject(r"\approx 0").move_to(np.array([0.04,-3.05,0])).scale(0.1)
+ textazero2 = TexMobject(r"\approx 0").move_to(np.array([-0.04,-3.05,0])).scale(0.1)
+ textm003 = TextMobject("-0.03").move_to(np.array([-0.15,-3.05,0])).scale(0.1)
+ text2 = TextMobject("Let f(x) = |x|. We'll check neighbourhood of origin")
+ text3 = TextMobject("h has to be a very small number greater than 0").move_to(np.array([0,-3.3,0])).scale(0.2)
+ text4 = TextMobject("The point travels through range of neighbourhood").move_to(np.array([0,-3.3,0])).scale(0.19)
+ text5 = TextMobject("let h be equal to 0.03").move_to(np.array([0,-3.3,0])).scale(0.25)
+ text6 = TextMobject("Notice how the point never touches the origin").move_to(np.array([0,-3.3,0])).scale(0.2)
+ text7 = TextMobject("Green line shows the Right hand neighbourhood of origin").move_to(np.array([0,-3.3,0])).scale(0.17)
+ text8 = TextMobject("The point is approaching (0,0) for the values of x which are positive").move_to(np.array([0,-3.3,0])).scale(0.1)
+ text9 = TextMobject("Values of x are tending to 0 from positive side").move_to(np.array([0,-3.3,0])).scale(0.19)
+ text10 = TexMobject(r"\text {Notation for this is }",r"x\rightarrow { 0 }^{ + }").move_to(np.array([0,-3.3,0])).scale(0.25)
+ text11 = TextMobject("Similar case can be made for negative values of x").move_to(np.array([0,-3.3,0])).scale(0.19)
+ text12 = TextMobject("The point is approaching (0,0) for the values of x which are negative").move_to(np.array([0,-3.3,0])).scale(0.1)
+ text13 = TextMobject("Values of x are tending to 0 from negative side").move_to(np.array([0,-3.3,0])).scale(0.19)
+ text14 = TexMobject(r"\text {Notation for this is }",r"x\rightarrow { 0 }^{ - }").move_to(np.array([0,-3.3,0])).scale(0.25)
+
+
+ self.play(FadeIn(text2), run_time = 1.5)
+ self.wait(2.5)
+ self.setup_axes()
+ graph_1 = self.get_graph(lambda x : x, color = RED, x_min = 0, x_max = 1)
+ graph_2 = self.get_graph(lambda x : -x, color = RED, x_min = 0, x_max = -1)
+ graph_3 = self.get_graph(lambda x : x,color = RED, x_min = 0.005, x_max = 0.03)
+ graph_4 = self.get_graph(lambda x : x,color = GREEN_SCREEN, x_min = 0.03, x_max = 0.005)
+ graph_5 = self.get_graph(lambda x : -x,color = GREEN_SCREEN, x_min = -0.03, x_max = -0.005)
+ grp1 = VGroup(graph_1,graph_2)
+ grp2 = VGroup(brline2, textazero1)
+ grp3 = VGroup(textazero2, textm003, brline3, brline4)
+ self.play(ShowCreation(grp1))
+ self.add(sqr)
+ self.play(ReplacementTransform(text2, text3))
+ self.camera_frame.save_state()
+ self.play(self.camera_frame.set_width,2.25,self.camera_frame.move_to,sqr,run_time = 2)
+ self.wait(2.5)
+ self.play(ReplacementTransform(text3, text4), ShowCreation(dot1))
+ self.wait(2.5)
+ self.play(ReplacementTransform(text4, text5), ShowCreation(brline1), ShowCreation(text003))
+ self.wait(2.5)
+ for i in range(0,3):
+ self.play(MoveAlongPath(dot1,graph_3), run_time = 0.5)
+ self.play(MoveAlongPath(dot1,graph_4), run_time = 0.5)
+ self.play(ReplacementTransform(text5, text6), ShowCreation(grp2))
+ self.wait(2)
+ self.play(FadeOut(dot1))
+ self.add(graph_4)
+ self.play(ReplacementTransform(text6, text7))
+ self.wait(2.5)
+ self.play(ReplacementTransform(text7,text8))
+ for i in range(0,3):
+ self.play(MoveAlongPath(dot1,graph_4), run_time = 0.7)
+ self.play(ReplacementTransform(text8, text9))
+ self.wait(2.5)
+ self.play(ReplacementTransform(text9, text10))
+ self.wait(2.5)
+ self.play(ShowCreation(grp3), ReplacementTransform(text10, text11), FadeOut(dot1))
+ self.add(graph_5)
+ for i in range(0,3):
+ self.play(MoveAlongPath(dot2, graph_5), run_time = 0.7)
+ self.play(ReplacementTransform(text11, text12))
+ self.wait(2.5)
+ self.play(ReplacementTransform(text12, text13))
+ self.wait(2.5)
+ self.play(ReplacementTransform(text13, text14))
+ self.wait(2)
+ self.play(FadeOut(dot2), ReplacementTransform(text14, textdef))
+ self.wait(2)
+ self.play(Restore(self.camera_frame))
+
+ self.wait(2.5)
diff --git a/FSF-2020/calculus/intro-to-calculus/limit/limit3.py b/FSF-2020/calculus/intro-to-calculus/limit/limit3.py
new file mode 100644
index 0000000..a4f07d7
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/limit/limit3.py
@@ -0,0 +1,95 @@
+from manimlib.imports import *
+class limit3(GraphScene, MovingCameraScene):
+ def setup(self):
+ GraphScene.setup(self)
+ MovingCameraScene.setup(self)
+ CONFIG = {
+ "y_max" : 10,
+ "y_min" : 0,
+ "x_max" : 100,
+ "x_min" : 0,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 10,
+ "axes_color" : WHITE,
+ "num_graph_anchor_points": 3000, #this is the number of points that graph manim
+ "graph_origin" : ORIGIN+3*DOWN+4*LEFT,
+ "x_labeled_nums": list(range(0,101))[::10],
+ "y_labeled_nums": list(range(0,11)),
+ "x_axis_label":"$x$",
+ "y_axis_label":"$f(x)$",
+ "x_axis_width": 10,
+ "y_axis_height": 5,
+ }
+ def construct(self):
+ XTD = self.x_axis_width/(self.x_max - self.x_min)
+ YTD = self.y_axis_height/(self.y_max - self.y_min)
+ sqr1 = Square(side_length = 15).move_to(np.array([1,0.5,0]))
+ sqr2 = Square(side_length = 15).move_to(np.array([-4,-3,0]))
+
+ textdef = TextMobject("")
+ text20 = TextMobject("f(x) is not defined at x=50").move_to(np.array([1,0.3,0])).scale(0.2)
+ text21 = TexMobject(r"\text {f(x) is not defined in interval }",r" (-\infty ,\quad 1]").move_to(np.array([-4,-3.2,0])).scale(0.18)
+ text22 = TextMobject("1").move_to(np.array([-3.9,-3.05,0])).scale(0.2)
+ text1 = TexMobject(r"\text {Let }" ,r"f\left( x \right) =\begin{cases} \sqrt { x-1 } ,x\in \quad (1,\infty )-50 \end{cases}")
+ text2 = TextMobject("Graph of f(x) is ")
+ text3 = TextMobject("Right hand neighbour of 50 will approximately be 50.000001").move_to(np.array([1,0.3,0])).scale(0.15)
+ text4 = TextMobject("Left hand neighbour of 50 will approximately be 49.999999").move_to(np.array([1,0.3,0])).scale(0.15)
+ text5 = TexMobject(r"\text {Hence R.H.L }", r"=\lim _{ x\rightarrow { 50 }^{ + } }{ \sqrt { 50.000001 - 1 } } \approx 7.000000071").move_to(np.array([1,0.3,0])).scale(0.13)
+ text6 = TexMobject(r"\text{Hence L.H.L }", r" = \lim _{ x\rightarrow { 50 }^{ - } }{ \sqrt { 49.999999-1 } }\approx 6.999999929").move_to(np.array([1,0.3,0])).scale(0.13)
+ text7 = TextMobject("7.000000071").move_to(np.array([1.9,0.25,0])).scale(0.1)
+ text8 = TextMobject("6.999999929").move_to(np.array([0.1,0.25,0])).scale(0.1)
+ text9 = TexMobject(r"6.999999929\quad \approx \quad 7.000000071 \quad \approx 7").move_to(np.array([1,0.25,0])).scale(0.2)
+ text10 = TexMobject(r"\text{Because LHL }" ,r"\approx" ,r"\text{ RHL, Limit exists at x=50 and equals 7").move_to(np.array([1,0.25,0])).scale(0.13)
+ text11 = TextMobject("There is no Left hand neighbour of x=1").move_to(np.array([-4,-3.2,0])).scale(0.22)
+ text12 = TexMobject(r"\therefore\quad \lim _{ x\rightarrow 0 }{ f(x) } \quad =\quad \lim _{ x\rightarrow { 0 }^{ + } }{ f(x) } ").move_to(np.array([-4,-3.2,0])).scale(0.25)
+ text13 = TexMobject(r"\text {R.H.L =}",r" \lim _{ x\rightarrow { 0 }^{ + } }{ \sqrt { 1.000000000001-1 } } \quad \approx 0").move_to(np.array([-4,-3.2,0])).scale(0.13)
+ text14 = TexMobject(r"\therefore \quad \lim _{ x\rightarrow 0 }{ f(x)\quad =\quad 0 }").move_to(np.array([-4,-3.2,0])).scale(0.13)
+ self.camera_frame.save_state()
+ self.play(ShowCreation(text1))
+ self.wait(3)
+ self.play(ReplacementTransform(text1, text2))
+ self.wait()
+ self.play(ReplacementTransform(text2, textdef))
+ self.setup_axes()
+ self.setup()
+ graph_1 = self.get_graph(lambda x : (x-1)**(1/2),color = PINK, x_min = 1, x_max = 49.9)
+ graph_2 = self.get_graph(lambda x : (x-1)**(1/2),color = PINK, x_min = 50.1, x_max = 100)
+ graph_3 = self.get_graph(lambda x : (x-1)**(1/2),color = PINK, x_min = 1.05, x_max = 1.001)
+ dot1 = SmallDot(color = PURPLE_A)
+ cir = Circle(radius = 0.01, color = GREEN_SCREEN).move_to(np.array([1,0.5,0]))
+ grp1 = VGroup(graph_1, graph_2, cir)
+ grp2 = VGroup(text7, text8)
+ self.play(ShowCreation(grp1))
+ self.wait(2)
+ self.play(self.camera_frame.set_width,2.25,self.camera_frame.move_to,sqr1,run_time = 2)
+ self.wait(1)
+ self.play(ShowCreation(text20))
+ self.wait(2)
+ self.play(ReplacementTransform(text20, text3))
+ self.wait(3)
+ self.play(ReplacementTransform(text3, text5))
+ self.wait(3)
+ self.play(ReplacementTransform(text5, text7), ShowCreation(text4))
+ self.wait(4)
+ self.play(ReplacementTransform(text4, text6))
+ self.wait(3)
+ self.play(ReplacementTransform(text6, text8))
+ self.wait(1.5)
+ self.play(ReplacementTransform(grp2, text9))
+ self.wait(1.5)
+ self.play(ReplacementTransform(text9, text10))
+ self.wait(3)
+ self.play(self.camera_frame.set_width,2.25,self.camera_frame.move_to,sqr2,run_time = 2)
+ self.play(ShowCreation(text21), ShowCreation(text22))
+ self.play(MoveAlongPath(dot1, graph_3), run_time = 3)
+ self.wait(3)
+ self.play(ReplacementTransform(text21, text11))
+ self.wait(3)
+ self.play(ReplacementTransform(text11, text12))
+ self.wait(3)
+ self.play(ReplacementTransform(text12, text13))
+ self.wait(2)
+ self.play(ReplacementTransform(text13, text14))
+ self.wait(3)
+ self.play(ReplacementTransform(text14, textdef))
+ self.wait(2)
diff --git a/FSF-2020/calculus/intro-to-calculus/limit/limitfin1.py b/FSF-2020/calculus/intro-to-calculus/limit/limitfin1.py
new file mode 100644
index 0000000..ba57a15
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/limit/limitfin1.py
@@ -0,0 +1,76 @@
+from manimlib.imports import *
+class limitfin1(GraphScene):
+ CONFIG = {
+ "x_min" : -8,
+ "x_max" : 8,
+ "x_labeled_nums" : list(range(-8, 10, 3)),
+ "x_axis_width" : FRAME_WIDTH - LARGE_BUFF,
+ "y_min" : -4,
+ "y_max" : 4,
+ "y_labeled_nums" : None,
+ "y_axis_height" : FRAME_HEIGHT+2*LARGE_BUFF,
+ "graph_origin" : DOWN,
+ "graph_color" : BLUE,
+ "x_axis_width":20,
+ "y_axis_height":10,
+ }
+ def construct(self):
+ self.setup_axes()
+ XTD = 10/(8 - (-8))
+ YTD = 10/(4 - (-4))
+ graph1 = self.get_graph(lambda x: x**3 +1.5, x_min = self.x_min, x_max = -0.1)
+ graph2 = self.get_graph(lambda x: x**3 +1.5, x_min = 0.1, x_max = self.x_max, color = self.graph_color)
+ dot2 = Circle(radius = 0.1).move_to(self.graph_origin+1.5*UP*YTD)
+ text0 = TextMobject("Let L be the value of f(x) at point denoted by circle").move_to(self.graph_origin+2*DOWN)
+ text1 = TexMobject(r"\text{As }", r"\delta",r"\text{ tends to zero }" ,r"\epsilon" r"\text{ tends to zero}").move_to(self.graph_origin+2*DOWN)
+ text2 = TexMobject(r"\text{For all values in }", r"(-\delta, +\delta)",r"\text{ you will always find a real and finite value of f(x) in }",r"(L-\epsilon, L+\epsilon)").move_to(self.graph_origin+2*DOWN).scale(0.6)
+ self.play(ShowCreation(graph1), ShowCreation(graph2), ShowCreation(text0), FadeIn(dot2))
+ line1 = DashedVMobject(Line(self.graph_origin+1*DOWN*YTD+1*LEFT*XTD, self.graph_origin+4*UP*YTD+1*LEFT*XTD), num_dashes = 50).set_color(PINK)
+ line2 = DashedVMobject(Line(self.graph_origin+1*DOWN*YTD+1*RIGHT*XTD, self.graph_origin+4*UP*YTD+1*RIGHT*XTD), num_dashes = 50).set_color(PINK)
+ line3 = DashedVMobject(Line(self.graph_origin+1.5*UP*YTD+5*LEFT*XTD, self.graph_origin+1.5*UP*YTD+4*RIGHT*XTD), num_dashes = 50).set_color(GOLD)
+ line4 = DashedVMobject(Line(self.graph_origin+0.5*UP*YTD+5*LEFT*XTD, self.graph_origin+0.5*UP*YTD+4*RIGHT*XTD), num_dashes = 50).set_color(GOLD)
+ line5 = DashedVMobject(Line(self.graph_origin+2.5*UP*YTD+5*LEFT*XTD, self.graph_origin+2.5*UP*YTD+4*RIGHT*XTD), num_dashes = 50).set_color(GOLD)
+ self.play(ShowCreation(line1), ShowCreation(line2))
+ vec1 = Line(self.graph_origin, self.graph_origin+1*RIGHT*XTD)
+ vec2 = Line(self.graph_origin, self.graph_origin+1*LEFT*XTD)
+ vec5 = Line(self.graph_origin+2.5*UP*YTD+4*RIGHT*XTD, self.graph_origin+1.5*UP*YTD+4*RIGHT*XTD)
+ vec6 = Line(self.graph_origin+0.5*UP*YTD+4*RIGHT*XTD, self.graph_origin+1.5*UP*YTD+4*RIGHT*XTD)
+ brace1 = Brace(vec1, DOWN)
+ brace2 = Brace(vec2, DOWN)
+ br1text = brace1.get_text(r"$\delta$").next_to(brace1, DOWN)
+ br2text = brace2.get_text(r"$\delta$").next_to(brace2, DOWN)
+ brace5 = Brace(vec5, RIGHT)
+ brace6 = Brace(vec6, RIGHT)
+ br5text = brace5.get_text(r"$\epsilon$").next_to(brace5, RIGHT)
+ br6text = brace6.get_text(r"$\epsilon$").next_to(brace6, RIGHT)
+ self.wait(3)
+ self.play(ShowCreation(brace1), ShowCreation(brace2), ShowCreation(br1text), ShowCreation(br2text))
+ self.wait(3)
+ self.play(ReplacementTransform(text0, text1))
+ self.play(ShowCreation(line3), ShowCreation(line4), ShowCreation(line5), ShowCreation(brace5), ShowCreation(brace6), ShowCreation(br5text), ShowCreation(br6text))
+ vec3 = Line(self.graph_origin, self.graph_origin+0.1*RIGHT*XTD)
+ vec4 = Line(self.graph_origin, self.graph_origin+0.11*LEFT*XTD)
+ brace3 = Brace(vec3, DOWN)
+ brace4 = Brace(vec4, DOWN)
+ vec7 = Line(self.graph_origin+1.6*UP*YTD+4*RIGHT*XTD, self.graph_origin+1.5*UP*YTD+4*RIGHT*XTD)
+ vec8 = Line(self.graph_origin+1.4*UP*YTD+4*RIGHT*XTD, self.graph_origin+1.5*UP*YTD+4*RIGHT*XTD)
+ brace7 = Brace(vec7, RIGHT)
+ brace8 = Brace(vec8, RIGHT)
+ self.play(Transform(brace1, brace3), Transform(brace2, brace4), ApplyMethod(line2.shift, 0.8*LEFT*XTD),
+ ApplyMethod(line1.shift, 0.8*RIGHT*XTD), ApplyMethod(br1text.scale, 0.3), ApplyMethod(br2text.scale, 0.3),
+ Transform(brace5, brace7), Transform(brace6, brace8), ApplyMethod(line4.shift, 1.8*UP*XTD),
+ ApplyMethod(line5.shift, 1.8*DOWN*XTD))
+ self.wait(3)
+ self.play(ReplacementTransform(text1, text2))
+ self.play(FadeOut(brace5), FadeOut(brace6), FadeOut(brace1), FadeOut(brace2))
+ self.play(ApplyMethod(line2.shift, 0.8*RIGHT*XTD), ApplyMethod(line1.shift, 0.8*LEFT*XTD), ApplyMethod(br1text.scale, 10/3), ApplyMethod(br2text.scale, 10/3),
+ ApplyMethod(line5.shift, 1.8*UP*XTD), ApplyMethod(line4.shift, 1.8*DOWN*XTD))
+ for i in range(0,3):
+ self.play(ApplyMethod(line2.shift, 0.8*LEFT*XTD), ApplyMethod(line1.shift, 0.8*RIGHT*XTD), ApplyMethod(br1text.scale, 0.3), ApplyMethod(br2text.scale, 0.3),
+ ApplyMethod(line5.shift, 1.8*DOWN*XTD), ApplyMethod(line4.shift, 1.8*UP*XTD), ApplyMethod(br5text.scale, 0.3), ApplyMethod(br6text.scale, 0.3), run_time = 0.5)
+ self.play(ApplyMethod(line2.shift, 0.8*RIGHT*XTD), ApplyMethod(line1.shift, 0.8*LEFT*XTD), ApplyMethod(br1text.scale, 10/3), ApplyMethod(br2text.scale, 10/3),
+ ApplyMethod(line5.shift, 1.8*UP*XTD), ApplyMethod(line4.shift, 1.8*DOWN*XTD), ApplyMethod(br5text.scale, 10/3), ApplyMethod(br6text.scale ,10/3), run_time = 0.5)
+ self.play(ApplyMethod(line2.shift, 0.8*LEFT*XTD), ApplyMethod(line1.shift, 0.8*RIGHT*XTD), ApplyMethod(br1text.scale, 0.3), ApplyMethod(br2text.scale, 0.3),
+ ApplyMethod(line5.shift, 1.8*DOWN*XTD), ApplyMethod(line4.shift, 1.8*UP*XTD),ApplyMethod(br5text.scale, 0.3), ApplyMethod(br6text.scale, 0.3), run_time = 0.5)
+
+ self.wait(5) \ No newline at end of file
diff --git a/FSF-2020/calculus/intro-to-calculus/limit/limitfin2.py b/FSF-2020/calculus/intro-to-calculus/limit/limitfin2.py
new file mode 100644
index 0000000..36ca388
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/limit/limitfin2.py
@@ -0,0 +1,70 @@
+from manimlib.imports import *
+class limitfin2(GraphScene):
+ CONFIG = {
+ "x_min" : -8,
+ "x_max" : 8,
+ "x_labeled_nums" : list(range(-8, 10, 3)),
+ "x_axis_width" : FRAME_WIDTH - LARGE_BUFF,
+ "y_min" : -4,
+ "y_max" : 4,
+ "y_labeled_nums" : None,#list(range(3,,)),
+ "y_axis_height" : FRAME_HEIGHT+2*LARGE_BUFF,
+ "graph_origin" : DOWN,
+ "graph_color" : BLUE,
+ "x_axis_width":20,
+ "y_axis_height":10,
+ }
+ def construct(self):
+ self.setup_axes()
+ XTD = 10/(8 - (-8))
+ YTD = 10/(4 - (-4))
+ graph1 = self.get_graph(lambda x: -(-(0.25*x**2)-1), x_min = self.x_min, x_max = -0.1)
+ graph2 = self.get_graph(lambda x: ((0.25*x**2)+2), x_min = 0.1, x_max = self.x_max, color = self.graph_color)
+ dot1 = Circle(radius = 0.1).move_to(self.graph_origin+1*UP*YTD)
+ dot2 = Circle(radius = 0.1).move_to(self.graph_origin+2*UP*YTD)
+ text1 = TexMobject(r"\text{It doesn't matter how small }", r"\delta",r"\text{ gets, }" r"\epsilon" r"\text{ does not tend to zero}").move_to(self.graph_origin+2*DOWN)
+ self.play(ShowCreation(graph1), ShowCreation(graph2), ShowCreation(text1), FadeIn(dot1), FadeIn(dot2))
+ line1 = DashedVMobject(Line(self.graph_origin+1*DOWN*YTD+1*LEFT*XTD, self.graph_origin+4*UP*YTD+1*LEFT*XTD), num_dashes = 50).set_color(PINK)
+ line2 = DashedVMobject(Line(self.graph_origin+1*DOWN*YTD+1*RIGHT*XTD, self.graph_origin+4*UP*YTD+1*RIGHT*XTD), num_dashes = 50).set_color(PINK)
+ line3 = DashedVMobject(Line(self.graph_origin+1.5*UP*YTD+5*LEFT*XTD, self.graph_origin+1.5*UP*YTD+4*RIGHT*XTD), num_dashes = 50).set_color(GOLD)
+ line4 = DashedVMobject(Line(self.graph_origin+0.5*UP*YTD+5*LEFT*XTD, self.graph_origin+0.5*UP*YTD+4*RIGHT*XTD), num_dashes = 50).set_color(GOLD)
+ line5 = DashedVMobject(Line(self.graph_origin+2.5*UP*YTD+5*LEFT*XTD, self.graph_origin+2.5*UP*YTD+4*RIGHT*XTD), num_dashes = 50).set_color(GOLD)
+ self.play(ShowCreation(line1), ShowCreation(line2))
+ vec1 = Line(self.graph_origin, self.graph_origin+1*RIGHT*XTD)
+ vec2 = Line(self.graph_origin, self.graph_origin+1*LEFT*XTD)
+ vec5 = Line(self.graph_origin+2.5*UP*YTD+4*RIGHT*XTD, self.graph_origin+1.5*UP*YTD+4*RIGHT*XTD)
+ vec6 = Line(self.graph_origin+0.5*UP*YTD+4*RIGHT*XTD, self.graph_origin+1.5*UP*YTD+4*RIGHT*XTD)
+ brace1 = Brace(vec1, DOWN)
+ brace2 = Brace(vec2, DOWN)
+ br1text = brace1.get_text(r"$\delta$").next_to(brace1, DOWN)
+ br2text = brace2.get_text(r"$\delta$").next_to(brace2, DOWN)
+ brace5 = Brace(vec5, RIGHT)
+ brace6 = Brace(vec6, RIGHT)
+ br5text = brace5.get_text(r"$\epsilon$").next_to(brace5, RIGHT)
+ br6text = brace6.get_text(r"$\epsilon$").next_to(brace6, RIGHT)
+ self.wait(3)
+ self.play(ShowCreation(brace1), ShowCreation(brace2), ShowCreation(br1text), ShowCreation(br2text))
+ self.wait(3)
+ self.play(ShowCreation(line3), ShowCreation(line4), ShowCreation(line5), ShowCreation(brace5), ShowCreation(brace6), ShowCreation(br5text), ShowCreation(br6text))
+ vec3 = Line(self.graph_origin, self.graph_origin+0.1*RIGHT*XTD)
+ vec4 = Line(self.graph_origin, self.graph_origin+0.11*LEFT*XTD)
+ brace3 = Brace(vec3, DOWN)
+ brace4 = Brace(vec4, DOWN)
+ vec7 = Line(self.graph_origin+2.1*UP*YTD+4*RIGHT*XTD, self.graph_origin+1.5*UP*YTD+4*RIGHT*XTD)
+ vec8 = Line(self.graph_origin+0.9*UP*YTD+4*RIGHT*XTD, self.graph_origin+1.5*UP*YTD+4*RIGHT*XTD)
+ brace7 = Brace(vec7, RIGHT)
+ brace8 = Brace(vec8, RIGHT)
+ self.play(Transform(brace1, brace3), Transform(brace2, brace4), ApplyMethod(line2.shift, 0.8*LEFT*XTD),
+ ApplyMethod(line1.shift, 0.8*RIGHT*XTD), ApplyMethod(br1text.scale, 0.3), ApplyMethod(br2text.scale, 0.3),
+ Transform(brace5, brace7), Transform(brace6, brace8), ApplyMethod(line4.shift, 0.8*UP*XTD),
+ ApplyMethod(line5.shift, 0.8*DOWN*XTD))
+
+ self.play(FadeOut(brace3), FadeOut(brace4), FadeOut(brace1), FadeOut(brace2))
+ self.play(ApplyMethod(line2.shift, 0.8*RIGHT*XTD), ApplyMethod(line1.shift, 0.8*LEFT*XTD), ApplyMethod(br1text.scale, 10/3), ApplyMethod(br2text.scale, 10/3))
+ for i in range(0,3):
+ self.play(ApplyMethod(line2.shift, 0.8*LEFT*XTD), ApplyMethod(line1.shift, 0.8*RIGHT*XTD), ApplyMethod(br1text.scale, 0.3), ApplyMethod(br2text.scale, 0.3), run_time = 0.5)
+ self.play(ApplyMethod(line2.shift, 0.8*RIGHT*XTD), ApplyMethod(line1.shift, 0.8*LEFT*XTD), ApplyMethod(br1text.scale, 10/3), ApplyMethod(br2text.scale, 10/3), run_time = 0.5)
+
+ self.play(ApplyMethod(line2.shift, 0.8*LEFT*XTD), ApplyMethod(line1.shift, 0.8*RIGHT*XTD), ApplyMethod(br1text.scale, 0.3), ApplyMethod(br2text.scale, 0.3), run_time = 0.5)
+
+ self.wait(5) \ No newline at end of file
diff --git a/FSF-2020/calculus/intro-to-calculus/riemann-integrals/README.md b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/README.md
new file mode 100644
index 0000000..de6df0f
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/README.md
@@ -0,0 +1,18 @@
+rierect1.gif
+![rierect1](https://user-images.githubusercontent.com/61246381/87141790-3ad90800-c2c1-11ea-86e4-af05cb93fa2d.gif)
+
+
+rierect2.gif
+![rierect2](https://user-images.githubusercontent.com/61246381/87141870-5ba15d80-c2c1-11ea-9307-40acc2884d77.gif)
+
+
+rierect3.gif
+![rierect3](https://user-images.githubusercontent.com/61246381/87141949-6e1b9700-c2c1-11ea-9433-4f6be752aa55.gif)
+
+
+RiemannRectanglesAnimation.gif
+![RiemannRectanglesAnimation](https://user-images.githubusercontent.com/61246381/87952202-2c5fcd00-cac7-11ea-8b14-a0c522886714.gif)
+
+
+mimi.gif
+![mimi](https://user-images.githubusercontent.com/61246381/87142127-b3d85f80-c2c1-11ea-864e-627e41d87ea2.gif)
diff --git a/FSF-2020/calculus/intro-to-calculus/riemann-integrals/RiemannRectanglesAnimation.py b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/RiemannRectanglesAnimation.py
new file mode 100644
index 0000000..1757231
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/RiemannRectanglesAnimation.py
@@ -0,0 +1,66 @@
+from manimlib.imports import *
+class RiemannRectanglesAnimation(GraphScene):
+ CONFIG = {
+ "y_max": 5,
+ "x_max": 6,
+ "x_min": 0,
+ "y_min": 0,
+ "x_axis_width": 5,
+ "y_axis_height": 5,
+ "init_dx":0.5,
+ "graph_origin": ORIGIN+2*DOWN+6*LEFT,
+ }
+ def construct(self):
+ self.setup_axes()
+ def func(x):
+ return 0.1*(x)*(x-3)*(x-7)+3
+
+ graph1=self.get_graph(func,x_min=0,x_max=6)
+ kwargs = {
+ "x_min" : 1.5,
+ "x_max" : 5.5,
+ "fill_opacity" : 0.75,
+ "stroke_width" : 0.25,
+ "input_sample_type": "right",
+ }
+ flat_rectangles1 = self.get_riemann_rectangles(self.get_graph(lambda x : 0),dx=self.init_dx,start_color=invert_color(PURPLE),end_color=invert_color(ORANGE),**kwargs)
+ riemann_rectangles_list1 = self.get_riemann_rectangles_list(graph1,6,max_dx=self.init_dx,power_base=2,start_color=PURPLE,end_color=ORANGE,**kwargs)
+ self.add(graph1)
+ self.graph_origin = ORIGIN+2*DOWN+1*RIGHT
+ self.setup_axes()
+ graph2=self.get_graph(func,x_min=0,x_max=6)
+ kwargs = {
+ "x_min" : 1.5,
+ "x_max" : 5.5,
+ "fill_opacity" : 0.75,
+ "stroke_width" : 0.25,
+ "input_sample_type": "left",
+ }
+ flat_rectangles2 = self.get_riemann_rectangles(self.get_graph(lambda x : 0),dx=self.init_dx,start_color=invert_color(PURPLE),end_color=invert_color(ORANGE),**kwargs)
+ riemann_rectangles_list2 = self.get_riemann_rectangles_list(graph2,6,max_dx=self.init_dx,power_base=2,start_color=PURPLE,end_color=ORANGE,**kwargs)
+ self.add(graph2)
+ text1 = TextMobject("Left Riemann sum").move_to(np.array([-3,-2.5,0]))
+ text2 = TextMobject("Right Riemann sum").move_to(np.array([4,-2.5,0]))
+ grp1 = VGroup(text1, text2)
+ text3 = TexMobject(r"n \rightarrow \infty").move_to(np.array([0, -3, 0]))
+ text4 = TextMobject("Left and Right Riemann sums are equal").move_to(np.array([0, -3, 0]))
+ text5 = TextMobject("Hence function is Riemann integrable and value of integral equals area covered").move_to(np.array([0, -3, 0])).scale(0.6)
+ grp2 = VGroup(text1, text2, text3)
+ # Show Riemann rectangles
+ self.play(ReplacementTransform(flat_rectangles1,riemann_rectangles_list1[0]), ReplacementTransform(flat_rectangles2, riemann_rectangles_list2[0]))
+ self.wait()
+ self.play(ShowCreation(grp1))
+ for r in range(1,len(riemann_rectangles_list1)-3):
+ self.transform_between_riemann_rects(riemann_rectangles_list1[r-1],riemann_rectangles_list1[r],replace_mobject_with_target_in_scene = True,)
+ self.transform_between_riemann_rects(riemann_rectangles_list2[r-1],riemann_rectangles_list2[r],replace_mobject_with_target_in_scene = True,)
+ self.play(ShowCreation(text3))
+ for r in range(len(riemann_rectangles_list1)-3,len(riemann_rectangles_list1)):
+ self.transform_between_riemann_rects(riemann_rectangles_list1[r-1],riemann_rectangles_list1[r],replace_mobject_with_target_in_scene = True,)
+ self.transform_between_riemann_rects(riemann_rectangles_list2[r-1],riemann_rectangles_list2[r],replace_mobject_with_target_in_scene = True,)
+ self.wait(2)
+ grp3 = VGroup(graph1, riemann_rectangles_list1[5])
+ grp4 = VGroup(graph2, riemann_rectangles_list2[5])
+ self.play(ReplacementTransform(grp2, text4))
+ self.wait(2)
+ self.play(ReplacementTransform(text4, text5), ApplyMethod(grp4.shift, 7*LEFT), ApplyMethod(self.axes.shift, 7*LEFT), )
+ self.wait(4) \ No newline at end of file
diff --git a/FSF-2020/calculus/intro-to-calculus/riemann-integrals/mimi.py b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/mimi.py
new file mode 100644
index 0000000..2471c87
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/mimi.py
@@ -0,0 +1,53 @@
+class mimi(GraphScene):
+ CONFIG = {
+ "y_max": 5,
+ "x_max": 6,
+ "x_min": 0,
+ "y_min": 0,
+ "x_axis_width": 5,
+ "y_axis_height": 5,
+ "init_dx":0.5,
+ "graph_origin": ORIGIN+2*DOWN+6*LEFT,
+ }
+ def construct(self):
+ self.setup_axes()
+ def func(x):
+ return 0.1*(x)*(x-3)*(x-7)+3
+
+ graph=self.get_graph(func,x_min=0,x_max=6)
+ kwargs = {
+ "x_min" : 1.5,
+ "x_max" : 5.5,
+ "fill_opacity" : 0.5,
+ "stroke_width" : 0.25,
+ }
+ flat_rectangles = self.get_riemann_rectangles(self.get_graph(lambda x : 0),dx=self.init_dx,**kwargs)
+ riemann_rectangles_list = self.get_riemann_rectangles_list(graph,8,max_dx=self.init_dx,power_base=2,start_color=PURPLE,end_color=ORANGE,**kwargs, input_sample_type = "right")
+ riemann_rectangles_list1 = self.get_riemann_rectangles_list(graph,8,max_dx=self.init_dx,power_base=2,start_color=PURPLE,end_color=ORANGE,**kwargs, input_sample_type = "left")
+ self.add(graph)
+ self.play(ReplacementTransform(flat_rectangles,riemann_rectangles_list[0]), ReplacementTransform(flat_rectangles,riemann_rectangles_list1[0]))
+ #self.play(ReplacementTransform(flat_rectangles,riemann_rectangles_list1[0]))
+ self.wait(2)
+ kwargs = {
+ "x_min" : 3,
+ "x_max" : 3.5,
+ "fill_opacity" : 0.5,
+ "stroke_width" : 0.25,
+ }
+ riemann_rectangles_list2 = self.get_riemann_rectangles_list(graph,8,max_dx=self.init_dx,power_base=2,start_color=PURPLE,end_color=ORANGE,**kwargs, input_sample_type = "right")
+ riemann_rectangles_list3 = self.get_riemann_rectangles_list(graph,8,max_dx=self.init_dx,power_base=2,start_color=PURPLE,end_color=ORANGE,**kwargs, input_sample_type = "left")
+ #self.play(FadeOut(riemann_rectangles_list[0]), FadeOut(riemann_rectangles_list1[0]))
+ self.play(ReplacementTransform(flat_rectangles,riemann_rectangles_list2[0]), ReplacementTransform(flat_rectangles,riemann_rectangles_list3[0]), FadeOut(riemann_rectangles_list[0]), FadeOut(riemann_rectangles_list1[0]))
+ minlim = self.get_vertical_line_to_graph(3,graph,DashedLine)
+ maxlim = self.get_vertical_line_to_graph(3.5,graph,DashedLine)
+ line2 = Line(self.graph_origin+2.5*RIGHT, self.graph_origin+2.9*RIGHT)
+ brace1 = Brace(minlim, LEFT)
+ brace2 = Brace(line2, DOWN)
+ brace3 = Brace(maxlim, RIGHT)
+ br1text = brace1.get_text(r"${M}_{i}$").next_to(brace1, LEFT)
+ br2text = brace2.get_text(r"$\Delta x$").next_to(brace2, DOWN)
+ br3text = brace3.get_text(r"${m}_{i}$").next_to(brace3, RIGHT)
+ text1 = TexMobject(r"\Delta x=(b-a)/n").shift(2*RIGHT)
+ grp3 = VGroup(br1text, br2text, br3text, brace1, brace2, brace3, text1)
+ self.play(ShowCreation(grp3))
+ self.wait(5)
diff --git a/FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect1.py b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect1.py
new file mode 100644
index 0000000..748d766
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect1.py
@@ -0,0 +1,31 @@
+from manimlib.imports import *
+class rierect1(GraphScene):
+ CONFIG = {
+ "y_max" : 6,
+ "y_min" : 0,
+ "x_max" : 4,
+ "x_min" : 0,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color" : WHITE,
+ "num_graph_anchor_points": 3000, #this is the number of points that graph manim
+ "graph_origin" : ORIGIN+2*DOWN+4*LEFT,
+ "x_labeled_nums": None,#list(range(-1,2)),
+ "y_labeled_nums": None,#list(range(0,2)),
+ "x_axis_label":"$x$",
+ "y_axis_label":"$f(x)$",
+ "x_axis_width": 10,
+ "y_axis_height": 5,
+ }
+ def construct(self):
+ self.setup_axes()
+ graph1 = self.get_graph(lambda x : (0.1*(1.5*x+1)**2 +0.5), x_min = 0, x_max = 4)
+ minlim = self.get_vertical_line_to_graph(1,graph1,DashedLine, color = PINK)
+ maxlim = self.get_vertical_line_to_graph(3,graph1,DashedLine,color = PINK)
+ x1 = TexMobject(r"{x}_{1}").next_to(minlim, DOWN)
+ x2 = TexMobject(r"{x}_{2}").next_to(maxlim, DOWN)
+ rie1 = self.get_riemann_rectangles(graph1, x_min = 1, x_max = 3, dx = 0.4, input_sample_type = "left", fill_opacity = 1, start_color = YELLOW, end_color = YELLOW)
+ #rie2 = self.get_riemann_rectangles(graph1, x_min = 1, x_max = 3, dx = 0.01, input_sample_type = "right", fill_opacity = 0.5, start_color = PINK, end_color = LIGHT_PINK)
+ group = VGroup(graph1, minlim, maxlim, x1, x2, rie1)
+ self.play(ShowCreation(group))
+ self.wait(1.5)
diff --git a/FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect2.py b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect2.py
new file mode 100644
index 0000000..e300250
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect2.py
@@ -0,0 +1,31 @@
+from manimlib.imports import *
+class rierect2(GraphScene):
+ CONFIG = {
+ "y_max" : 6,
+ "y_min" : 0,
+ "x_max" : 4,
+ "x_min" : 0,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color" : WHITE,
+ "num_graph_anchor_points": 3000, #this is the number of points that graph manim
+ "graph_origin" : ORIGIN+2*DOWN+4*LEFT,
+ "x_labeled_nums": None,#list(range(-1,2)),
+ "y_labeled_nums": None,#list(range(0,2)),
+ "x_axis_label":"$x$",
+ "y_axis_label":"$f(x)$",
+ "x_axis_width": 10,
+ "y_axis_height": 5,
+ }
+ def construct(self):
+ self.setup_axes()
+ graph1 = self.get_graph(lambda x : (0.1*(1.5*x+1)**2 +0.5), x_min = 0, x_max = 4)
+ minlim = self.get_vertical_line_to_graph(1,graph1,DashedLine, color = PINK)
+ maxlim = self.get_vertical_line_to_graph(3,graph1,DashedLine,color = PINK)
+ x1 = TexMobject(r"{x}_{1}").next_to(minlim, DOWN)
+ x2 = TexMobject(r"{x}_{2}").next_to(maxlim, DOWN)
+ rie1 = self.get_riemann_rectangles(graph1, x_min = 1, x_max = 3, dx = 0.1, input_sample_type = "left", fill_opacity = 1, start_color = YELLOW, end_color = YELLOW)
+ #rie2 = self.get_riemann_rectangles(graph1, x_min = 1, x_max = 3, dx = 0.01, input_sample_type = "right", fill_opacity = 0.5, start_color = PINK, end_color = LIGHT_PINK)
+ group = VGroup(graph1, minlim, maxlim, x1, x2, rie1)
+ self.play(ShowCreation(group))
+ self.wait(1.5)
diff --git a/FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect3.py b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect3.py
new file mode 100644
index 0000000..3542358
--- /dev/null
+++ b/FSF-2020/calculus/intro-to-calculus/riemann-integrals/rierect3.py
@@ -0,0 +1,31 @@
+from manimlib.imports import *
+class rierect3(GraphScene):
+ CONFIG = {
+ "y_max" : 6,
+ "y_min" : 0,
+ "x_max" : 4,
+ "x_min" : 0,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color" : WHITE,
+ "num_graph_anchor_points": 3000, #this is the number of points that graph manim
+ "graph_origin" : ORIGIN+2*DOWN+4*LEFT,
+ "x_labeled_nums": None,#list(range(-1,2)),
+ "y_labeled_nums": None,#list(range(0,2)),
+ "x_axis_label":"$x$",
+ "y_axis_label":"$f(x)$",
+ "x_axis_width": 10,
+ "y_axis_height": 5,
+ }
+ def construct(self):
+ self.setup_axes()
+ graph1 = self.get_graph(lambda x : (0.1*(1.5*x+1)**2 +0.5), x_min = 0, x_max = 4)
+ minlim = self.get_vertical_line_to_graph(1,graph1,DashedLine, color = PINK)
+ maxlim = self.get_vertical_line_to_graph(3,graph1,DashedLine,color = PINK)
+ x1 = TexMobject(r"{x}_{1}").next_to(minlim, DOWN)
+ x2 = TexMobject(r"{x}_{2}").next_to(maxlim, DOWN)
+ rie1 = self.get_riemann_rectangles(graph1, x_min = 1, x_max = 3, dx = 0.01, input_sample_type = "left", fill_opacity = 1, start_color = YELLOW, end_color = YELLOW)
+ #rie2 = self.get_riemann_rectangles(graph1, x_min = 1, x_max = 3, dx = 0.01, input_sample_type = "right", fill_opacity = 0.5, start_color = PINK, end_color = LIGHT_PINK)
+ group = VGroup(graph1, minlim, maxlim, x1, x2, rie1)
+ self.play(ShowCreation(group))
+ self.wait(1.5)
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/README.md b/FSF-2020/calculus/series-and-transformations/Fourier Transform/README.md
new file mode 100644
index 0000000..2fa4e04
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/README.md
@@ -0,0 +1,20 @@
+### Dividing a tone into its constituents
+![GIF1](gifs/file1.gif)
+
+### Colors Analogy
+![GIF2](gifs/file2a.gif)
+
+### Applying the same on Graphs
+![GIF3](gifs/file2b.gif)
+
+### Fourier series for non-periodic functions-a
+![GIF4](gifs/file3.gif)
+
+### Fourier series for non-periodic functions-b
+![GIF4a](gifs/file7.gif)
+
+### Fourier Series of Square pulse
+![GIF5](gifs/file4.gif)
+
+### Coins Analogy
+![GIF6](gifs/file5.gif)
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file1.gif b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file1.gif
new file mode 100644
index 0000000..d4dc9d7
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file1.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file2a.gif b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file2a.gif
new file mode 100644
index 0000000..8f83bc4
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file2a.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file2b.gif b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file2b.gif
new file mode 100644
index 0000000..d68c405
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file2b.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file3.gif b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file3.gif
new file mode 100644
index 0000000..de94810
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file3.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file4.gif b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file4.gif
new file mode 100644
index 0000000..36cd61b
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file4.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file5.gif b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file5.gif
new file mode 100644
index 0000000..9757bd6
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file5.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file6.gif b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file6.gif
new file mode 100644
index 0000000..de94810
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file6.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file7.gif b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file7.gif
new file mode 100644
index 0000000..ab4eed8
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/gifs/file7.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/video1_DividingAToneIntoItsConstituents.py b/FSF-2020/calculus/series-and-transformations/Fourier Transform/video1_DividingAToneIntoItsConstituents.py
new file mode 100644
index 0000000..fdb8719
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/video1_DividingAToneIntoItsConstituents.py
@@ -0,0 +1,83 @@
+from manimlib.imports import*
+import numpy as np
+
+class intro(GraphScene):
+ CONFIG = {
+ "x_min": -3,
+ "x_max": 3,
+ "x_axis_width": 6,
+ "y_min": -5,
+ "y_max": 5,
+ "graph_origin": 10.5*LEFT,
+ "axes_color": BLUE,
+ "exclude_zero_label": True,
+ "x_labeled_nums": range(-2, 3, 1),
+ }
+ def func(self,t,n1,n2):
+ s=0
+ for i in range(n1,n2+1):
+ s+=((-2/(i*np.pi))*((-1)**i)*np.sin(2*np.pi*i*t))
+ return s
+
+ def construct(self):
+ image=ImageMobject('image.png').shift(5.5*LEFT+2.5*UP).scale(1.5)
+ self.play(ShowCreation(image))
+
+ self.setup_axes(scalee=1)
+
+ mainGraphs=[
+ self.get_graph(lambda x:self.func(x,2,7),x_max=2,x_min=-2).shift(9.3*RIGHT+3*UP).set_color([ORANGE,GREEN_B,RED_E,YELLOW_E,RED_D,YELLOW_D]).scale(1.4),
+ self.get_graph(lambda x:self.func(x,3,7),x_max=2,x_min=-2).shift(10.8*RIGHT+3*UP).set_color([GREEN_B,ORANGE,RED_D,YELLOW_E,YELLOW_D]).scale(1.4),
+ self.get_graph(lambda x:self.func(x,4,7),x_max=2,x_min=-2).shift(10.8*RIGHT+3*UP).set_color([GREEN_B,YELLOW_E,ORANGE,YELLOW_D]).scale(1.4),
+ self.get_graph(lambda x:self.func(x,5,7),x_max=2,x_min=-2).shift(10.8*RIGHT+3*UP).set_color([YELLOW_E,GREEN_B,YELLOW_D]).scale(1.4),
+ self.get_graph(lambda x:self.func(x,6,7),x_max=2,x_min=-2).shift(10.8*RIGHT+3*UP).set_color([YELLOW_D,GREEN_B]).scale(1.4),
+ self.get_graph(lambda x:self.func(x,7,7),x_max=2,x_min=-2,color=GREEN_B).shift(10.8*RIGHT+3*UP).scale(1.4),
+ ]
+ self.play(ApplyMethod(mainGraphs[0].shift,1.5*RIGHT))
+
+ graph1=self.get_graph(lambda x:self.func(x,2,2),x_max=2,x_min=-2,color=RED_E).shift(10.8*RIGHT+3*UP).scale(1.5)
+ graph2=self.get_graph(lambda x:self.func(x,3,3),x_max=2,x_min=-2,color=RED_D).shift(10.8*RIGHT+3*UP).scale(1.5)
+ graph3=self.get_graph(lambda x:self.func(x,4,4),x_max=2,x_min=-2,color=ORANGE).shift(10.8*RIGHT+3*UP).scale(1.5)
+ graph4=self.get_graph(lambda x:self.func(x,5,5),x_max=2,x_min=-2,color=YELLOW_E).shift(10.8*RIGHT+3*UP).scale(1.5)
+ graph5=self.get_graph(lambda x:self.func(x,6,6),x_max=2,x_min=-2,color=YELLOW_D).shift(10.8*RIGHT+3*UP).scale(1.5)
+
+ coeff=[
+ TextMobject("$\\frac { -1 }{ \pi } sin(4\pi t)$").scale(0.5).shift(DOWN+4.6*RIGHT+3*UP).set_color(RED_E),
+ TextMobject("$\\frac { 2 }{ 3\pi } sin(6\pi t)$").scale(0.5).shift(2*DOWN+4.6*RIGHT+3*UP).set_color(RED_D),
+ TextMobject("$\\frac { -1 }{ 2\pi } sin(8\pi t)$").scale(0.5).shift(3*DOWN+4.6*RIGHT+3*UP).set_color(ORANGE),
+ TextMobject("$\\frac { 2 }{ 5\pi } sin(10\pi t)$").scale(0.5).shift(4*DOWN+4.6*RIGHT+3*UP).set_color(YELLOW_E),
+ TextMobject("$\\frac { -1 }{ 3\pi } sin(12\pi t)$").scale(0.5).shift(5*DOWN+4.6*RIGHT+3*UP).set_color(YELLOW_D),
+ TextMobject("$\\frac { 2 }{ 7\pi } sin(14\pi t)$").scale(0.5).shift(6*DOWN+4.6*RIGHT+3*UP).set_color(GREEN_B)
+ ]
+
+ self.wait(0.6)
+ self.play(ApplyMethod(graph1.shift,1*DOWN),ReplacementTransform(mainGraphs[0],mainGraphs[1]))
+ self.play(Write(coeff[0]))
+ self.play(ApplyMethod(graph2.shift,2*DOWN),ReplacementTransform(mainGraphs[1],mainGraphs[2]))
+ self.play(Write(coeff[1]))
+ self.play(ApplyMethod(graph3.shift,3*DOWN),ReplacementTransform(mainGraphs[2],mainGraphs[3]))
+ self.play(Write(coeff[2]))
+ self.play(ApplyMethod(graph4.shift,4*DOWN),ReplacementTransform(mainGraphs[3],mainGraphs[4]))
+ self.play(Write(coeff[3]))
+ self.play(ApplyMethod(graph5.shift,5*DOWN),ReplacementTransform(mainGraphs[4],mainGraphs[5]))
+ self.play(Write(coeff[4]))
+ self.play(ApplyMethod(mainGraphs[5].shift,6*DOWN))
+ self.play(Write(coeff[5]))
+
+ pluses=[TextMobject("+"),TextMobject("+"),TextMobject("+"),TextMobject("+"),TextMobject("+")]
+ for t in pluses:
+ t.scale(0.5).shift((2.2-1.5*pluses.index(t))*LEFT)
+
+ finalGraph=self.get_graph(lambda x:self.func(x,2,7),x_max=2,x_min=-2).shift(10.8*RIGHT+3*UP)
+ finalGraph.set_color([GREEN_B,YELLOW_D,YELLOW_E,ORANGE,RED_D,RED_E])
+ finalGroup=VGroup(graph1,graph2,graph3,graph4,graph5,mainGraphs[5])
+ self.play(ReplacementTransform(finalGroup,finalGraph))
+ self.play(ApplyMethod(coeff[0].scale,0.7),ApplyMethod(coeff[1].scale,0.7),ApplyMethod(coeff[2].scale,0.7),ApplyMethod(coeff[3].scale,0.7),ApplyMethod(coeff[4].scale,0.7),ApplyMethod(coeff[5].scale,0.7))
+ #self.play(ApplyMethod(coeff[0].shift,7*LEFT+1.6*DOWN),ApplyMethod(coeff[1].shift,5.5*LEFT+0.8*DOWN),ApplyMethod(coeff[2].shift,4*LEFT),ApplyMethod(coeff[3].shift,2.5*LEFT+0.8*UP),ApplyMethod(coeff[4].shift,LEFT+1.6*UP),ApplyMethod(coeff[5].shift,0.5*RIGHT+2.4*DOWN))
+ self.play(ApplyMethod(coeff[0].shift,7.6*LEFT+2*DOWN),ApplyMethod(coeff[1].shift,6.1*LEFT+DOWN),ApplyMethod(coeff[2].shift,4.6*LEFT),ApplyMethod(coeff[3].shift,3.1*LEFT+UP),ApplyMethod(coeff[4].shift,1.6*LEFT+2*UP),ApplyMethod(coeff[5].shift,0.1*LEFT+3*UP))
+ equal=TextMobject("=").scale(1.5).shift(1.5*UP)
+ self.play(Write(equal))
+ self.play(Write(pluses[0]),Write(pluses[1]),Write(pluses[2]),Write(pluses[3]),Write(pluses[4]))
+ group=VGroup(pluses[0],pluses[1],pluses[2],pluses[3],pluses[4],coeff[0],coeff[1],coeff[2],coeff[3],coeff[4],coeff[5])
+ self.play(ApplyMethod(group.scale,1.5))
+ self.wait(2)
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/video2_ColorsAnalogyForFourierSeries.py b/FSF-2020/calculus/series-and-transformations/Fourier Transform/video2_ColorsAnalogyForFourierSeries.py
new file mode 100644
index 0000000..c87e58e
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/video2_ColorsAnalogyForFourierSeries.py
@@ -0,0 +1,146 @@
+from manimlib.imports import*
+import numpy as np
+
+def func(t,n1,n2):
+ s=0
+ for i in range(n1,n2+1):
+ s+=((-2/(i*np.pi))*((-1)**i)*np.sin(2*np.pi*i*t))
+ return s
+
+class divideColors(GraphScene):
+ CONFIG = {
+ "x_min": -2,
+ "x_max": 2,
+ "y_min": -1,
+ "y_max": 1,
+ "graph_origin": ORIGIN,
+ "function_color": RED,
+ "axes_color": BLUE,
+ "x_axis_label": "$t$",
+ "y_axis_label": "$y$",
+ "x_labeled_nums": range(-1, 2, 1),
+ "x_axis_width": 3,
+ "y_axis_height": 2
+ }
+ def construct(self):
+ text1a=TextMobject("Consider dividing a","mixture of colors")
+ text1b=TextMobject("into its","components")
+ text1a.scale(0.8)
+ text1b.scale(0.8)
+ text1a.shift(UP)
+ text1b.shift(0.3*UP)
+ text1a.set_color_by_tex_to_color_map({"mixture of colors":[GREEN,RED,BLUE,YELLOW]})
+ text1b.set_color_by_tex_to_color_map({"components":GREEN})
+ self.play(Write(text1a))
+ self.play(FadeIn(text1b))
+ self.wait(0.8)
+
+ self.play(FadeOut(text1a),FadeOut(text1b))
+
+ mainCircle=Circle(radius=1.4,color=BLACK,fill_color=[PURPLE_E,PURPLE_D,RED_B,ORANGE,YELLOW_B,YELLOW_D,GREEN_A,GREEN_C],fill_opacity=0.8)
+ self.play(ShowCreation(mainCircle))
+ self.wait(1)
+ mainCirclea=Circle(radius=1.4,color=BLACK,fill_color=[RED_B,ORANGE,YELLOW_B,YELLOW_D,GREEN_A,GREEN_C],fill_opacity=0.8)
+ mainCircleb=Circle(radius=1.4,color=BLACK,fill_color=[YELLOW_B,YELLOW_D,GREEN_A,GREEN_C],fill_opacity=0.8)
+ mainCirclec=Circle(radius=1.4,color=BLACK,fill_color=[GREEN_A,GREEN_C],fill_opacity=0.8)
+ mainCircled=Circle(radius=1.4,color=BLACK,fill_color=[],fill_opacity=0.8)
+
+ c1=Circle(radius=0.5,color=PURPLE_E,fill_color=PURPLE_E,fill_opacity=0.8)
+ c2=Circle(radius=0.5,color=PURPLE_D,fill_color=PURPLE_D,fill_opacity=0.8)
+ c3=Circle(radius=0.5,color=RED_D,fill_color=RED_B,fill_opacity=0.8)
+ c4=Circle(radius=0.5,color=ORANGE,fill_color=ORANGE,fill_opacity=0.8)
+ c5=Circle(radius=0.5,color=YELLOW_B,fill_color=YELLOW_B,fill_opacity=0.8)
+ c6=Circle(radius=0.5,color=YELLOW_D,fill_color=YELLOW_D,fill_opacity=0.8)
+ c7=Circle(radius=0.5,color=GREEN_A,fill_color=GREEN_A,fill_opacity=0.8)
+ c8=Circle(radius=0.5,color=GREEN_C,fill_color=GREEN_C,fill_opacity=0.8)
+
+ self.play(ApplyMethod(c1.shift,3*UP+LEFT),ApplyMethod(c2.shift,3*UP+RIGHT),ReplacementTransform(mainCircle,mainCirclea))
+ self.wait(0.8)
+
+ self.play(ApplyMethod(c3.shift,UP+3*LEFT),ApplyMethod(c4.shift,DOWN+3*LEFT),ReplacementTransform(mainCirclea,mainCircleb))
+ self.wait(0.8)
+
+ self.play(ApplyMethod(c5.shift,3*DOWN+LEFT),ApplyMethod(c6.shift,3*DOWN+RIGHT),ReplacementTransform(mainCircleb,mainCirclec))
+ self.wait(0.8)
+
+ self.play(ApplyMethod(c7.shift,3*RIGHT+UP),ApplyMethod(c8.shift,3*RIGHT+DOWN),ReplacementTransform(mainCirclec,mainCircled))
+ self.wait(1)
+
+ text2=TextMobject("Similarly,").scale(0.8).shift(UP).set_color(RED)
+
+ self.play(FadeOut(c1),FadeOut(c2),FadeOut(c3),FadeOut(c4),FadeOut(c5),FadeOut(c6),FadeOut(c7),FadeOut(c8))
+ self.play(Write(text2))
+ self.wait(0.8)
+ self.play(FadeOut(text2))
+
+
+ coeff=[
+ TextMobject("$\\frac { -2 }{ \pi } \sum _{ n=1 }^{ 24 }{ \\frac { { -1 }^{ n } }{ n } sin(2\pi nt) }$").scale(0.2).shift(RIGHT+UP),
+ TextMobject("$\\frac { 2 }{ \pi } sin(2\pi t)$").scale(0.3).shift(RIGHT+UP+4*LEFT+UP),
+ TextMobject("$\\frac { -2 }{ \pi } \sum _{ n=2 }^{ 24 }{ \\frac { { -1 }^{ n } }{ n } sin(2\pi nt) }$").scale(0.2).shift(RIGHT+UP),
+ TextMobject("$\\frac { -1 }{ \pi } sin(4\pi t)$").scale(0.3).shift(RIGHT+UP+4*RIGHT+UP),
+ TextMobject("$\\frac { -2 }{ \pi } \sum _{ n=3 }^{ 24 }{ \\frac { { -1 }^{ n } }{ n } sin(2\pi nt) }$").scale(0.2).shift(RIGHT+UP),
+ TextMobject("$\\frac { 2 }{ 3\pi } sin(6\pi t)$").scale(0.3).shift(RIGHT+UP+4*LEFT+2*DOWN),
+ TextMobject("$\\frac { -2 }{ \pi } \sum _{ n=4 }^{ 24 }{ \\frac { { -1 }^{ n } }{ n } sin(2\pi nt) }$").scale(0.2).shift(RIGHT+UP),
+ TextMobject("$\\frac { -1 }{ 2\pi } sin(8\pi t)$").scale(0.3).shift(RIGHT+UP+4*RIGHT+2*DOWN),
+ TextMobject("$\\frac { -2 }{ \pi } \sum _{ n=5 }^{ 24 }{ \\frac { { -1 }^{ n } }{ n } sin(2\pi nt) }$").scale(0.2).shift(RIGHT+UP),
+ TextMobject("$\\frac { 2 }{ 5\pi } sin(10\pi t)$").scale(0.3).shift(RIGHT+UP+2.5*UP),
+ TextMobject("$\\frac { -2 }{ \pi } \sum _{ n=6 }^{ 24 }{ \\frac { { -1 }^{ n } }{ n } sin(2\pi nt) }$").scale(0.2).shift(RIGHT+UP),
+ TextMobject("$\\frac { -1 }{ 3\pi } sin(12\pi t)$").scale(0.3).shift(RIGHT+UP+2.5*DOWN),
+ TextMobject("$\\frac { -2 }{ \pi } \sum _{ n=7 }^{ 24 }{ \\frac { { -1 }^{ n } }{ n } sin(2\pi nt) }$").scale(0.2).shift(RIGHT+UP),
+ ]
+
+ axes=[]
+ self.setup_axes(scalee=1)
+ axes.append(self.axes)
+ graphs=[self.get_graph(lambda x:func(x,1,24),x_min=-1,x_max=1).set_color([DARK_BROWN,GREEN_E,GREEN_C,GOLD_E,GOLD_C,ORANGE,RED_C]),
+ self.get_graph(lambda x:func(x,2,24),x_min=-1,x_max=1).set_color([DARK_BROWN,GREEN_C,GOLD_E,GOLD_C,ORANGE,RED_C]),
+ self.get_graph(lambda x:func(x,3,24),x_min=-1,x_max=1).set_color([DARK_BROWN,GOLD_E,GOLD_C,ORANGE,RED_C]),
+ self.get_graph(lambda x:func(x,4,24),x_min=-1,x_max=1).set_color([DARK_BROWN,GOLD_C,ORANGE,RED_C]),
+ self.get_graph(lambda x:func(x,5,24),x_min=-1,x_max=1).set_color([DARK_BROWN,ORANGE,RED_C]),
+ self.get_graph(lambda x:func(x,6,24),x_min=-1,x_max=1).set_color([DARK_BROWN,RED_C]),
+ self.get_graph(lambda x:func(x,7,24),x_min=-1,x_max=1).set_color(DARK_BROWN)
+ ]
+
+ self.setup_axes(scalee=1)
+ axes.append(self.axes)
+ graph1=self.get_graph(lambda x:func(x,1,1),x_min=-1,x_max=1,color=GREEN_E)
+
+ self.setup_axes(scalee=1)
+ axes.append(self.axes)
+ graph2=self.get_graph(lambda x:func(x,2,2),x_min=-1,x_max=1,color=GREEN_C)
+
+ self.setup_axes(scalee=1)
+ axes.append(self.axes)
+ graph3=self.get_graph(lambda x:func(x,3,3),x_min=-1,x_max=1,color=GOLD_E)
+
+ self.setup_axes(scalee=1)
+ axes.append(self.axes)
+ graph4=self.get_graph(lambda x:func(x,4,4),x_min=-1,x_max=1,color=GOLD_C)
+
+ self.setup_axes(scalee=1)
+ axes.append(self.axes)
+ graph5=self.get_graph(lambda x:func(x,5,5),x_min=-1,x_max=1,color=ORANGE)
+
+ self.setup_axes(scalee=1)
+ axes.append(self.axes)
+ graph6=self.get_graph(lambda x:func(x,6,6),x_min=-1,x_max=1,color=RED_C)
+
+ groups=[VGroup(axes[1],graph1),VGroup(axes[2],graph2),VGroup(axes[3],graph3),VGroup(axes[4],graph4),
+ VGroup(axes[5],graph5),VGroup(axes[6],graph6)]
+
+ self.play(ShowCreation(graphs[0]))
+ self.play(Write(coeff[0]))
+ self.wait(1)
+
+ self.play(ReplacementTransform(graphs[0],graphs[1]),ApplyMethod(groups[0].shift,4*LEFT+UP),ReplacementTransform(coeff[0],coeff[2]),FadeIn(coeff[1]))
+ self.play(ReplacementTransform(graphs[1],graphs[2]),ApplyMethod(groups[1].shift,4*RIGHT+UP),ReplacementTransform(coeff[2],coeff[4]),FadeIn(coeff[3]))
+ self.play(ReplacementTransform(graphs[2],graphs[3]),ApplyMethod(groups[2].shift,4*LEFT+2*DOWN),ReplacementTransform(coeff[4],coeff[6]),FadeIn(coeff[5]))
+ self.play(ReplacementTransform(graphs[3],graphs[4]),ApplyMethod(groups[3].shift,4*RIGHT+2*DOWN),ReplacementTransform(coeff[6],coeff[8]),FadeIn(coeff[7]))
+ self.play(ReplacementTransform(graphs[4],graphs[5]),ApplyMethod(groups[4].shift,2.5*UP),ReplacementTransform(coeff[8],coeff[10]),FadeIn(coeff[9]))
+ self.play(ReplacementTransform(graphs[5],graphs[6]),ApplyMethod(groups[5].shift,2.5*DOWN),ReplacementTransform(coeff[10],coeff[12]),FadeIn(coeff[11]))
+
+
+
+ self.wait(2)
+
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/video3_seriesVSTransform.py b/FSF-2020/calculus/series-and-transformations/Fourier Transform/video3_seriesVSTransform.py
new file mode 100644
index 0000000..d35f8bf
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/video3_seriesVSTransform.py
@@ -0,0 +1,129 @@
+from manimlib.imports import *
+import numpy as np
+
+class compare(GraphScene,MovingCameraScene):
+ CONFIG = {
+ "x_min": -3,
+ "x_max": 3,
+ "x_axis_width": 6,
+ "y_min": -5,
+ "y_max": 5,
+ "y_axis_label":"$\\frac { { x }^{ 2 } }{ 2 } $",
+ "graph_origin": ORIGIN,
+ "axes_color": BLUE,
+ "exclude_zero_label": True,
+ "x_labeled_nums": range(-2, 3, 1),
+ }
+ def setup(self):
+ GraphScene.setup(self)
+ MovingCameraScene.setup(self)
+ def returnPairLines(self,left,right,y_each_unit):
+ lineLeft=DashedLine(start=(0,5*y_each_unit,0),end=(0,-5*y_each_unit,0)).shift(left)
+ lineRight=DashedLine(start=(0,5*y_each_unit,0),end=(0,-5*y_each_unit,0)).shift(right)
+ return lineLeft,lineRight
+
+ def resultFunc(self,x,n,l):
+ s=(l**2)/6
+ for n in range(1,n+1):
+ s+=(2*((-1)**n))*((l**2)*np.cos(n*np.pi*x/l))*(1/((np.pi**2)*(n**2)))
+ return s
+
+ def returnPartFunction(self,left,right):
+ return self.get_graph(lambda x:(x**2)/2,x_min=left,x_max=right,color=RED)
+
+ def returnPartResult(self,l,n):
+ return self.get_graph(lambda x:self.resultFunc(x,n,l),x_min=-3,x_max=3,color=RED)
+
+ def construct(self):
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+ axes=[]
+ self.setup_axes(animate=True,scalee=1)
+ axes.append(self.axes)
+ partFunction1=self.returnPartFunction(-1,1).shift(4*LEFT)
+ partFunction2=self.returnPartFunction(-2,2).shift(4*LEFT)
+ functionText=TextMobject("$\\frac { { x }^{ 2 } }{ 2 } $")
+ function=self.get_graph(lambda x:(x**2)/2,x_min=-3,x_max=3,color=GREEN)
+ text1=TextMobject("Non-Periodic function").scale(0.5).shift(3*DOWN+3*RIGHT).set_color(RED)
+ self.play(ShowCreation(function))
+ self.play(FadeIn(text1))
+ self.wait(1)
+ self.play(FadeOut(text1))
+ self.play(ApplyMethod(axes[0].shift,4*LEFT),ApplyMethod(function.shift,4*LEFT))
+ text2=TextMobject("For a","given","interval of $x$,").scale(0.5).shift(2.5*RIGHT+UP).set_color_by_tex_to_color_map({"given":YELLOW,"interval of $x$,":BLUE})
+ text3=TextMobject("We can get the","Fourier Series","of that","particular part!").scale(0.4).shift(2.5*RIGHT+0.5*UP).set_color_by_tex_to_color_map({"particular part!":YELLOW,"Fourier Series":RED})
+ self.play(Write(text2))
+ left,right=self.returnPairLines((4+x_each_unit)*LEFT,(4-x_each_unit)*LEFT,y_each_unit)
+ self.play(ShowCreation(left),ShowCreation(right))
+ self.play(Write(text3))
+ self.wait(0.5)
+ self.play(FadeOut(text2),FadeOut(text3))
+ self.graph_origin=3.5*RIGHT
+ self.y_axis_label="$\\frac { { l }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ \infty }{ \\frac { 2{ (-1) }^{ n }{ l }^{ 2 }cos(\\frac { n\pi x }{ l } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } }$"
+ self.setup_axes(animate=True,scalee=1)
+ axes.append(self.axes)
+ coeffResult=[
+ TextMobject("$\\frac { { 1 }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ 1 }{ \\frac { 2{ (-1) }^{ n }{ 1 }^{ 2 }cos(\\frac { n\pi x }{ 1 } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } } $").scale(0.3).shift(4.5*RIGHT+UP).set_color(YELLOW),
+ TextMobject("$\\frac { { 1 }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ 3 }{ \\frac { 2{ (-1) }^{ n }{ 1 }^{ 2 }cos(\\frac { n\pi x }{ 1 } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } } $").scale(0.3).shift(4.5*RIGHT+UP).set_color(YELLOW),
+ TextMobject("$\\frac { { 1 }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ 5 }{ \\frac { 2{ (-1) }^{ n }{ 1 }^{ 2 }cos(\\frac { n\pi x }{ 1 } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } } $").scale(0.3).shift(4.5*RIGHT+UP).set_color(YELLOW),
+ TextMobject("$\\frac { { 1 }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ 7 }{ \\frac { 2{ (-1) }^{ n }{ 1 }^{ 2 }cos(\\frac { n\pi x }{ 1 } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } } $").scale(0.3).shift(4.5*RIGHT+UP).set_color(YELLOW),
+ TextMobject("$\\frac { { 1 }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ 9 }{ \\frac { 2{ (-1) }^{ n }{ 1 }^{ 2 }cos(\\frac { n\pi x }{ 1 } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } } $").scale(0.3).shift(4.5*RIGHT+UP).set_color(YELLOW),
+ TextMobject("$\\frac { { 1 }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ 11 }{ \\frac { 2{ (-1) }^{ n }{ 1 }^{ 2 }cos(\\frac { n\pi x }{ 1 } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } }$").scale(0.3).shift(4.5*RIGHT+UP).set_color(YELLOW),
+ TextMobject("$\\frac { { 1 }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ 13 }{ \\frac { 2{ (-1) }^{ n }{ 1 }^{ 2 }cos(\\frac { n\pi x }{ 1 } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } }$").scale(0.3).shift(4.5*RIGHT+UP).set_color(YELLOW)
+ ]
+ result1a=self.returnPartResult(1,1)
+ result1b=self.returnPartResult(1,3)
+ result1c=self.returnPartResult(1,5)
+ result1d=self.returnPartResult(1,7)
+ result1e=self.returnPartResult(1,9)
+ result1f=self.returnPartResult(1,11)
+ result1g=self.returnPartResult(1,13)
+ self.play(ApplyMethod(partFunction1.shift,0.2*UP))
+ self.wait(0.5)
+
+ self.play(ReplacementTransform(partFunction1,result1a),Write(coeffResult[0]))
+ self.play(FadeOut(axes[0]),FadeOut(left),FadeOut(right),FadeOut(function))
+ self.camera_frame.save_state()
+ self.play(self.camera_frame.set_width, 5,self.camera_frame.move_to, 3.5*RIGHT)
+
+
+ self.play(ReplacementTransform(result1a,result1b),ReplacementTransform(coeffResult[0],coeffResult[1]))
+ self.play(ReplacementTransform(result1b,result1c),ReplacementTransform(coeffResult[1],coeffResult[2]))
+ self.play(ReplacementTransform(result1c,result1d),ReplacementTransform(coeffResult[2],coeffResult[3]))
+ self.play(ReplacementTransform(result1d,result1e),ReplacementTransform(coeffResult[3],coeffResult[4]))
+ self.play(ReplacementTransform(result1e,result1f),ReplacementTransform(coeffResult[4],coeffResult[5]))
+ self.play(ReplacementTransform(result1f,result1g),ReplacementTransform(coeffResult[5],coeffResult[6]))
+
+ self.wait(0.5)
+ self.play(self.camera_frame.set_width, 14,self.camera_frame.move_to, 0)
+
+ text4=TextMobject("Here the","obtained function","will always be","periodic","with period equal to the chosen interval").scale(0.4).shift(3.3*DOWN).set_color_by_tex_to_color_map({"obtained function":YELLOW,"periodic":RED})
+ self.play(Write(text4))
+
+ self.wait(0.8)
+
+ self.play(FadeOut(text4))
+ text5=TextMobject("As we","increase","the","interval of $x$,").scale(0.5).shift(3*DOWN).set_color_by_tex_to_color_map({"increase":RED,"interval of $x$,":YELLOW})
+ text6=TextMobject("We get","approximation","for","higher intervals!").scale(0.5).shift(3.5*DOWN).set_color_by_tex_to_color_map({"approximation":GREEN,"higher intervals!":YELLOW})
+ self.play(FadeIn(axes[0]),FadeIn(left),FadeIn(right),FadeIn(function))
+ self.play(Write(text5))
+ self.play(Write(text6))
+ result2=self.returnPartResult(1.5,20)
+ result3=self.returnPartResult(2,20)
+ result4=self.returnPartResult(2.5,20)
+ result5=self.returnPartResult(3,20)
+ finalCoeff=coeffResult[6]
+ coeffResult=[
+ TextMobject("$\\frac { { 1.5 }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ 20 }{ \\frac { 2{ (-1) }^{ n }{ 1.5 }^{ 2 }cos(\\frac { n\pi x }{ 2 } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } }$").scale(0.4).shift(5*RIGHT+1.5*UP).set_color(YELLOW),
+ TextMobject("$\\frac { { 2 }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ 20 }{ \\frac { 2{ (-1) }^{ n }{ 2 }^{ 2 }cos(\\frac { n\pi x }{ 2 } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } } $").scale(0.4).shift(5*RIGHT+1.5*UP).set_color(YELLOW),
+ TextMobject("$\\frac { { 2.5 }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ 20 }{ \\frac { 2{ (-1) }^{ n }{ 2.5 }^{ 2 }cos(\\frac { n\pi x }{ 2 } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } } $").scale(0.4).shift(5*RIGHT+2.2*UP).set_color(YELLOW),
+ TextMobject("$\\frac { { 3 }^{ 2 } }{ 6 } +\sum _{ n=1 }^{ 20 }{ \\frac { 2{ (-1) }^{ n }{ 3 }^{ 2 }cos(\\frac { n\pi x }{ 2 } ) }{ { \pi }^{ 2 }{ n }^{ 2 } } } $").scale(0.4).shift(5*RIGHT+2.2*UP).set_color(YELLOW),
+ ]
+ self.play(ApplyMethod(left.shift,LEFT*x_each_unit*0.5),ApplyMethod(right.shift,RIGHT*x_each_unit*0.5),ReplacementTransform(result1g,result2),ReplacementTransform(finalCoeff,coeffResult[0]))
+ self.play(ApplyMethod(left.shift,LEFT*x_each_unit*0.5),ApplyMethod(right.shift,RIGHT*x_each_unit*0.5),ReplacementTransform(result2,result3),ReplacementTransform(coeffResult[0],coeffResult[1]))
+ self.play(ApplyMethod(left.shift,LEFT*x_each_unit*0.5),ApplyMethod(right.shift,RIGHT*x_each_unit*0.5),ReplacementTransform(result3,result4),ReplacementTransform(coeffResult[1],coeffResult[2]))
+ self.play(ApplyMethod(left.shift,LEFT*x_each_unit*0.5),ApplyMethod(right.shift,RIGHT*x_each_unit*0.5),ReplacementTransform(result4,result5),ReplacementTransform(coeffResult[2],coeffResult[3]))
+
+
+
+ self.wait(2)
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/video4_FourierSeriesOfSquarePulse.py b/FSF-2020/calculus/series-and-transformations/Fourier Transform/video4_FourierSeriesOfSquarePulse.py
new file mode 100644
index 0000000..fdf4bb3
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/video4_FourierSeriesOfSquarePulse.py
@@ -0,0 +1,97 @@
+from manimlib.imports import *
+import numpy as np
+
+def returnSum(k,x):
+ summ=0
+ for i in range(1,k+1,2):
+ summ+=((np.sin(2*np.pi*i*x))/i)
+ return summ
+
+def returnFunc(self,k):
+ graph=self.get_graph(lambda x:(4/np.pi)*returnSum(k,x),color=WHITE,x_max=1,x_min=-1)
+ return graph
+
+class fourierSeries(GraphScene,MovingCameraScene):
+ CONFIG = {
+ "x_min": -3,
+ "x_max": 3,
+ "x_axis_width": 13,
+ "y_min": -3,
+ "y_max": 3,
+ "graph_origin": ORIGIN,
+ "function_color": RED,
+ "axes_color": BLUE,
+ "x_axis_label": "$x$",
+ "y_axis_label": "$y$",
+ "exclude_zero_label": True,
+ "x_labeled_nums": range(-2, 3, 1),
+ }
+ def setup(self):
+ GraphScene.setup(self)
+ MovingCameraScene.setup(self)
+ def construct(self):
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+
+ equation=TextMobject("$f(x)=\\frac { 4 }{ \pi } \sum _{ k=1,3,5.. }^{ \infty }{ \\frac { 1 }{ k } \sin { 2\pi kx } }$").shift(5*RIGHT+3*UP).set_color(RED).scale(0.5)
+ self.add(equation)
+ self.setup_axes(animate=True,scalee=1)
+ line1=Line(start=(-x_each_unit,y_each_unit,0),end=(-(1/2)*x_each_unit,y_each_unit,0),color=RED)
+ line2=Line(start=(-(1/2)*x_each_unit,y_each_unit,0),end=(-(1/2)*x_each_unit,-y_each_unit,0),color=RED)
+ line3=Line(start=(-(1/2)*x_each_unit,-y_each_unit,0),end=(0,-y_each_unit,0),color=RED)
+ line4=Line(start=(0,-y_each_unit,0),end=(0,y_each_unit,0),color=RED)
+ line5=Line(start=(0,y_each_unit,0),end=((1/2)*x_each_unit,y_each_unit,0),color=RED)
+ line6=Line(start=((1/2)*x_each_unit,y_each_unit,0),end=((1/2)*x_each_unit,-y_each_unit,0),color=RED)
+ line7=Line(start=((1/2)*x_each_unit,-y_each_unit,0),end=(x_each_unit,-y_each_unit,0),color=RED)
+ self.play(ShowCreation(line1))
+ self.play(ShowCreation(line2))
+ self.play(ShowCreation(line3))
+ self.play(ShowCreation(line4))
+ self.play(ShowCreation(line5))
+ self.play(ShowCreation(line6))
+ self.play(ShowCreation(line7))
+ self.wait(0.5)
+
+ labels=[
+ TextMobject("$f_{ k=1 }(x)$"),
+ TextMobject("$f_{ k=3 }(x)$"),
+ TextMobject("$f_{ k=5 }(x)$"),
+ TextMobject("$f_{ k=7 }(x)$"),
+ TextMobject("$f_{ k=9 }(x)$"),
+ TextMobject("$f_{ k=11 }(x)$"),
+ TextMobject("$f_{ k=13 }(x)$"),
+ TextMobject("$f_{ k=15 }(x)$"),
+ TextMobject("$f_{ k=17 }(x)$"),
+ TextMobject("$f_{ k=19 }(x)$"),
+ TextMobject("$f_{ k=85 }(x)$")
+ ]
+ p=0
+ for i in range(1,20,2):
+ if(i==1):
+ graphInitial=returnFunc(self,1)
+ label=labels[p].scale(0.5).shift(y_each_unit*1.5*UP+RIGHT*x_each_unit*0.3)
+ self.play(ShowCreation(graphInitial),Write(labels[0]))
+ old=graphInitial
+ oldLabel=label
+ else:
+ graph=returnFunc(self,i)
+ graphLabel=labels[p].scale(0.5).shift(y_each_unit*1.5*UP+RIGHT*x_each_unit*0.3)
+ self.play(ReplacementTransform(old,graph),ReplacementTransform(oldLabel,graphLabel))
+ old=graph
+ oldLabel=graphLabel
+ p+=1
+ graphFinal=returnFunc(self,85)
+ labelFinal=labels[10].scale(0.5).shift(y_each_unit*1.5*UP+RIGHT*x_each_unit*0.3)
+ self.play(FadeOut(old),FadeOut(oldLabel))
+ self.play(ShowCreation(graphFinal),Write(labelFinal))
+ self.wait(1)
+ self.camera_frame.save_state()
+ self.play(self.camera_frame.set_width, 2.25,self.camera_frame.move_to, y_each_unit*UP+RIGHT*x_each_unit*0.3)
+ circleMark=Circle(radius=0.1,color=GREEN).shift(x_each_unit*RIGHT*0.47+UP*y_each_unit*1.1)
+ text=TextMobject("Gibbs","phenomenon").set_color_by_tex_to_color_map({"Gibbs":BLUE,"phenomenon":YELLOW}).scale(0.1).shift(RIGHT*x_each_unit*0.65+UP*y_each_unit*1.1)
+ self.wait(0.7)
+ self.play(ShowCreation(circleMark))
+ self.play(Write(text))
+ self.wait(0.5)
+ self.play(self.camera_frame.set_width,14,self.camera_frame.move_to,0,FadeOut(circleMark),FadeOut(text))
+ self.wait(2)
diff --git a/FSF-2020/calculus/series-and-transformations/Fourier Transform/video5_CoinsAnalogy.py b/FSF-2020/calculus/series-and-transformations/Fourier Transform/video5_CoinsAnalogy.py
new file mode 100644
index 0000000..10ee889
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Fourier Transform/video5_CoinsAnalogy.py
@@ -0,0 +1,225 @@
+from manimlib.imports import*
+import math
+import numpy as np
+
+class coinsAnalogy(Scene):
+ def construct(self):
+ text1=TextMobject("Consider we have","Rs 39").shift(2*UP).scale(0.75).set_color_by_tex_to_color_map({"Rs 39":[YELLOW,PURPLE]})
+ text2=TextMobject("and we want to represent them only in terms of","Rs 2","and","Rs 5").shift(UP).scale(0.6).set_color_by_tex_to_color_map({"Rs 2":YELLOW,"Rs 5":PURPLE})
+ text3=TextMobject("How many","Rs 2 coins","and","Rs 5 coins","do","we need?").scale(0.8).set_color_by_tex_to_color_map({"Rs 2 coins":YELLOW,"Rs 5 coins":PURPLE,"we need?":RED})
+ text4=TextMobject("We","perform","the following!").scale(0.75).shift(DOWN).set_color_by_tex_to_color_map({"perform":GREEN})
+
+ self.play(FadeIn(text1))
+ self.wait(0.6)
+ self.play(Write(text2))
+ self.wait(0.5)
+ self.play(Write(text3))
+ self.wait(0.7)
+ self.play(FadeIn(text4))
+ self.wait(1)
+ self.play(FadeOut(text1),FadeOut(text2),FadeOut(text3),FadeOut(text4))
+
+ g1=self.group("Rs 39")
+ g1.shift(3*LEFT+0.75*UP)
+ l1=self.line()
+ l1.shift(4*LEFT)
+ f1=self.fiveGroup()
+ t1=self.twoGroup()
+ f1.shift(3.5*LEFT+0.7*DOWN)
+ andT=TextMobject("and").next_to(f1,buff=-0.1).scale(0.3)
+ t1.next_to(andT,buff=0.2)
+ equal1=TextMobject("$=$")
+ equal1.next_to(l1,buff=0.2)
+
+ self.play(ShowCreation(g1))
+ self.play(ShowCreation(l1))
+ self.play(ShowCreation(f1),Write(andT),ShowCreation(t1))
+ self.play(ShowCreation(equal1))
+ self.wait(0.6)
+
+ f2=self.fiveGroup().next_to(equal1,buff=0.4)
+ multiple1=TextMobject("$X7$","$\quad +$").next_to(f2,buff=0.2).set_color_by_tex_to_color_map({"$X7$":PURPLE})
+ l2=self.line().next_to(multiple1,buff=0.4)
+ g2=self.group("Rs 4").shift(2.75*RIGHT+0.75*UP)
+ t2=self.twoGroup().shift(2.75*RIGHT+0.7*DOWN)
+
+ self.play(ShowCreation(f2))
+ self.play(ShowCreation(multiple1))
+ self.play(ShowCreation(g2))
+ self.play(ShowCreation(l2))
+ self.play(ShowCreation(t2))
+ self.wait(1)
+
+ tempGrup=VGroup(g2,l2,t2)
+
+ t3=self.twoGroup().next_to(multiple1,buff=0.4)
+ multiple2=TextMobject("$X2$").next_to(t3,buff=0.2).set_color_by_tex_to_color_map({"$X2$":YELLOW})
+
+ self.play(ReplacementTransform(tempGrup,t3))
+ self.play(Write(multiple2))
+ self.wait(2)
+
+ def line(self):
+ l=Line(start=[0,0,0],end=[2,0,0])
+ return l
+
+ def twoGroup(self):
+ two=Circle(radius=0.25,color=BLACK,fill_color=YELLOW,fill_opacity=0.7)
+ twoText=TextMobject("Rs 2").scale(0.25).set_color(BLACK)
+ twoGrup=VGroup(two,twoText)
+ return twoGrup
+
+ def fiveGroup(self):
+ five=Circle(radius=0.35,color=BLACK,fill_color=PURPLE,fill_opacity=0.7)
+ fiveText=TextMobject("Rs 5").scale(0.3).set_color(BLACK)
+ fiveGrup=VGroup(five,fiveText)
+ return fiveGrup
+
+ def group(self,money):
+ coins=[
+ Circle(radius=0.35,color=GREY,fill_color=GREY,fill_opacity=0.75),
+ Circle(radius=0.35,color=GREY,fill_color=GREY,fill_opacity=0.8),
+ Circle(radius=0.35,color=GREY,fill_color=GREY,fill_opacity=0.7),
+ Circle(radius=0.35,color=GREY,fill_color=GREY,fill_opacity=0.75),
+ Circle(radius=0.35,color=GREY,fill_color=GREY,fill_opacity=0.8),
+ Circle(radius=0.35,color=GREY,fill_color=GREY,fill_opacity=0.7)
+ ]
+ coinsText=TextMobject(money).set_color(BLACK)
+ coinsText.scale(0.35)
+
+ coins[1].shift(0.2*RIGHT+0.2*UP)
+ coins[2].shift(0.2*RIGHT+0.1*DOWN)
+ coins[3].shift(0.2*DOWN)
+ coins[4].shift(0.2*UP+0.2*LEFT)
+ coins[5].shift(0.2*LEFT+0.1*LEFT)
+
+ coinsGrup=VGroup(coins[0],coins[1],coins[2],coins[3],coins[4],coins[5],coinsText)
+ return coinsGrup
+
+class divideFunction(GraphScene):
+ CONFIG = {
+ "x_min": -6,
+ "x_max": 6,
+ "y_min": -300,
+ "y_max": 300,
+ "x_tick_frequency": 2,
+ "y_tick_frequency": 300,
+ "graph_origin": 3*LEFT+1.5*UP+6*LEFT,
+ "function_color": RED,
+ "axes_color": BLUE,
+ "x_axis_label": "$t$",
+ "y_axis_label": "$y$",
+ "x_labeled_nums": [-6,0,6],
+ "y_labeled_nums": [-300,0,300],
+ "x_axis_width": 1.5,
+ "y_axis_height": 1
+ }
+ def line(self):
+ l=Line(start=[0,0,0],end=[2,0,0])
+ return l
+ def construct(self):
+ text1=TextMobject("Similarly,").scale(0.8).shift(UP).set_color(RED)
+ text2=TextMobject("To find the amount of","each frequency","present in","$f(x)$").scale(0.6).set_color_by_tex_to_color_map({"each frequency":[YELLOW,RED],"$f(x)$":RED})
+ text3=TextMobject("We","perform","the following!").scale(0.7).shift(DOWN).set_color_by_tex_to_color_map({"perform":GREEN})
+
+ self.play(FadeIn(text1))
+ self.wait(0.6)
+ self.play(Write(text2))
+ self.wait(0.7)
+ self.play(FadeIn(text3))
+
+ self.wait(1)
+ self.play(FadeOut(text1),FadeOut(text2),FadeOut(text3))
+
+ boxUP=Square(side_length=1.7,fill_color=BLUE_C,fill_opacity=0.5,color=BLACK).shift(3*LEFT+UP)
+ boxDOWN=Square(side_length=1.7,fill_color=BLUE_C,fill_opacity=0.5,color=BLACK).shift(3*LEFT+DOWN)
+
+ axes=[]
+ self.graph_origin=10*LEFT+1.5*UP
+ self.setup_axes(scalee=1)
+ axes.append(self.axes)
+ fx=self.get_graph(lambda x:math.pow(x,3)-math.pow(x,2)+x-2,x_min=-2*math.pi,x_max=2*math.pi,color=RED).shift(7*RIGHT+0.5*DOWN)
+
+ l=self.line().shift(4*LEFT)
+
+ self.graph_origin=10*LEFT+1.5*DOWN
+ self.y_min=-2
+ self.y_max=1
+ self.y_tick_frequency=1
+ self.y_labeled_nums=[-1,0,1]
+ self.setup_axes(scalee=1)
+ axes.append(self.axes)
+ sinx=self.get_graph(lambda x:np.sin(x),x_min=-2*math.pi,x_max=2*math.pi,color=PURPLE_C).shift(7*RIGHT+0.5*UP)
+
+ equal=TextMobject("$=$").next_to(l,buff=0.3)
+ result1=TextMobject("Amount of").scale(0.6).next_to(equal,buff=0.3)
+ boxRIGHT=Square(side_length=1.7,fill_color=GOLD_B,fill_opacity=0.5,color=BLACK).next_to(result1,buff=0.2)
+ self.graph_origin=10*LEFT
+ sinxResult=self.get_graph(lambda x:np.sin(x),color=PURPLE_C).next_to(result1,buff=0.3)
+ axes.append(self.axes)
+ result2=TextMobject("in","$f(x)$").scale(0.6).next_to(sinxResult,buff=0.2).set_color_by_tex_to_color_map({"$f(x)$":RED})
+
+ self.play(FadeIn(boxUP))
+ self.play(ShowCreation(fx))
+ self.play(ShowCreation(l))
+ self.play(FadeIn(boxDOWN))
+ self.play(ShowCreation(sinx))
+ self.wait(0.4)
+ self.play(Write(equal))
+ self.play(Write(result1))
+ self.play(FadeIn(boxRIGHT))
+ self.play(ShowCreation(sinxResult))
+ self.play(Write(result2))
+ aText1=TextMobject("and").scale(0.65).shift(4*RIGHT+2*DOWN).set_color(GREEN)
+ self.play(Write(aText1))
+ self.wait(0.7)
+
+ self.graph_origin=10*LEFT
+ cos4x=self.get_graph(lambda x:np.cos(4*x),color=PURPLE_A).shift(7*RIGHT+0.5*UP)
+ axes.append(self.axes)
+ self.graph_origin=10*LEFT
+ cos4xResult=self.get_graph(lambda x:np.cos(4*x),color=PURPLE_A).next_to(result1,buff=0.3)
+ axes.append(self.axes)
+ self.play(ReplacementTransform(sinx,cos4x),ReplacementTransform(sinxResult,cos4xResult))
+ self.wait(0.7)
+
+ soText=TextMobject("And so on..!").scale(0.65).shift(4*RIGHT+2*DOWN).set_color(GREEN)
+ self.play(ReplacementTransform(aText1,soText))
+
+ self.graph_origin=10*LEFT
+ cosx=self.get_graph(lambda x:np.cos(x),color=GREEN_E).shift(7*RIGHT+0.5*UP)
+ axes.append(self.axes)
+ self.graph_origin=10*LEFT
+ cosxResult=self.get_graph(lambda x:np.cos(x),color=GREEN_E).next_to(result1,buff=0.3)
+ axes.append(self.axes)
+ self.play(ReplacementTransform(cos4x,cosx),ReplacementTransform(cos4xResult,cosxResult))
+
+ self.graph_origin=10*LEFT
+ cos3x=self.get_graph(lambda x:np.cos(3*x),color=GREEN_C).shift(7*RIGHT+0.5*UP)
+ axes.append(self.axes)
+ self.graph_origin=10*LEFT
+ cos3xResult=self.get_graph(lambda x:np.cos(3*x),color=GREEN_C).next_to(result1,buff=0.3)
+ axes.append(self.axes)
+ self.play(ReplacementTransform(cosx,cos3x),ReplacementTransform(cosxResult,cos3xResult))
+
+ self.graph_origin=10*LEFT
+ const=self.get_graph(lambda x:1,color=YELLOW_B).shift(7*RIGHT+0.5*UP)
+ axes.append(self.axes)
+ self.graph_origin=10*LEFT
+ constResult=self.get_graph(lambda x:1,color=YELLOW_B).next_to(result1,buff=0.3)
+ axes.append(self.axes)
+ self.play(ReplacementTransform(cos3x,const),ReplacementTransform(cos3xResult,constResult))
+
+ self.wait(1)
+
+ self.play(FadeOut(soText),FadeOut(const),FadeOut(constResult),FadeOut(l),FadeOut(equal),FadeOut(result1),FadeOut(result2),FadeOut(fx),FadeOut(boxRIGHT),FadeOut(boxUP),FadeOut(boxDOWN))
+
+ finalFormula1=TexMobject(r"Therefore,",r"F(s)",r"=",r"\int _{ -\infty }^{ \infty }",r"{f(t)",r"\over",r"sines",r"\enspace and \enspace",r"cosines}",r"dt }").scale(0.7).set_color_by_tex_to_color_map({"F(s)":RED,"sines":BLUE,"cosines}":YELLOW,"{f(t)":GREEN})
+ finalFormula2=TexMobject(r"F(s)",r"=",r"\int _{ -\infty }^{ \infty }",r"{f(t)",r"\over",r"{ e }^",r"{ i\theta }}",r"dt }").set_color_by_tex_to_color_map({"F(s)":RED,"{f(t)":GREEN})
+ subFinalFormula=TextMobject("where","$\\theta =2\pi st$").scale(0.5).shift(DOWN+2*RIGHT).set_color_by_tex_to_color_map({"$\\theta =2\pi st$":RED})
+
+ self.play(Write(finalFormula1))
+ self.wait(1)
+ self.play(ReplacementTransform(finalFormula1,finalFormula2))
+ self.play(Write(subFinalFormula))
+ self.wait(2)
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/README.md b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/README.md
new file mode 100644
index 0000000..d4cd8bc
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/README.md
@@ -0,0 +1,21 @@
+### Basic Intuition
+![GIF1](gifs/basicIntuition.gif)
+
+### Solving D.E.intuition
+![GIF2](gifs/solvingDEintuition.gif)
+
+### Unit Step Function
+#### Part1
+![GIF3](gifs/unitStepFunction.gif)
+#### Part2
+![GIF4](gifs/UnitStepFunctionExample.gif)
+#### Part3
+![GIF5](gifs/LtransformUnitStepFunction.gif)
+
+### Dirac Delta Function
+#### Part1
+![GIF6](gifs/DiracFunction.gif)
+#### Part2
+![GIF7](gifs/DiracFunctionFormation.gif)
+#### Part3
+![GIF8](gifs/LtransformDiracFunction.gif)
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file1_laplaceTransformBasic.py b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file1_laplaceTransformBasic.py
new file mode 100644
index 0000000..7a37ae8
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file1_laplaceTransformBasic.py
@@ -0,0 +1,67 @@
+from manimlib.imports import *
+import pylatex
+
+class depict(Scene):
+ def construct(self):
+ square=Square(side_length=2,fill_color=GREEN,fill_opacity=0.7)
+ inputText=TextMobject("$t$")
+ squareText=TextMobject("$f$")
+ outputText=TextMobject("$f($","$t$","$)$")
+
+ inputText.scale(0.8)
+ outputText.scale(0.8)
+ inputText.shift(2.1*LEFT)
+ outputText.shift(1.5*RIGHT)
+ squareText.scale(1.2)
+
+ outputText.set_color_by_tex_to_color_map({"$t$":RED})
+
+ self.play(ShowCreation(square))
+ self.play(FadeIn(squareText))
+ self.add(inputText)
+ self.wait(0.5)
+ self.play(ApplyMethod(inputText.shift,0.9*RIGHT))
+ self.play(FadeOut(inputText),FadeIn(outputText))
+ self.play(ApplyMethod(outputText.shift,1.5*RIGHT))
+ self.wait(1)
+
+ fOutGroup=VGroup(outputText,square,squareText)
+ self.play(ApplyMethod(fOutGroup.scale,0.6))
+ self.play(ApplyMethod(fOutGroup.shift,5*LEFT))
+ self.wait(0.8)
+ laplaceSquare=Square(side_length=3,fill_color=BLUE,fill_opacity=0.6)
+ laplaceText=TextMobject("$\mathscr{L}$")
+ outText=TextMobject("$F($","$s$","$)$")
+ outText.scale(0.8)
+ outText.set_color_by_tex_to_color_map({"$s$":RED})
+ laplaceText.scale(1.5)
+ outText.shift(2*RIGHT)
+ self.play(ShowCreation(laplaceSquare))
+ self.play(FadeIn(laplaceText))
+ self.wait(0.5)
+ self.play(ApplyMethod(outputText.shift,RIGHT))
+ self.play(FadeOut(outputText),FadeIn(outText))
+ self.play(ApplyMethod(outText.shift,2*RIGHT))
+ self.wait(1)
+
+ updatedOutputText=TextMobject("$f($","$t$","$)$")
+ updatedOutputText.shift(2.5*LEFT)
+ updatedOutputText.set_color_by_tex_to_color_map({"$t$":RED})
+ updatedInputText=TextMobject("$t$")
+ updatedInputText.shift(6*LEFT)
+ updatedInputText.scale(0.7)
+ updatedOutputText.scale(0.7)
+
+ self.play(FadeIn(updatedInputText),FadeIn(updatedOutputText))
+ self.wait(0.5)
+
+ timeText=TextMobject("Time Domain")
+ frequencyText=TextMobject("Frequency Domain")
+ timeText.set_color(RED)
+ frequencyText.set_color(RED)
+ timeText.scale(0.35)
+ frequencyText.scale(0.35)
+ timeText.shift(2.5*LEFT+0.5*DOWN)
+ frequencyText.shift(4*RIGHT+0.5*DOWN)
+ self.play(Write(frequencyText),Write(timeText))
+ self.wait(2) \ No newline at end of file
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file2_differentialEqSimplification.py b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file2_differentialEqSimplification.py
new file mode 100644
index 0000000..33e9173
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file2_differentialEqSimplification.py
@@ -0,0 +1,78 @@
+from manimlib.imports import *
+import pylatex
+
+class scene(Scene):
+ def construct(self):
+ normalSq=Square(side_length=2,fill_color=BLUE,fill_opacity=0.6)
+ normalSqText=TextMobject("$\mathscr{L}$")
+ inputText=TextMobject("$f($","$y'(t)$","$)$")
+ outputText=TextMobject("$F($","$s$","$)$")
+
+ inputText.scale(0.7)
+ outputText.scale(0.7)
+ inputText.shift(2.5*LEFT)
+ outputText.shift(1.7*RIGHT)
+ normalSq.scale(1.2)
+
+ inputText.set_color_by_tex_to_color_map({"$y'(t)$":RED})
+ outputText.set_color_by_tex_to_color_map({"$s$":RED})
+
+ self.play(ShowCreation(normalSq))
+ self.play(FadeIn(normalSqText))
+ self.add(inputText)
+ self.wait(0.5)
+ self.play(ApplyMethod(inputText.shift,0.7*RIGHT))
+ self.play(FadeOut(inputText),FadeIn(outputText))
+ self.play(ApplyMethod(outputText.shift,RIGHT))
+ self.wait(1)
+
+ group1=VGroup(outputText,normalSq,normalSqText)
+ self.play(ApplyMethod(group1.scale,0.6))
+ self.play(ApplyMethod(group1.shift,4.7*LEFT))
+ self.wait(0.6)
+
+ inverseSq=Square(side_length=3,fill_color=GREEN,fill_opacity=0.6)
+ inverseSqText=TextMobject("$\mathscr{L}^{ -1 }$")
+ outText=TextMobject("$f($","$y(t)$","$)$")
+ inverseSqText.scale(0.7)
+ outText.scale(0.7)
+ outText.set_color_by_tex_to_color_map({"$y(t)$":RED})
+ self.play(ShowCreation(inverseSq))
+ self.play(FadeIn(inverseSqText))
+ self.wait(0.5)
+ outText.shift(2*RIGHT)
+ self.play(ApplyMethod(outputText.shift,RIGHT))
+ self.play(FadeOut(outputText),FadeIn(outText))
+ self.play(ApplyMethod(outText.shift,2*RIGHT))
+ self.wait(1)
+
+ updatedOutputText=TextMobject("$F($","$s$","$)$")
+ updatedOutputText.shift(2.5*LEFT)
+ updatedInputText=TextMobject("$f($","$y'(t)$","$)$")
+ updatedInputText.shift(6*LEFT)
+ updatedInputText.scale(0.7)
+ updatedOutputText.scale(0.7)
+ updatedOutputText.set_color_by_tex_to_color_map({"$s$":RED})
+ updatedInputText.set_color_by_tex_to_color_map({"$y'(t)$":RED})
+
+ self.play(FadeIn(updatedInputText),FadeIn(updatedOutputText))
+ self.wait(0.5)
+
+ deText=TextMobject("Differential Equation")
+ deinterTexta=TextMobject("Transformed D.E")
+ deinterTextb=TextMobject("(Easy to simplify)!")
+ deOutText=TextMobject("Solution of D.E")
+ deText.set_color(RED)
+ deinterTexta.set_color(RED)
+ deOutText.set_color(RED)
+ deinterTextb.set_color(PURPLE_C)
+ deText.scale(0.35)
+ deinterTexta.scale(0.35)
+ deinterTextb.scale(0.35)
+ deOutText.scale(0.35)
+ deText.shift(6*LEFT+0.5*DOWN)
+ deinterTexta.shift(2.6*LEFT+0.5*DOWN)
+ deinterTextb.shift(2.6*LEFT+0.8*DOWN)
+ deOutText.shift(4*RIGHT+0.5*DOWN)
+ self.play(Write(deText),Write(deinterTexta),Write(deinterTextb),Write(deOutText))
+ self.wait(2)
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file3_unitStepFunction.py b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file3_unitStepFunction.py
new file mode 100644
index 0000000..53c5f14
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file3_unitStepFunction.py
@@ -0,0 +1,168 @@
+from manimlib.imports import *
+import math
+import pylatex
+
+class intro(GraphScene,Scene):
+ CONFIG = {
+ "x_min": -8,
+ "x_max": 8,
+ "y_min": -5,
+ "y_max": 5,
+ "graph_origin": ORIGIN+DOWN,
+ "function_color": RED,
+ "axes_color": GREEN,
+ "x_axis_label": "$t$",
+ "y_axis_label": "$\mu_{c}(t)$",
+ "exclude_zero_label": True,
+ "y_axis_height":4,
+ "x_axis_width":7
+ }
+ def setup(self):
+ GraphScene.setup(self)
+ Scene.setup(self)
+ def construct(self):
+ introText=TextMobject("Unit","Step","Function")
+ introText.set_color_by_tex_to_color_map({"Unit":BLUE,"Step":YELLOW})
+ introText.scale(0.8)
+ self.play(Write(introText))
+ self.wait(0.5)
+ self.play(ApplyMethod(introText.shift,3*UP))
+ formulaa=TextMobject("$\mu _{ c }(t)=0\quad$","$t<c$")
+ formulab=TextMobject("$\mu _{ c }(t)=1\quad$","$t\ge c$")
+ formulaa.set_color_by_tex_to_color_map({"$t<c$":RED})
+ formulab.set_color_by_tex_to_color_map({"$t\ge c$":RED})
+ formulaa.scale(0.8)
+ formulab.scale(0.8)
+ formulab.shift(0.5*DOWN)
+ self.play(FadeIn(formulaa),FadeIn(formulab))
+ self.wait(1)
+
+ self.play(FadeOut(formulaa),FadeOut(formulab))
+
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+
+ self.setup_axes(animate=True)
+ self.wait(0.8)
+
+ c=TextMobject("c")
+ c.scale(0.5)
+ c.set_color(RED)
+ c.shift(self.graph_origin+3*x_each_unit*RIGHT+y_each_unit*0.4*DOWN)
+ self.play(Write(c))
+ smallCircle=Circle(radius=0.03,fill_color=WHITE,color=WHITE)
+ smallCircle.shift(self.graph_origin+3*x_each_unit*RIGHT)
+ downLine=Line(start=self.graph_origin,end=self.graph_origin+RIGHT*3*x_each_unit,color=BLUE)
+ upLine=Line(start=self.graph_origin+3*x_each_unit*RIGHT+y_each_unit*UP,end=self.graph_origin+8*x_each_unit*RIGHT+y_each_unit*UP,color=BLUE)
+
+ self.play(Write(downLine))
+ self.play(Write(smallCircle))
+ self.play(Write(upLine))
+ self.wait(1.5)
+ self.play(FadeOut(self.axes),FadeOut(smallCircle),FadeOut(c),FadeOut(upLine),FadeOut(downLine),FadeOut(introText))
+ self.wait(0.5)
+
+
+class example(GraphScene):
+ CONFIG = {
+ "x_min": -3,
+ "x_max": 8,
+ "y_min": -4,
+ "y_max": 5,
+ "graph_origin": ORIGIN+LEFT+DOWN,
+ "function_color": RED,
+ "axes_color": GREEN,
+ "x_axis_label": "$t$",
+ "y_axis_label": "$y$",
+ "exclude_zero_label": True,
+ "y_axis_height":4,
+ "x_axis_width":6
+ }
+ def construct(self):
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+
+ text1=TextMobject("Consider the","formation","of","following graph!"," (a part of $f(t))$")
+ text1.set_color_by_tex_to_color_map({"following graph!":BLUE,"formation":YELLOW})
+ text1.scale(0.6)
+ ft=TextMobject("$f(t)$")
+ ftminusc=TextMobject("$f(t-c)$")
+ final=TextMobject("$\mu_{c}(t)f(t-c)$")
+ ft.set_color(PURPLE_C)
+ ftminusc.set_color(PURPLE_C)
+ final.set_color(PURPLE_C)
+ c=TextMobject("c")
+ c.scale(0.5)
+ c.set_color(RED)
+ c.shift(self.graph_origin+RIGHT*x_each_unit*3+DOWN*y_each_unit*0.5)
+ ft.scale(0.5)
+ ftminusc.scale(0.5)
+ final.scale(0.5)
+
+ self.play(Write(text1))
+ self.play(ApplyMethod(text1.shift,3*UP))
+
+ self.setup_axes(animate=True)
+ y=self.get_graph(lambda x:(math.pow((x-3),3)/3)-math.pow((x-3),2)-(x-3)+3,x_min=3,x_max=7,color=RED)
+ f=self.get_graph(lambda x:(math.pow(x,3)/3)-math.pow(x,2)-x+3,x_min=-2,x_max=4,color=RED)
+ yFull=self.get_graph(lambda x:(math.pow((x-3),3)/3)-math.pow((x-3),2)-(x-3)+3,x_min=1,x_max=7,color=RED)
+
+ self.play(Write(c))
+ self.play(ShowCreation(y))
+ self.wait(1)
+ self.play(FadeOut(self.axes),FadeOut(y),FadeOut(c))
+
+ belowText1=TextMobject("Consider its","normal form",", $f(t)$")
+ belowText1.set_color_by_tex_to_color_map({"normal form":BLUE})
+ belowText2=TextMobject("Shift it to","x=c")
+ belowText2.set_color_by_tex_to_color_map({"x=c":RED})
+ belowText3a=TextMobject("Now to remove the","left part","of","$c$,")
+ belowText3a.set_color_by_tex_to_color_map({"left part":YELLOW,"$c$,":YELLOW})
+ belowText3b=TextMobject("multiply it with the","unit step function",", $\mu_{c}(t)$")
+ belowText3b.set_color_by_tex_to_color_map({"unit step function":BLUE})
+ belowText1.scale(0.4)
+ belowText2.scale(0.4)
+ belowText3a.scale(0.4)
+ belowText3b.scale(0.4)
+ belowText1.shift(2.7*DOWN+4*RIGHT)
+ belowText2.shift(2.7*DOWN+4*RIGHT)
+ belowText3a.shift(2.7*DOWN+4*RIGHT)
+ belowText3b.shift(3.1*DOWN+4*RIGHT)
+ self.setup_axes(animate=True)
+ self.play(Write(belowText1))
+ self.play(ShowCreation(f))
+ ft.shift(1.5*RIGHT+UP*0.8)
+ self.play(FadeIn(ft))
+ self.play(ReplacementTransform(belowText1,belowText2))
+ ftminusc.shift(3.5*RIGHT+UP*0.8)
+ self.play(ReplacementTransform(f,yFull),ReplacementTransform(ft,ftminusc),Write(c))
+ self.wait(1)
+
+ self.play(ReplacementTransform(belowText2,belowText3a))
+ self.play(Write(belowText3b))
+ final.shift(3.7*RIGHT+UP*0.8)
+ self.play(ReplacementTransform(ftminusc,final),ReplacementTransform(yFull,y))
+
+ finalText=TextMobject("We got our required Graph!")
+ finalText.scale(0.55)
+ finalText.shift(2.7*DOWN+4*RIGHT)
+ self.play(FadeOut(belowText3b),ReplacementTransform(belowText3a,finalText))
+ self.wait(1.5)
+
+ self.play(FadeOut(finalText),FadeOut(text1))
+
+ graphGrup=VGroup(self.axes,c,final,y)
+ self.play(ApplyMethod(graphGrup.scale,0.45))
+ box=Square(side_length=2,fill_color=BLUE,fill_opacity=0.7)
+ boxtext=TextMobject("$\mathscr{L}$")
+ boxtext.scale(0.8)
+ self.play(ApplyMethod(graphGrup.shift,5.5*LEFT+UP))
+ self.play(ShowCreation(box),Write(boxtext))
+ outText=TextMobject("${ e }^{ -cs }F(s)$")
+ outText.set_color(GREEN)
+ outText.scale(0.65)
+ outText.shift(2*RIGHT)
+ self.play(ApplyMethod(graphGrup.shift,2*RIGHT))
+ self.play(FadeOut(graphGrup),FadeIn(outText))
+ self.play(ApplyMethod(outText.shift,RIGHT))
+ self.wait(2)
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file4_diracBasic.py b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file4_diracBasic.py
new file mode 100644
index 0000000..0c7f8e4
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file4_diracBasic.py
@@ -0,0 +1,61 @@
+from manimlib.imports import *
+import math
+import pylatex
+
+class intro(GraphScene,Scene):
+ CONFIG = {
+ "x_min": -9,
+ "x_max": 9,
+ "y_min": -5,
+ "y_max": 5,
+ "graph_origin": ORIGIN+DOWN,
+ "function_color": RED,
+ "axes_color": GREEN,
+ "x_axis_label": "$x$",
+ "y_axis_label": "$\delta (x)$",
+ "y_axis_height":4,
+ "x_axis_width":7
+ }
+ def setup(self):
+ GraphScene.setup(self)
+ Scene.setup(self)
+ def construct(self):
+ introText=TextMobject("Dirac","Delta","Function")
+ introText.set_color_by_tex_to_color_map({"Dirac":BLUE,"Delta":YELLOW})
+ introText.scale(0.8)
+ self.play(Write(introText))
+ self.wait(0.5)
+ self.play(ApplyMethod(introText.shift,3*UP))
+ formulaa=TextMobject("$\delta (x)=\infty$","$x=0$")
+ formulab=TextMobject("$\delta (x)=0$","$x\\neq 0$")
+ formulaa.set_color_by_tex_to_color_map({"$x=0$":RED})
+ formulab.set_color_by_tex_to_color_map({"$x\\neq 0$":RED})
+ formulaa.scale(0.8)
+ formulab.scale(0.8)
+ formulab.shift(0.5*DOWN)
+ self.play(FadeIn(formulaa),FadeIn(formulab))
+ self.wait(1)
+
+ self.play(FadeOut(formulaa),FadeOut(formulab))
+
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+
+ self.setup_axes(animate=True)
+ self.wait(0.8)
+
+ functionUpLine=Line(start=self.graph_origin,end=self.graph_origin+UP*y_each_unit*5,color=RED)
+ functionDownLine=Line(start=self.graph_origin+UP*y_each_unit*5,end=self.graph_origin,color=RED)
+ functinLeftLine=Line(start=self.graph_origin+LEFT*x_each_unit*9,end=self.graph_origin,color=RED)
+ functionRightLine=Line(start=self.graph_origin,end=self.graph_origin+RIGHT*x_each_unit*9,color=RED)
+ functionUpLine.shift(0.02*LEFT)
+ functionRightLine.shift(0.02*RIGHT)
+
+ self.play(ShowCreation(functinLeftLine))
+ self.play(ShowCreation(functionUpLine))
+ self.play(ShowCreation(functionDownLine))
+ self.play(ShowCreation(functionRightLine))
+ self.wait(1.5)
+
+ self.play(FadeOut(self.axes),FadeOut(introText),FadeOut(functinLeftLine),FadeOut(functionRightLine),FadeOut(functionUpLine),FadeOut(functionDownLine))
+ self.wait(0.5)
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file5_formationDiracDeltaFunction.py b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file5_formationDiracDeltaFunction.py
new file mode 100644
index 0000000..565a7cb
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/file5_formationDiracDeltaFunction.py
@@ -0,0 +1,142 @@
+from manimlib.imports import *
+import math
+import pylatex
+
+def func(x,t):
+ if(x>-t and x<t):
+ return 1/(2*t)
+ else:
+ return 0
+
+
+class formation(GraphScene):
+ CONFIG = {
+ "x_min": -7,
+ "x_max": 7,
+ "y_min": -2,
+ "y_max": 2,
+ "graph_origin": ORIGIN,
+ "function_color": RED,
+ "axes_color": GREEN,
+ "x_axis_label": "$t$",
+ "y_axis_label": "$y$",
+ "y_labeled_nums":range(-2,3),
+ "y_axis_height":4,
+ "x_axis_width":7
+ }
+ def construct(self):
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+
+ text1=TextMobject("Consider the","following function's graph!")
+ text1.set_color_by_tex_to_color_map({"following function's graph!":BLUE})
+ text1.scale(0.6)
+
+ equation1=TextMobject("$\delta _{ \\tau }(t)=\\frac { 1 }{ 2\\tau } \quad$","$-\\tau <t<\\tau$")
+ equation2=TextMobject("$\delta _{ \\tau }(t)=0\quad \quad$","$t\in (-\infty ,-\\tau ]\cup [\\tau ,\infty )$")
+ equation1.scale(0.7)
+ equation2.scale(0.7)
+ equation1.shift(0.2*UP)
+ equation2.shift(0.4*DOWN+RIGHT*0.8)
+ equation1.set_color_by_tex_to_color_map({"$-\\tau <t<\\tau$":RED})
+ equation2.set_color_by_tex_to_color_map({"$t\in (-\infty ,-\\tau ]\cup [\\tau ,\infty )$":RED})
+
+ self.play(Write(text1))
+ self.play(ApplyMethod(text1.shift,3*UP))
+ self.play(Write(equation1))
+ self.play(Write(equation2))
+ self.wait(1)
+
+ self.play(FadeOut(equation1),FadeOut(equation2))
+ self.wait(0.5)
+
+ pointes1=TextMobject("$-\\tau$")
+ pointes2=TextMobject("$\\tau$")
+ pointes1.set_color(RED)
+ pointes2.set_color(RED)
+ pointes1.scale(0.65)
+ pointes2.scale(0.65)
+
+ bottomText1=TextMobject("Here","$\int _{ -\infty }^{ \infty }{ \delta _{ \\tau }(t)dt }$","=","$1$")
+ bottomText2=TextMobject("Now as","$\\tau \\rightarrow 0$")
+ bottomText3=TextMobject("We get our","Dirac Function!")
+ bottomText4=TextMobject("i.e.","$\lim _{ \\tau \\rightarrow 0 }{ \delta _{ \\tau }(t)}$","$=$","$\delta (t)$")
+ textFinal=TextMobject("Area=1")
+ bottomText1.set_color_by_tex_to_color_map({"$\int _{ -\infty }^{ \infty }{ \delta _{ \\tau }(t)dt }$":BLUE,"$1$":YELLOW})
+ textFinal.set_color(PURPLE_B)
+ bottomText2.set_color_by_tex_to_color_map({"$\\tau \\rightarrow 0$":YELLOW})
+ bottomText3.set_color_by_tex_to_color_map({"Dirac Function!":RED})
+ bottomText4.set_color_by_tex_to_color_map({"$\lim _{ \\tau \\rightarrow 0 }{ \delta _{ \\tau }(t)}$":BLUE,"$\delta (t)$":YELLOW})
+
+ bottomText1.scale(0.6)
+ bottomText2.scale(0.6)
+ bottomText3.scale(0.6)
+ bottomText4.scale(0.6)
+ textFinal.scale(0.9)
+
+ bottomText1.shift(4*RIGHT+3*DOWN)
+ bottomText2.shift(4*RIGHT+3*DOWN)
+ bottomText3.shift(4*RIGHT+3*DOWN)
+ bottomText4.shift(4*RIGHT+3*DOWN)
+ textFinal.shift(5*RIGHT+2*UP)
+
+ self.setup_axes(animate=True)
+
+ graphs=[
+ self.get_graph(lambda x:func(x,3),x_min=-7,x_max=7,color=RED),
+ self.get_graph(lambda x:func(x,2),x_min=-7,x_max=7,color=RED),
+ self.get_graph(lambda x:func(x,1),x_min=-7,x_max=7,color=RED),
+ self.get_graph(lambda x:func(x,0.5),x_min=-7,x_max=7,color=RED),
+ self.get_graph(lambda x:func(x,0.3),x_min=-7,x_max=7,color=RED),
+ self.get_graph(lambda x:func(x,0.15),x_min=-7,x_max=7,color=RED),
+ self.get_graph(lambda x:func(x,0.05),x_min=-7,x_max=7,color=RED),
+ self.get_graph(lambda x:func(x,0.01),x_min=-7,x_max=7,color=RED)
+ ]
+ pointes1.shift(self.graph_origin+3*LEFT*x_each_unit+0.4*DOWN*y_each_unit)
+ pointes2.shift(self.graph_origin+3*RIGHT*x_each_unit+0.4*DOWN*y_each_unit)
+
+ functionUpLine=Line(start=self.graph_origin,end=self.graph_origin+UP*y_each_unit*2,color=RED)
+ functionDownLine=Line(start=self.graph_origin+UP*y_each_unit*2,end=self.graph_origin,color=RED)
+ functinLeftLine=Line(start=self.graph_origin+LEFT*x_each_unit*7,end=self.graph_origin,color=RED)
+ functionRightLine=Line(start=self.graph_origin,end=self.graph_origin+RIGHT*x_each_unit*7,color=RED)
+ functionUpLine.shift(0.02*LEFT)
+ functionRightLine.shift(0.02*RIGHT)
+
+ self.play(Write(pointes1),Write(pointes2),ShowCreation(graphs[0]))
+ self.play(Write(bottomText1))
+ self.wait(0.7)
+
+ self.play(ReplacementTransform(bottomText1,bottomText2),Write(textFinal))
+ self.wait(0.5)
+ self.play(ReplacementTransform(graphs[0],graphs[1]),ApplyMethod(pointes2.shift,LEFT*x_each_unit),ApplyMethod(pointes1.shift,RIGHT*x_each_unit))
+ self.play(ReplacementTransform(graphs[1],graphs[2]),ApplyMethod(pointes2.shift,LEFT*x_each_unit),ApplyMethod(pointes1.shift,RIGHT*x_each_unit))
+ self.wait(0.5)
+ self.play(ReplacementTransform(graphs[2],graphs[3]),FadeOut(pointes1),FadeOut(pointes2))
+ self.play(ReplacementTransform(graphs[3],graphs[4]))
+ self.wait(1)
+ self.play(ReplacementTransform(bottomText2,bottomText3))
+ self.wait(1)
+ self.play(FadeOut(graphs[4]),ReplacementTransform(bottomText3,bottomText4))
+ self.wait(0.5)
+ self.play(ShowCreation(functinLeftLine))
+ self.play(ShowCreation(functionUpLine))
+ self.play(ShowCreation(functionDownLine))
+ self.play(ShowCreation(functionRightLine))
+ self.wait(2)
+
+ self.play(FadeOut(bottomText4),FadeOut(textFinal))
+ graphGrup=VGroup(self.axes,functinLeftLine,functionDownLine,functionRightLine,functionUpLine)
+ self.play(ApplyMethod(graphGrup.scale,0.5))
+ box=Square(side_length=2,fill_color=BLUE,fill_opacity=0.6)
+ boxtext=TextMobject("$\mathscr{L}$")
+ boxtext.scale(0.8)
+ self.play(ApplyMethod(graphGrup.shift,4.9*LEFT))
+ self.play(ShowCreation(box),Write(boxtext))
+ outText=TextMobject("$f(0)$")
+ outText.set_color(GREEN)
+ outText.scale(0.65)
+ outText.shift(1.5*RIGHT)
+ self.play(ApplyMethod(graphGrup.shift,2*RIGHT))
+ self.play(FadeOut(graphGrup),FadeIn(outText))
+ self.play(ApplyMethod(outText.shift,RIGHT))
+ self.wait(2) \ No newline at end of file
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/DiracFunction.gif b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/DiracFunction.gif
new file mode 100644
index 0000000..cb62ed2
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/DiracFunction.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/DiracFunctionFormation.gif b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/DiracFunctionFormation.gif
new file mode 100644
index 0000000..23acbe9
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/DiracFunctionFormation.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/LtransformDiracFunction.gif b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/LtransformDiracFunction.gif
new file mode 100644
index 0000000..b1d50b5
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/LtransformDiracFunction.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/LtransformUnitStepFunction.gif b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/LtransformUnitStepFunction.gif
new file mode 100644
index 0000000..ccbd791
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/LtransformUnitStepFunction.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/UnitStepFunctionExample.gif b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/UnitStepFunctionExample.gif
new file mode 100644
index 0000000..2b1c38f
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/UnitStepFunctionExample.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/basicIntuition.gif b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/basicIntuition.gif
new file mode 100644
index 0000000..3b974bb
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/basicIntuition.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/solvingDEintuition.gif b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/solvingDEintuition.gif
new file mode 100644
index 0000000..9883a8c
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/solvingDEintuition.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/unitStepFunction.gif b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/unitStepFunction.gif
new file mode 100644
index 0000000..16757e1
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Laplace Transformations/gifs/unitStepFunction.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/PowerSeriesQuestions.pdf b/FSF-2020/calculus/series-and-transformations/Power Series/PowerSeriesQuestions.pdf
index 04ed6d5..9fc409b 100644
--- a/FSF-2020/calculus/series-and-transformations/Power Series/PowerSeriesQuestions.pdf
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/PowerSeriesQuestions.pdf
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/README.md b/FSF-2020/calculus/series-and-transformations/Power Series/README.md
new file mode 100644
index 0000000..2fd400d
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/README.md
@@ -0,0 +1,14 @@
+#### Convergence Intuition
+![GIF1a](gifs/file1_convergence_Intuition.gif)
+
+#### Convergence Intuition
+![GIF1b](gifs/file1a_convergence_Intuition.gif)
+
+#### Convergence of a function
+![GIF2](gifs/file2_convergence_of_a_function.gif)
+
+#### Radius and IntervalOfConvergence
+![GIF3](gifs/file3_radius_and_intervalOfConvergence.gif)
+
+#### Uniform Convergence
+![GIF4](gifs/file4a_UniformConvergence.gif)
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file1_convergence_Intuition.gif b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file1_convergence_Intuition.gif
new file mode 100644
index 0000000..292d19d
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file1_convergence_Intuition.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file1a_convergence_Intuition.gif b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file1a_convergence_Intuition.gif
new file mode 100644
index 0000000..287cbd1
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file1a_convergence_Intuition.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file2_convergence_of_a_function.gif b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file2_convergence_of_a_function.gif
new file mode 100644
index 0000000..78d6014
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file2_convergence_of_a_function.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file3_radius_and_intervalOfConvergence.gif b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file3_radius_and_intervalOfConvergence.gif
new file mode 100644
index 0000000..a45c75e
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file3_radius_and_intervalOfConvergence.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file4_UniformConvergence.gif b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file4_UniformConvergence.gif
new file mode 100644
index 0000000..7b635d7
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file4_UniformConvergence.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file4a_UniformConvergence.gif b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file4a_UniformConvergence.gif
new file mode 100644
index 0000000..e284b83
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/gifs/file4a_UniformConvergence.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/script1.py b/FSF-2020/calculus/series-and-transformations/Power Series/script1.py
deleted file mode 100644
index 28eb07c..0000000
--- a/FSF-2020/calculus/series-and-transformations/Power Series/script1.py
+++ /dev/null
@@ -1,128 +0,0 @@
-from manimlib.imports import *
-
-
-def formFormula(coeff_list,variable_list):
- coeff_list=[TextMobject("${ a }_{ 0 }$"),TextMobject("${ a }_{ 1 }$"),TextMobject("${ a }_{ 2 }$")]
- variable_list=[TextMobject("+"),TextMobject("${ x }$+"),TextMobject("${ x }^{ 2 }$")]
- coeff_list[0].shift(2.2*UP+1.6*LEFT)
- for i in range(0,3):
- coeff_list[i].set_color(GOLD_A)
- variable_list[i].next_to(coeff_list[i],buff=0.1)
- if i!=2:
- coeff_list[i+1].next_to(variable_list[i],buff=0.1)
- dots=TextMobject("...")
- dots.next_to(variable_list[2])
- expansion=VGroup(coeff_list[0],coeff_list[1],coeff_list[2],variable_list[0],variable_list[1],variable_list[2],dots)
- expansion.scale(0.7)
- return expansion
-
-class pieChart(Scene):
- def construct(self):
- circle1=Circle(radius=3,color=BLUE)
- powerText=TextMobject("Power Series")
- powerText.scale(0.8)
- self.play(FadeIn(powerText))
- self.play(ShowCreation(circle1))
- self.wait(1)
-
- powerGroup=VGroup(circle1,powerText)
-
- self.play(ApplyMethod(powerGroup.scale,0.5))
- self.play(ApplyMethod(powerGroup.move_to,2.2*UP))
- self.wait(0.5)
- expansion_power_coeff=[]
- variables_power=[]
- expansion_power=formFormula(expansion_power_coeff,variables_power)
- self.play(ReplacementTransform(powerText,expansion_power))
- self.wait(1)
-
- circle2=Circle(radius=1.5)
- circle2.shift(2.2*UP)
- expansion_geo_coeff=[0]*3
- variables_geo=[0]*3
- arrow1_2=Line(start=0.7*UP,end=2.5*LEFT)
- expansion_geo_coeff=[TextMobject("${ a }_{ 0 }$"),TextMobject("${ a }_{ 1 }$"),TextMobject("${ a }_{ 2 }$")]
- for i in range(0,3):
- expansion_geo_coeff[i].set_color(GOLD_A)
- variables_geo=[TextMobject("+"),TextMobject("${ x }$+"),TextMobject("${ x }^{ 2 }$")]
- expansion_geo_coeff[0].shift(2.2*UP+1.6*LEFT)
- for i in range(0,3):
- variables_geo[i].next_to(expansion_geo_coeff[i],buff=0.1)
- if i!=2:
- expansion_geo_coeff[i+1].next_to(variables_geo[i],buff=0.1)
- dots=TextMobject("...")
- dots.next_to(variables_geo[2])
- expansion_geo=VGroup(expansion_geo_coeff[0],expansion_geo_coeff[1],expansion_geo_coeff[2],variables_geo[0],variables_geo[1],variables_geo[2],dots)
- expansion_geo.scale(0.7)
-
- self.play(ApplyMethod(circle2.shift,4*LEFT+2.5*DOWN),ApplyMethod(expansion_geo.shift,4*LEFT+2.5*DOWN))
- self.add(arrow1_2)
- self.wait(1)
-
- ones=[TextMobject("1"),TextMobject("1"),TextMobject("1")]
- for i in range(0,3):
- ones[i].set_color(GOLD_A)
- ones[0].shift(0.3*DOWN,5*LEFT)
- ones[1].next_to(ones[0],buff=0.5)
- ones[2].next_to(ones[1],buff=0.7)
- self.play(ReplacementTransform(expansion_geo_coeff[0],ones[0]),ReplacementTransform(expansion_geo_coeff[1],ones[1]),ReplacementTransform(expansion_geo_coeff[2],ones[2]))
- self.wait(1)
- expansion_geo=VGroup(ones[0],ones[1],ones[2],variables_geo[0],variables_geo[1],variables_geo[2],dots)
-
- expansion_geo_final=TextMobject("$1+x+{ x }^{ 2 }..$")
- expansion_geo_final.scale(0.8)
- expansion_geo_final.shift(0.3*DOWN+4*LEFT)
- self.play(ReplacementTransform(expansion_geo,expansion_geo_final))
- self.wait(1)
-
- circle3=Circle(radius=1.5,color=GREEN)
- circle3.shift(2.2*UP)
- expansion_taylor_coeff=[0]*3
- variables_taylor=[0]*3
- arrow1_3=Line(start=0.7*UP,end=DOWN*0.3)
- expansion_taylor_coeff=[TextMobject("${ a }_{ 0 }$"),TextMobject("${ a }_{ 1 }$"),TextMobject("${ a }_{ 2 }$")]
- for i in range(0,3):
- expansion_taylor_coeff[i].set_color(GOLD_A)
- variables_taylor=[TextMobject("+"),TextMobject("${ x }$+"),TextMobject("${ x }^{ 2 }$")]
- expansion_taylor_coeff[0].shift(2.2*UP+1.6*LEFT)
- for i in range(0,3):
- variables_taylor[i].next_to(expansion_taylor_coeff[i],buff=0.1)
- if i!=2:
- expansion_taylor_coeff[i+1].next_to(variables_taylor[i],buff=0.1)
- dots=TextMobject("...")
- dots.next_to(variables_taylor[2])
- expansion_taylor=VGroup(expansion_taylor_coeff[0],expansion_taylor_coeff[1],expansion_taylor_coeff[2],variables_taylor[0],variables_taylor[1],variables_taylor[2],dots)
- expansion_taylor.scale(0.7)
-
- self.play(ApplyMethod(circle3.shift,4*DOWN),ApplyMethod(expansion_taylor.shift,4*DOWN))
- self.add(arrow1_3)
- self.wait(1)
-
- differentials=[TextMobject("$f(0)$"),TextMobject("${ f'\left( 0 \\right) }$"),TextMobject("$\\frac { f''\left( 0 \\right) }{ 2! }$")]
- for i in range(0,3):
- differentials[i].set_color(GOLD_A)
- differentials[0].shift(1.8*DOWN+1.15*LEFT)
- differentials[1].shift(1.8*DOWN+0.45*LEFT)
- differentials[2].shift(1.8*DOWN+0.45*RIGHT)
- differentials[0].scale(0.35)
- differentials[1].scale(0.35)
- differentials[2].scale(0.35)
- self.play(ReplacementTransform(expansion_taylor_coeff[0],differentials[0]),ReplacementTransform(expansion_taylor_coeff[1],differentials[1]),ReplacementTransform(expansion_taylor_coeff[2],differentials[2]))
- self.wait(2)
- expansion_taylor_final=VGroup(differentials[0],differentials[1],differentials[2],variables_taylor[0],variables_taylor[1],variables_taylor[2],dots)
-
- self.play(FadeOut(expansion_geo_final),FadeOut(expansion_taylor_final))
- geoText=TextMobject("Geometric Series")
- geoText.scale(0.7)
- geoText.shift(4*LEFT+0.3*DOWN)
- taylorText=TextMobject("Taylor Series")
- taylorText.scale(0.7)
- taylorText.shift(1.8*DOWN)
- self.play(FadeIn(geoText),FadeIn(taylorText))
- self.wait(1)
-
- soOntext=TextMobject("So on..!")
- soOntext.shift(4*RIGHT)
- soOntext.scale(0.8)
- self.play(FadeIn(soOntext))
- self.wait(2)
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/script2.py b/FSF-2020/calculus/series-and-transformations/Power Series/video1_convergence_Intuition.py
index 72356c6..66f48f9 100644
--- a/FSF-2020/calculus/series-and-transformations/Power Series/script2.py
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/video1_convergence_Intuition.py
@@ -11,23 +11,36 @@ class convergence(Scene):
self.play(ApplyMethod(originalFormula.shift,2.7*UP))
self.wait(1)
- terms=["$a_{ 0 }$","$a_{ 1 }x$","$a_{ 2 }x^{ 2 }$","$a_{ 3 }x^{ 3 }$","$a_{ 4 }x^{ 4 }$","$a_{ 5 }x^{ 5 }$","$a_{ 6 }x^{ 6 }$","$a_{ 7 }x^{ 7 }$","$a_{ 8 }x^{ 8 }$","$a_{ 9 }x^{ 9 }$","$a_{ 10 }x^{ 10 }$","$a_{ 11 }x^{ 11 }$"]
+ colors=[PURPLE_E,PURPLE_D,MAROON_D,RED_E,RED_D,RED_C,ORANGE,YELLOW_E,YELLOW_D,YELLOW_B]
+ terms=["$a_{ 0 }$","$a_{ 1 }x$","$a_{ 2 }x^{ 2 }$","$a_{ 3 }x^{ 3 }$","$a_{ 4 }x^{ 4 }$","$a_{ 5 }x^{ 5 }$","$a_{ 6 }x^{ 6 }$","$a_{ 7 }x^{ 7 }$","$a_{ 8 }x^{ 8 }$","$a_{ 9 }x^{ 9 }$"]
termsTogetherString="+".join(terms)
- termsTogether=TextMobject(termsTogetherString+"...")
+ #termsTogether=TextMobject(termsTogetherString+"...")
+ termsTogether=TextMobject("$a_{ 0 }$","+","$a_{ 1 }x$","+","$a_{ 2 }x^{ 2 }$","+","$a_{ 3 }x^{ 3 }$","+","$a_{ 4 }x^{ 4 }$","+","$a_{ 5 }x^{ 5 }$","+","$a_{ 6 }x^{ 6 }$","+","$a_{ 7 }x^{ 7 }$","+","$a_{ 8 }x^{ 8 }$","+","$a_{ 9 }x^{ 9 }$","+..")
+ termsTogether.set_color_by_tex_to_color_map({"$a_{ 0 }$":colors[0],
+ "$a_{ 1 }x$":colors[1],
+ "$a_{ 2 }x^{ 2 }$":colors[2],
+ "$a_{ 3 }x^{ 3 }$":colors[3],
+ "$a_{ 4 }x^{ 4 }$":colors[4],
+ "$a_{ 5 }x^{ 5 }$":colors[5],
+ "$a_{ 6 }x^{ 6 }$":colors[6],
+ "$a_{ 7 }x^{ 7 }$":colors[7],
+ "$a_{ 8 }x^{ 8 }$":colors[8],
+ "$a_{ 9 }x^{ 9 }$":colors[9]})
termsTogether.scale(0.8)
termsTogether.shift(2.7*UP)
self.play(ReplacementTransform(originalFormula,termsTogether))
self.wait(1)
- termMobjectRect=[0]*12
- termMobject=TextMobject(terms[0])
+ termMobjectRect=[0]*10
+ termMobject=TextMobject(terms[0]).set_color(colors[0])
termMobject.shift(2.7*UP+6.2*LEFT)
- for i in range(1,13):
+ for i in range(1,11):
termMobjectOld=termMobject
termMobjectOld.scale(0.8)
- if(i<12):
+ if(i<10):
termMobject=TextMobject(terms[i])
- termMobject.next_to(termMobjectOld)
+ termMobject.set_color(colors[i])
+ termMobject.next_to(termMobjectOld,buff=0.5)
if(i==1):
rectDefine=TextMobject("Here","each rectangle","represents the","value of the term")
rectDefine.set_color_by_tex_to_color_map({"each rectangle":BLUE,"value of the term":YELLOW})
@@ -50,7 +63,7 @@ class convergence(Scene):
self.play(ReplacementTransform(ratio,inequality))
self.wait(1)
#self.play(ApplyMethod(termMobjectOld.move_to,(2-0.3*i)*DOWN+RIGHT*0.2*i))
- termMobjectRect[i-1]=Rectangle(height=0.1,width=(5-0.4*i))
+ termMobjectRect[i-1]=Rectangle(height=0.1,width=(4.2-0.4*i),color=colors[i-1])
termMobjectRect[i-1].move_to((2-0.2*i)*DOWN+RIGHT*0.2*i)
#rectangles[p] = termMobjectRect
#p+=1
@@ -58,8 +71,8 @@ class convergence(Scene):
uparrow=TextMobject("$\\uparrow$")
uparrow.set_color(GREEN)
- uparrow.scale(6)
- uparrow.shift(4*RIGHT+0.5*DOWN)
+ uparrow.scale(5)
+ uparrow.shift(4*RIGHT+0.7*DOWN)
self.play(ShowCreation(uparrow))
self.wait(1)
@@ -72,9 +85,9 @@ class convergence(Scene):
self.play(FadeOut(converges),FadeOut(uparrow),FadeOut(inequality))
self.wait(0.5)
- rect=VGroup(termMobjectRect[0],termMobjectRect[1],termMobjectRect[2],termMobjectRect[3],termMobjectRect[4],termMobjectRect[5],termMobjectRect[6],termMobjectRect[7],termMobjectRect[8],termMobjectRect[9],termMobjectRect[10],termMobjectRect[11])
+ rect=VGroup(termMobjectRect[0],termMobjectRect[1],termMobjectRect[2],termMobjectRect[3],termMobjectRect[4],termMobjectRect[5],termMobjectRect[6],termMobjectRect[7],termMobjectRect[8],termMobjectRect[9])
self.play(ApplyMethod(rect.scale,0.2))
- for i in range(0,12):
+ for i in range(0,10):
self.play(ApplyMethod(termMobjectRect[i].shift,i*0.04*DOWN+(11-(3-0.11*i)*i)*LEFT*0.3))
func=TextMobject("$\\approx$","$f(x)$")
func.set_color_by_tex_to_color_map({"$f(x)$":RED})
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/script3.py b/FSF-2020/calculus/series-and-transformations/Power Series/video2_convergence_of_a_function.py
index f710f42..8680792 100644
--- a/FSF-2020/calculus/series-and-transformations/Power Series/script3.py
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/video2_convergence_of_a_function.py
@@ -69,10 +69,7 @@ class graphScene(GraphScene):
eqText[i].scale(0.6)
eqText[i].set_color(BLUE)
eqText[i].shift(ORIGIN+UP*2*y_each_unit+RIGHT*3.3*x_each_unit)
- eqTextTerm=TextMobject("And so on..!")
- eqTextTerm.set_color(BLUE)
- eqTextTerm.scale(0.6)
- eqTextTerm.shift(ORIGIN+UP*2*y_each_unit+3*RIGHT*x_each_unit)
+
equation1 = self.get_graph(lambda x : 1,color = RED,x_min = -8,x_max=8)
equation2 = self.get_graph(lambda x : 1-math.pow(x,2),color = RED,x_min = -1.7,x_max=1.7)
equation3 = self.get_graph(lambda x : 1-math.pow(x,2)+math.pow(x,4),color = RED,x_min = -1.6,x_max=1.6)
@@ -106,7 +103,7 @@ class graphScene(GraphScene):
self.play(ReplacementTransform(equation3,equation4),ReplacementTransform(eqText[2],eqText[3]))
self.wait(0.3)
self.play(FadeOut(eqText[3]))
- self.play(FadeIn(eqTextTerm))
+ #self.play(FadeIn(eqTextTerm))
self.play(Write(textBtwAnim1),Write(textBtwAnim2))
self.play(FadeIn(textBtwAnim3))
self.play(ReplacementTransform(equation4,equation5))
@@ -122,7 +119,7 @@ class graphScene(GraphScene):
self.play(ReplacementTransform(equation9,equation10))
self.wait(1)
- self.play(FadeOut(textBtwAnim1),FadeOut(textBtwAnim2),FadeOut(textBtwAnim3),FadeOut(equation10),FadeOut(eqTextTerm))
+ self.play(FadeOut(textBtwAnim1),FadeOut(textBtwAnim2),FadeOut(textBtwAnim3),FadeOut(equation10))
self.wait(1)
convergeLine=Line(start=ORIGIN+x_each_unit*LEFT,end=ORIGIN+x_each_unit*RIGHT,color=WHITE)
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/script4.py b/FSF-2020/calculus/series-and-transformations/Power Series/video3_radius_and_intervalOfConvergence.py
index 412d20c..af4bdea 100644
--- a/FSF-2020/calculus/series-and-transformations/Power Series/script4.py
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/video3_radius_and_intervalOfConvergence.py
@@ -3,7 +3,7 @@ import math
class intro(Scene):
def construct(self):
- introText1=TextMobject("Consider the","above","example..")
+ introText1=TextMobject("Consider the example","above",)
introText1.scale(0.8)
introText1.set_color_by_tex_to_color_map({"above":YELLOW})
self.play(Write(introText1))
@@ -24,12 +24,13 @@ class graphScene(GraphScene,MovingCameraScene):
"x_labeled_nums": range(-1, 2, 1),
"y_labeled_nums": range(0,2,1),
"y_axis_height":7,
- "x_axis_width":7
+ "x_axis_width":7,
}
def setup(self):
GraphScene.setup(self)
MovingCameraScene.setup(self)
+
def construct(self):
x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
@@ -74,15 +75,14 @@ class graphScene(GraphScene,MovingCameraScene):
radiusText=TextMobject("Radius of convergence")
radiusText.scale(0.14)
radiusText.shift(ORIGIN+RIGHT*x_each_unit*0.45+DOWN*y_each_unit*0.2)
-
+ #self.activate_zooming(animate=True)
self.play(Write(radiusText))
self.wait(0.6)
self.camera_frame.save_state()
- self.camera_frame.set_width(5.5)
- self.play(self.camera_frame.move_to, ORIGIN)
+ self.play(self.camera_frame.set_width,5.5)
self.wait(1)
- self.camera_frame.set_width(14)
+ self.play(self.camera_frame.set_width,14)
self.wait(1.3)
self.play(FadeOut(radiusText),FadeOut(circle),FadeOut(movingPoint))
@@ -101,8 +101,8 @@ class graphScene(GraphScene,MovingCameraScene):
self.wait(0.6)
self.camera_frame.save_state()
- self.camera_frame.set_width(5.5)
- self.play(self.camera_frame.move_to, ORIGIN)
+ self.play(self.camera_frame.set_width,5.5)
self.wait(1)
- self.camera_frame.set_width(14)
- self.wait(1.5)
+ self.play(self.camera_frame.set_width,14)
+ self.wait(1.3)
+
diff --git a/FSF-2020/calculus/series-and-transformations/Power Series/script5.py b/FSF-2020/calculus/series-and-transformations/Power Series/video4_UniformConvergence.py
index e9681aa..b75da59 100644
--- a/FSF-2020/calculus/series-and-transformations/Power Series/script5.py
+++ b/FSF-2020/calculus/series-and-transformations/Power Series/video4_UniformConvergence.py
@@ -3,19 +3,15 @@ import math
class uniformlyConvergent(Scene):
def construct(self):
- introText1=TextMobject("Again consider the","above","example")
introText2=TextMobject("Let","$g(x)=\\frac { 1 }{ 1+{ x }^{ 2 } }$","and","x=0.5 $\in$(-1,1)")
introText3=TextMobject("Lets analyse..","!")
- introText1.scale(0.8)
+
introText2.scale(0.7)
introText3.scale(0.9)
introText3.shift(DOWN)
- introText1.set_color_by_tex_to_color_map({"above":YELLOW})
+
introText2.set_color_by_tex_to_color_map({"$g(x)=\\frac { 1 }{ 1+{ x }^{ 2 } }$":BLUE,"x=0.5 $\in$(-1,1)":YELLOW})
introText3.set_color_by_tex_to_color_map({"!":GREEN})
- self.play(Write(introText1))
- self.wait(0.5)
- self.play(FadeOut(introText1))
self.play(Write(introText2))
self.play(FadeIn(introText3))
self.wait(2)
@@ -45,7 +41,7 @@ def makeLines(x,numPoints,x_each_unit,y_each_unit):
lines[i]=Line(start=ORIGIN+RIGHT*x_each_unit*i+UP*y_each_unit*y,end=ORIGIN+RIGHT*x_each_unit*(i+1)+UP*y_each_unit*y_next,color=RED)
return lines
-class graphScene(GraphScene,MovingCameraScene):
+class graphScene(GraphScene,ZoomedScene):
CONFIG = {
"x_min": -6,
"x_max": 6,
@@ -58,12 +54,15 @@ class graphScene(GraphScene,MovingCameraScene):
"y_axis_label": "$f(\\frac{1}{2})_k$",
"exclude_zero_label": True,
"x_axis_width":7,
- "y_axis_height":7
+ "y_axis_height":7,
+ "zoomed_camera_frame_starting_position": 0.5*UP+0.5*RIGHT,
+ "zoom_factor": 0.4,
}
def setup(self):
GraphScene.setup(self)
- MovingCameraScene.setup(self)
+
+ ZoomedScene.setup(self)
def construct(self):
@@ -87,6 +86,14 @@ class graphScene(GraphScene,MovingCameraScene):
makeSeries(0.5,points,x_each_unit,y_each_unit)
lines=makeLines(0.5,6,x_each_unit,y_each_unit)
+ func1=TextMobject("$g(x)=\\frac { 1 }{ 1+{ x }^{ 2 } }$")
+ func2=TextMobject("x=0.5 $\in$(-1,1)")
+ func1.scale(0.4)
+ func2.scale(0.4)
+ func1.shift(5.3*LEFT+3.3*UP)
+ func2.shift(5.3*LEFT+2.9*UP)
+ self.add(func1)
+ self.add(func2)
self.add(sequence)
self.add(formula)
@@ -95,22 +102,14 @@ class graphScene(GraphScene,MovingCameraScene):
self.add(fLineText)
for p in points:
self.add(p)
+ self.setup()
+ self.activate_zooming(animate=True)
for p in range(0,5):
self.play(Write(lines[p]))
- self.wait(0.5)
- self.camera_frame.save_state()
- self.camera_frame.set_width(0.6)
- self.play(self.camera_frame.move_to, points[0])
- self.wait(0.4)
- self.play(self.camera_frame.move_to, points[1])
- self.wait(0.4)
- self.play(self.camera_frame.move_to, points[2])
- self.wait(0.3)
- self.play(self.camera_frame.move_to, points[3])
- self.wait(1)
- self.play(self.camera_frame.move_to,ORIGIN)
- self.camera_frame.set_width(14)
+
+
self.wait(1)
+ self.get_zoomed_display_pop_out_animation()
explanation1=TextMobject("Since the series","converges","to")
explanation1.set_color_by_tex_to_color_map({"converges":YELLOW})
diff --git a/FSF-2020/calculus/series-and-transformations/README.md b/FSF-2020/calculus/series-and-transformations/README.md
index 4747205..0ca6397 100644
--- a/FSF-2020/calculus/series-and-transformations/README.md
+++ b/FSF-2020/calculus/series-and-transformations/README.md
@@ -4,10 +4,9 @@ GitHub Handle: <a href="https://github.com/GSri30/">GSri30</a>
Sub-Topics Covered:
<ul>
- <li>Power Series
- <li>Taylor Series
- <li>Laplace Transformation
- <li>Fourier Transformation
- <li>z-Transform
- <li>Constant-Q transform
+ <li><a href="https://math.animations.fossee.in/contents/series-and-transformations/series/taylor-series">Taylor Series</a>
+ <li><a href="https://math.animations.fossee.in/contents/series-and-transformations/series/power-series">Power Series</a>
+ <li><a href="https://math.animations.fossee.in/contents/series-and-transformations/transformations/fourier-transform">Fourier Transformation</a>
+ <li><a href="https://math.animations.fossee.in/contents/series-and-transformations/transformations/laplace-transform">Laplace Transformation</a>
+ <li><a href="https://math.animations.fossee.in/contents/series-and-transformations/transformations/z-transform">Z-Transform</a>
</ul>
diff --git a/FSF-2020/calculus/series-and-transformations/Taylor Series/README.md b/FSF-2020/calculus/series-and-transformations/Taylor Series/README.md
new file mode 100644
index 0000000..88eb772
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Taylor Series/README.md
@@ -0,0 +1,11 @@
+#### Example of Taylors expansion
+![GIF1](gifs/file1_Example_TaylorExpansion.gif)
+
+#### Taylor Series GeneralForm
+![GIF2](gifs/file2a_TaylorExpansionGeneralForm.gif)
+
+#### Radius Of Convergence
+![GIF3](gifs/file3_radiusOfConvergence.gif)
+
+#### Divergence of a Remainder
+![GIF4](gifs/file4_DivergentRemainder.gif)
diff --git a/FSF-2020/calculus/series-and-transformations/Taylor Series/TaylorSeriesQuestions.pdf b/FSF-2020/calculus/series-and-transformations/Taylor Series/TaylorSeriesQuestions.pdf
index 2096f52..46d46e1 100644
--- a/FSF-2020/calculus/series-and-transformations/Taylor Series/TaylorSeriesQuestions.pdf
+++ b/FSF-2020/calculus/series-and-transformations/Taylor Series/TaylorSeriesQuestions.pdf
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file1_Example_TaylorExpansion.gif b/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file1_Example_TaylorExpansion.gif
new file mode 100644
index 0000000..4272d84
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file1_Example_TaylorExpansion.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file2_TaylorExpansionGeneralForm.gif b/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file2_TaylorExpansionGeneralForm.gif
new file mode 100644
index 0000000..33dfa81
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file2_TaylorExpansionGeneralForm.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file2a_TaylorExpansionGeneralForm.gif b/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file2a_TaylorExpansionGeneralForm.gif
new file mode 100644
index 0000000..33dfa81
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file2a_TaylorExpansionGeneralForm.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file3_radiusOfConvergence.gif b/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file3_radiusOfConvergence.gif
new file mode 100644
index 0000000..9e53cfb
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file3_radiusOfConvergence.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file4_DivergentRemainder.gif b/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file4_DivergentRemainder.gif
new file mode 100644
index 0000000..0bc8b65
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Taylor Series/gifs/file4_DivergentRemainder.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Taylor Series/script1.py b/FSF-2020/calculus/series-and-transformations/Taylor Series/video1_Example_TaylorExpansion.py
index e83eff8..a0c7176 100644
--- a/FSF-2020/calculus/series-and-transformations/Taylor Series/script1.py
+++ b/FSF-2020/calculus/series-and-transformations/Taylor Series/video1_Example_TaylorExpansion.py
@@ -31,7 +31,7 @@ class intro(Scene):
self.wait(0.7)
self.play(FadeOut(equation),FadeOut(text))
-class graphScene(GraphScene):
+class graphScene(GraphScene,MovingCameraScene):
CONFIG = {
"x_min": -8,
"x_max": 8,
@@ -45,10 +45,25 @@ class graphScene(GraphScene):
"exclude_zero_label": True,
"x_labeled_nums": range(-8, 8, 1),
}
+ def setup(self):
+ GraphScene.setup(self)
+ MovingCameraScene.setup(self)
def construct(self):
x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+ equation=TextMobject("$f(x)=$","${ e }^{ -x^{ 2 } }$")
+ equation.scale(0.55)
+ equation.set_color_by_tex_to_color_map({"${ e }^{ -x^{ 2 } }$":RED})
+ text=TextMobject("$a=0$")
+ text.scale(0.55)
+
+ equation.shift(3.39*UP+5*LEFT)
+ text.shift(2.9*UP+5*LEFT)
+
+ self.add(equation)
+ self.add(text)
+
generalized_eq_coeff=[]
variables_eq=[]
eq,generalized_eq_coeff=formFormula(generalized_eq_coeff,variables_eq)
@@ -58,7 +73,7 @@ class graphScene(GraphScene):
trTextGrup.scale(0.5)
trTextGrup.to_corner(UP+RIGHT)
self.play(Write(trTextGrup))
- self.setup_axes(animate=True)
+ self.setup_axes(animate=True,scalee=1)
fx=TextMobject("${ e }^{ -x^{ 2 } }$")
fx.scale(0.5)
@@ -66,18 +81,20 @@ class graphScene(GraphScene):
mainfunction=self.get_graph(lambda x:math.exp(-1*pow(x,2)),color=RED,x_min=-8,x_max=8)
self.play(ShowCreation(mainfunction))
self.play(FadeIn(fx))
- self.wait(1.4)
+ self.wait(1)
coeff=[TextMobject("$1$"),TextMobject("$f'(x)$"),TextMobject("$\\frac { f''(x) }{ 2! } $")]
coeff[0].shift(3.39*UP+4.88*RIGHT)
coeff[0].scale(0.5)
- coeff[1].shift(3.39*UP+5.3*RIGHT)
+ coeff[1].shift(3.39*UP+5.4*RIGHT)
coeff[1].scale(0.275)
- coeff[2].shift(3.39*UP+5.98*RIGHT)
+ coeff[2].shift(3.39*UP+6*RIGHT)
coeff[2].scale(0.28)
for obj in coeff:
obj.set_color(GOLD_A)
+ group=VGroup(coeff[0],coeff[1],coeff[2])
+
firstApprox=[self.get_graph(lambda x:1,color=BLUE)]
secondApprox=[self.get_graph(lambda x:1,color=BLUE),
@@ -124,16 +141,37 @@ class graphScene(GraphScene):
bottomText8.scale(0.5)
bottomText1.shift(4.5*RIGHT+2.5*DOWN)
- bottomText2.shift(4.5*RIGHT+2.5*DOWN)
- bottomText3.shift(4.5*RIGHT+2.5*DOWN)
- bottomText4.shift(4.5*RIGHT+2.5*DOWN)
- bottomText5.shift(4.5*RIGHT+2.5*DOWN)
- bottomText6.shift(4.5*RIGHT+2.5*DOWN)
- bottomText7.shift(4.5*RIGHT+2.5*DOWN)
- bottomText8.shift(4.5*RIGHT+2.5*DOWN)
+ bottomText2.shift(3*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText3.shift(3*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText4.shift(3*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText5.shift(3*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText6.shift(3.7*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText7.shift(3.7*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText8.shift(3.7*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+
+ bottomText2.scale(0.7)
+ bottomText3.scale(0.7)
+ bottomText4.scale(0.7)
+ bottomText5.scale(0.7)
+ bottomText6.scale(0.7)
+ bottomText7.scale(0.7)
+ bottomText8.scale(0.7)
self.play(Write(bottomText1))
- self.wait(1)
+ self.wait(0.8)
+ #self.activate_zooming(animate=True)
+ self.camera_frame.save_state()
+ group.move_to(4*y_each_unit*UP+4.6*RIGHT*x_each_unit).scale(0.7)
+ self.play(self.camera_frame.set_width, 8,
+ self.camera_frame.move_to, x_each_unit*UP,
+ ApplyMethod(trTextGrup.move_to,4*y_each_unit*UP+4.1*RIGHT*x_each_unit),
+ ApplyMethod(bottomText1.move_to,3.4*RIGHT*x_each_unit+2.5*DOWN*y_each_unit),
+ ApplyMethod(equation.shift,1.39*DOWN+2*RIGHT),
+ ApplyMethod(text.shift,1.39*DOWN+2*RIGHT),)
+ self.play(ApplyMethod(text.scale,0.5),ApplyMethod(equation.scale,0.5),ApplyMethod(bottomText1.scale,0.6),ApplyMethod(trTextGrup.scale,0.7))
+ self.play(ApplyMethod(text.shift,0.3*UP))
+ self.wait(0.6)
+
self.play(ShowCreation(firstApprox[0]),ReplacementTransform(bottomText1,bottomText2))
#change coeff in tn(x)
self.play(ReplacementTransform(generalized_eq_coeff[0],coeff[0]))
@@ -170,10 +208,12 @@ class graphScene(GraphScene):
self.wait(2)
textFinal=TextMobject("And so on..!")
- textFinal.scale(0.7)
- textFinal.shift(4.5*RIGHT+2.5*DOWN)
+ textFinal.scale(0.35)
+ textFinal.shift(3.7*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
self.play(ReplacementTransform(bottomText8,textFinal))
- self.wait(2.5)
+ self.wait(1)
+ self.play(FadeOut(equation),FadeOut(text))
+ self.play(self.camera_frame.set_width, 15)
finalFormula=TextMobject("Hence","$T_{ n }(x)$","=","$f(0)+f'(0)x+\\frac { f''(0) }{ 2! }x^2+..+\\frac { { f }^{ n }(0) }{ n! } { x }^{ n }$")
finalFormula.scale(0.8)
@@ -182,16 +222,7 @@ class graphScene(GraphScene):
self.play(FadeOut(self.axes),FadeOut(textFinal),FadeOut(secondGraph),FadeOut(trTextGrup),FadeOut(mainfunction),FadeOut(fx),FadeOut(coeff[0]),FadeOut(coeff[1]),FadeOut(coeff[2]))
self.play(Write(finalFormula))
self.wait(2)
- # self.play(ReplacementTransform(secondApprox[2],secondApprox[3]))
- # self.wait(0.5)
- # self.play(ReplacementTransform(secondApprox[3],secondApprox[4]))
- # self.wait(0.5)
- # self.play(ReplacementTransform(secondApprox[4],secondApprox[5]))
- # self.wait(0.5)
- # self.play(ReplacementTransform(secondApprox[0],secondApprox[0]))
- # self.wait(0.5)
- # self.play(ReplacementTransform(secondApprox[0],secondApprox[0]))
- # self.wait(0.5)
+
diff --git a/FSF-2020/calculus/series-and-transformations/Taylor Series/script2.py b/FSF-2020/calculus/series-and-transformations/Taylor Series/video2_TaylorExpansionGeneralForm.py
index b5d0a53..5be336b 100644
--- a/FSF-2020/calculus/series-and-transformations/Taylor Series/script2.py
+++ b/FSF-2020/calculus/series-and-transformations/Taylor Series/video2_TaylorExpansionGeneralForm.py
@@ -7,7 +7,7 @@ class intro(Scene):
equation=TextMobject("$f(x)=$","${ e }^{ -x^{ 2 } }$")
equation.scale(2)
equation.set_color_by_tex_to_color_map({"${ e }^{ -x^{ 2 } }$":RED})
- text=TextMobject("at $a=1$")
+ text=TextMobject("about $x=1$")
text.scale(0.7)
text.shift(DOWN)
@@ -41,7 +41,7 @@ def formFormula(coeff_list,variable_list):
return expansion,coeff_list
-class graphScene(GraphScene):
+class graphScene(GraphScene,MovingCameraScene):
CONFIG = {
"x_min": -8,
"x_max": 8,
@@ -55,10 +55,25 @@ class graphScene(GraphScene):
"exclude_zero_label": True,
"x_labeled_nums": range(-8, 8, 1),
}
+ def setup(self):
+ GraphScene.setup(self)
+ MovingCameraScene.setup(self)
def construct(self):
x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+ equation=TextMobject("$f(x)=$","${ e }^{ -x^{ 2 } }$")
+ equation.scale(0.55)
+ equation.set_color_by_tex_to_color_map({"${ e }^{ -x^{ 2 } }$":RED})
+ text=TextMobject("about $x=1$")
+ text.scale(0.55)
+ equation.shift(3.39*UP+5*LEFT)
+ text.shift(3*UP+5*LEFT)
+
+ self.add(equation)
+ self.add(text)
+
+
generalized_eq_coeff=[]
variables_eq=[]
eq,generalized_eq_coeff=formFormula(generalized_eq_coeff,variables_eq)
@@ -68,7 +83,7 @@ class graphScene(GraphScene):
trTextGrup.scale(0.5)
trTextGrup.to_corner(UP+RIGHT)
self.play(Write(trTextGrup))
- self.setup_axes(animate=True)
+ self.setup_axes(animate=True,scalee=1)
fx=TextMobject("${ e }^{ -x^{ 2 } }$")
fx.scale(0.5)
@@ -79,29 +94,29 @@ class graphScene(GraphScene):
self.wait(1.4)
coeff=[TextMobject("$e^{-1}$"),TextMobject("$f'(x)$"),TextMobject("$\\frac { f''(x) }{ 2! } $")]
- coeff[0].shift(3.33*UP+3.65*RIGHT)
- coeff[0].scale(0.45)
- coeff[1].shift(3.33*UP+4.13*RIGHT)
- coeff[1].scale(0.275)
- coeff[2].shift(3.33*UP+5.36*RIGHT)
- coeff[2].scale(0.28)
+ coeff[0].shift(4.1*y_each_unit*UP+5.15*RIGHT*x_each_unit)
+ coeff[0].scale(0.3)
+ coeff[1].shift(4*y_each_unit*UP+5.7*RIGHT*x_each_unit)
+ coeff[1].scale(0.2)
+ coeff[2].shift(4*y_each_unit*UP+7.3*RIGHT*x_each_unit)
+ coeff[2].scale(0.18)
for obj in coeff:
obj.set_color(GOLD_A)
- firstApprox=[self.get_graph(lambda x:math.exp(-1),color=BLUE,x_min=-5.5,x_max=5.5)]
- secondApprox=[self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1),color=BLUE,x_min=-5.5,x_max=5.5),
- self.get_graph(lambda x:math.exp(-1)+3*(x-1)*math.exp(-1),color=BLUE,x_min=-5.5,x_max=5.5),
- self.get_graph(lambda x:math.exp(-1)-4*(x-1)*math.exp(-1),color=BLUE,x_min=-5.5,x_max=5.5)]
- thirdApprox=[self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1)-2*math.exp(-1)*(x-1)**2,color=BLUE,x_max=5.5,x_min=-5.5),
- self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1)-0.1*math.exp(-1)*(x-1)**2,color=BLUE,x_max=5.5,x_min=-5.5),
- self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1),color=BLUE,x_max=5.5,x_min=-5.5),
- self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1)+0.5*math.exp(-1)*(x-1)**2,color=BLUE,x_max=5.5,x_min=-5.5),
- self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1)+2*math.exp(-1)*(x-1)**2,color=BLUE,x_max=5.5,x_min=-5.5)]
+ firstApprox=[self.get_graph(lambda x:math.exp(-1),color=BLUE,x_min=-3,x_max=4)]
+ secondApprox=[self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1),color=BLUE,x_min=-3,x_max=4),
+ self.get_graph(lambda x:math.exp(-1)+3*(x-1)*math.exp(-1),color=BLUE,x_min=-3,x_max=4),
+ self.get_graph(lambda x:math.exp(-1)-4*(x-1)*math.exp(-1),color=BLUE,x_min=-3,x_max=4)]
+ thirdApprox=[self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1)-2*math.exp(-1)*(x-1)**2,color=BLUE,x_max=4,x_min=-3),
+ self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1)-0.1*math.exp(-1)*(x-1)**2,color=BLUE,x_max=4,x_min=-3),
+ self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1),color=BLUE,x_max=4,x_min=-3),
+ self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1)+0.5*math.exp(-1)*(x-1)**2,color=BLUE,x_max=4,x_min=-3),
+ self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1)+2*math.exp(-1)*(x-1)**2,color=BLUE,x_max=4,x_min=-3)]
- firstGraph=self.get_graph(lambda x:math.exp(-1),color=BLUE,x_min=-5.5,x_max=5.5)
- secondGraph=self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1),color=BLUE,x_min=-5.5,x_max=5.5)
- thirdGraph=self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1)+math.exp(-1)*(x-1)**2,color=BLUE,x_max=5.5,x_min=-5.5)
+ firstGraph=self.get_graph(lambda x:math.exp(-1),color=BLUE,x_min=-3,x_max=4)
+ secondGraph=self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1),color=BLUE,x_min=-3,x_max=4)
+ thirdGraph=self.get_graph(lambda x:math.exp(-1)-2*(x-1)*math.exp(-1)+math.exp(-1)*(x-1)**2,color=BLUE,x_max=4,x_min=-3)
bottomText1=TextMobject("Apply","$f(1)=T_{n}(1)$")
bottomText2=TextMobject("This gives","$a_{ 0 }=e^{-1}$")
@@ -135,16 +150,35 @@ class graphScene(GraphScene):
bottomText8.scale(0.5)
bottomText1.shift(4.5*RIGHT+2.5*DOWN)
- bottomText2.shift(4.5*RIGHT+2.5*DOWN)
- bottomText3.shift(4.5*RIGHT+2.5*DOWN)
- bottomText4.shift(4.5*RIGHT+2.5*DOWN)
- bottomText5.shift(4.5*RIGHT+2.5*DOWN)
- bottomText6.shift(4.5*RIGHT+2.5*DOWN)
- bottomText7.shift(4.5*RIGHT+2.5*DOWN)
- bottomText8.shift(4.5*RIGHT+2.5*DOWN)
+ bottomText2.shift(5*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText3.shift(5*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText4.shift(5*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText5.shift(5*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText6.shift(5.7*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText7.shift(5.7*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+ bottomText8.shift(5.7*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
+
+ bottomText2.scale(0.7)
+ bottomText3.scale(0.7)
+ bottomText4.scale(0.7)
+ bottomText5.scale(0.7)
+ bottomText6.scale(0.7)
+ bottomText7.scale(0.7)
+ bottomText8.scale(0.7)
self.play(Write(bottomText1))
- self.wait(1)
+ self.wait(0.8)
+ self.camera_frame.save_state()
+ self.play(self.camera_frame.set_width, 8,
+ self.camera_frame.move_to, x_each_unit*UP+x_each_unit*2*RIGHT,
+ ApplyMethod(trTextGrup.move_to,4*y_each_unit*UP+6.1*RIGHT*x_each_unit),
+ ApplyMethod(bottomText1.move_to,5.4*RIGHT*x_each_unit+2.5*DOWN*y_each_unit),
+ ApplyMethod(equation.shift,1.39*DOWN+2*RIGHT+RIGHT*x_each_unit*2),
+ ApplyMethod(text.shift,1.39*DOWN+2*RIGHT+RIGHT*x_each_unit*2),)
+ self.play(ApplyMethod(text.scale,0.5),ApplyMethod(equation.scale,0.5),ApplyMethod(bottomText1.scale,0.6),ApplyMethod(trTextGrup.scale,0.7))
+ self.play(ApplyMethod(text.shift,0.25*UP))
+ self.wait(0.6)
+
self.play(ShowCreation(firstApprox[0]),ReplacementTransform(bottomText1,bottomText2))
#change coeff in tn(x)
self.play(ReplacementTransform(generalized_eq_coeff[0],coeff[0]))
@@ -154,8 +188,6 @@ class graphScene(GraphScene):
self.play(ReplacementTransform(firstApprox[0],secondApprox[1]))
self.wait(0.5)
self.play(ReplacementTransform(secondApprox[1],secondApprox[2]))
- # self.wait(0.5)
- # self.play(ReplacementTransform(secondApprox[2],secondApprox[0]))
self.wait(1)
self.play(ReplacementTransform(bottomText3,bottomText4),FadeOut(secondApprox[2]))
self.wait(1)
@@ -167,8 +199,6 @@ class graphScene(GraphScene):
self.play(ReplacementTransform(secondGraph,thirdApprox[0]))
self.wait(0.6)
self.play(ReplacementTransform(thirdApprox[0],thirdApprox[1]))
- # self.wait(0.6)
- # self.play(ReplacementTransform(thirdApprox[1],thirdApprox[2]))
self.wait(0.6)
self.play(ReplacementTransform(thirdApprox[1],thirdApprox[3]))
self.wait(0.6)
@@ -181,10 +211,13 @@ class graphScene(GraphScene):
self.wait(2)
textFinal=TextMobject("And so on..!")
- textFinal.scale(0.7)
- textFinal.shift(4.5*RIGHT+2.5*DOWN)
+ textFinal.scale(0.35)
+ textFinal.shift(5.7*RIGHT*x_each_unit+2.5*DOWN*y_each_unit)
self.play(ReplacementTransform(bottomText8,textFinal))
- self.wait(2.5)
+ self.wait(1)
+ self.play(FadeOut(equation),FadeOut(text))
+ self.play(self.camera_frame.set_width, 15,
+ self.camera_frame.move_to, 0)
finalFormula=TextMobject("Hence","$T_{ n }(x)$","=","$f(1)+f'(1)(x-1)+\\frac { f''(1) }{ 2! }(x-1)^2+..+\\frac { { f }^{ n }(1) }{ n! } { (x-1) }^{ n }$")
finalFormula.scale(0.8)
@@ -192,4 +225,4 @@ class graphScene(GraphScene):
self.play(FadeOut(self.axes),FadeOut(textFinal),FadeOut(thirdGraph),FadeOut(trTextGrup),FadeOut(mainfunction),FadeOut(fx),FadeOut(coeff[0]),FadeOut(coeff[1]),FadeOut(coeff[2]))
self.play(Write(finalFormula))
- self.wait(2) \ No newline at end of file
+ self.wait(2)
diff --git a/FSF-2020/calculus/series-and-transformations/Taylor Series/script3.py b/FSF-2020/calculus/series-and-transformations/Taylor Series/video3_radiusOfConvergence.py
index a2870d4..52f07bb 100644
--- a/FSF-2020/calculus/series-and-transformations/Taylor Series/script3.py
+++ b/FSF-2020/calculus/series-and-transformations/Taylor Series/video3_radiusOfConvergence.py
@@ -2,7 +2,7 @@ from manimlib.imports import*
import math
-class graphScene(GraphScene):
+class graphScene(GraphScene,MovingCameraScene):
CONFIG = {
"x_min": -8,
"x_max": 8,
@@ -16,12 +16,15 @@ class graphScene(GraphScene):
"exclude_zero_label": True,
"x_labeled_nums": range(-8, 8, 1),
}
+ def setup(self):
+ GraphScene.setup(self)
+ MovingCameraScene.setup(self)
def construct(self):
x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
- self.setup_axes(animate=True)
+ self.setup_axes(animate=True,scalee=1)
lnx=self.get_graph(lambda x:math.log2(x),color=RED,x_min=0.01,x_max=8)
@@ -98,14 +101,23 @@ class graphScene(GraphScene):
circle=Circle(radius=ORIGIN+x_each_unit*2,color=PURPLE_E)
circle.shift(ORIGIN+RIGHT*x_each_unit*2)
- radiusLine=Line(start=ORIGIN+x_each_unit*RIGHT*2,end=ORIGIN+x_each_unit*4*RIGHT,color=PURPLE_E)
+ radiusLine=Line(start=ORIGIN+x_each_unit*RIGHT*2,end=ORIGIN+x_each_unit*2*RIGHT+y_each_unit*3*UP,color=PURPLE_E)
radius=TextMobject("$R$")
radius.set_color(RED)
radius.scale(0.5)
- radius.shift(ORIGIN+RIGHT*x_each_unit*2.45+DOWN*y_each_unit*0.6)
+ radius.shift(ORIGIN+RIGHT*x_each_unit*2.45+UP*y_each_unit*2.2)
+ rText=TextMobject("R",":","Radius of Convergence").scale(0.3).shift(x_each_unit*RIGHT*2+UP*y_each_unit*3.3).set_color_by_tex_to_color_map({"R":RED,"Radius of Convergence":YELLOW})
self.play(FadeOut(equations[6]),Write(circle))
self.wait(0.6)
self.play(Write(radiusLine))
self.play(FadeIn(radius))
- self.wait(2) \ No newline at end of file
+ self.wait(0.7)
+ self.camera_frame.save_state()
+ self.play(self.camera_frame.set_width, 8,
+ self.camera_frame.move_to, y_each_unit*UP+x_each_unit*2*RIGHT)
+ self.play(Write(rText))
+ self.wait(1)
+ self.play(self.camera_frame.set_width, 15,
+ self.camera_frame.move_to,0)
+ self.wait(2) \ No newline at end of file
diff --git a/FSF-2020/calculus/series-and-transformations/Taylor Series/script4.py b/FSF-2020/calculus/series-and-transformations/Taylor Series/video4_DivergentRemainder.py
index 1f41c97..6b368da 100644
--- a/FSF-2020/calculus/series-and-transformations/Taylor Series/script4.py
+++ b/FSF-2020/calculus/series-and-transformations/Taylor Series/video4_DivergentRemainder.py
@@ -43,7 +43,6 @@ class graphScene(GraphScene):
bottomText1=TextMobject("$R_{n}(x)=\\frac { d }{ dx } ($","area bounded","$)$")
bottomText1.set_color_by_tex_to_color_map({"area bounded":ORANGE})
- #bottomText2.set_color_by_tex_to_color_map({"area bounded":BLUE})
arrow=TextMobject("$\downarrow$")
arrow.scale(2.5)
arrow.shift(ORIGIN+x_each_unit*RIGHT*9.5+UP*y_each_unit)
@@ -56,12 +55,8 @@ class graphScene(GraphScene):
increasingText.scale(0.4)
bottomText1.scale(0.5)
- #bottomText2.scale(0.5)
- #bottomText3.scale(0.5)
bottomText1.shift(3.5*LEFT+2*DOWN)
- #bottomText2.shift(3.5*LEFT+2.4*DOWN)
- #bottomText3.shift(3.5*LEFT+2.8*DOWN)
dline=DashedLine(start=ORIGIN+8*y_each_unit*UP,end=ORIGIN+8*y_each_unit*DOWN)
dline.shift(ORIGIN+x_each_unit*4*RIGHT)
@@ -72,11 +67,9 @@ class graphScene(GraphScene):
self.play(Write(dline))
self.wait(0.5)
self.play(ShowCreation(area1),ShowCreation(area2),Write(bottomText1))
- # self.play(Write(bottomText2))
- # self.play(FadeIn(bottomText3))
self.play(Write(arrow))
self.wait(0.7)
self.play(Write(increasingText))
self.play(FadeIn(followupText))
self.wait(2)
- \ No newline at end of file
+
diff --git a/FSF-2020/calculus/series-and-transformations/Z-Transform/README.md b/FSF-2020/calculus/series-and-transformations/Z-Transform/README.md
new file mode 100644
index 0000000..c626bdf
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Z-Transform/README.md
@@ -0,0 +1,9 @@
+#### Sampling
+![GIF1](gifs/file1.gif)
+
+#### Z Transform of a delta function
+![GIF2](gifs/file2.gif)
+
+#### Region of convergence
+![GIF3](gifs/file3.gif)
+
diff --git a/FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file1.gif b/FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file1.gif
new file mode 100644
index 0000000..d21aa59
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file1.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file2.gif b/FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file2.gif
new file mode 100644
index 0000000..203be8d
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file2.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file3.gif b/FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file3.gif
new file mode 100644
index 0000000..0f100f1
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Z-Transform/gifs/file3.gif
Binary files differ
diff --git a/FSF-2020/calculus/series-and-transformations/Z-Transform/video1_Sampling.py b/FSF-2020/calculus/series-and-transformations/Z-Transform/video1_Sampling.py
new file mode 100644
index 0000000..47615e3
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Z-Transform/video1_Sampling.py
@@ -0,0 +1,81 @@
+from manimlib.imports import *
+import math
+
+def func(x):
+ return math.pow(x,3)-2*math.pow(x,2)-x+3
+
+class graphScene(GraphScene):
+ CONFIG = {
+ "x_min": -3,
+ "x_max": 3,
+ "y_min": -4,
+ "y_max": 4,
+ "x_tick_frequency": 0.2,
+ "graph_origin": ORIGIN,
+ "function_color": RED,
+ "axes_color": BLUE,
+ "x_axis_label": "$t$",
+ "y_axis_label": "$f(t)$",
+ "exclude_zero_label": True,
+ "x_labeled_nums": range(-3, 4, 1),
+ "y_axis_height": 5,
+ "x_axis_width": 9,
+ }
+
+ def construct(self):
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+
+ fx=TextMobject("$f(t) = { t }^{ 3 }{ -2t }^{ 2 }-t+3$").set_color(RED).to_corner(UP+RIGHT).scale(0.4)
+ self.setup_axes(animate=True,scalee=1)
+ function=self.get_graph(lambda x:math.pow(x,3)-2*math.pow(x,2)-x+3,color=RED,x_min=-1,x_max=2)
+ functionArea=self.get_riemann_rectangles(function,x_min=-1,x_max=2,dx=0.01,start_color=GREEN,end_color=YELLOW,stroke_color=GREEN,fill_opacity=0.8)
+ functionDot=Dot(point=self.graph_origin,radius=0.065,color=WHITE)
+ aboveText1=TextMobject("Continuous","Time Function").shift(4*RIGHT+2*UP).scale(0.4).set_color_by_tex_to_color_map({"Continuous":YELLOW,"Time Function":BLUE})
+ aboveText2=TextMobject("Discrete","Time Function").shift(4*RIGHT+2*UP).scale(0.4).set_color_by_tex_to_color_map({"Time Function":BLUE,"Discrete":YELLOW})
+
+ bottomText1=TextMobject("Instead of considering the","function","over the","entire $t$,").shift(4.5*RIGHT+3*DOWN).scale(0.4).set_color_by_tex_to_color_map({"entire $t$,":RED,"function":YELLOW})
+ bottomText2=TextMobject("We consider only at","certain $t$").shift(4.5*RIGHT+3*DOWN).scale(0.4).set_color_by_tex_to_color_map({"certain $t$":RED})
+
+ self.play(ShowCreation(function),Write(fx),FadeIn(aboveText1))
+ self.wait(0.7)
+ self.play(Write(bottomText1))
+ self.play(ShowCreation(functionArea),MoveAlongPath(functionDot,function))
+ self.wait(0.7)
+ self.play(FadeOut(bottomText1))
+ self.play(Write(bottomText2),FadeOut(aboveText1))
+
+ dots=[Dot(radius=0.05) for i in range(10)]
+ dotShifts=[-1,-0.7,-0.4,0,0.3,0.6,1,1.3,1.6,2]
+ lines=[]
+ for x in dotShifts:
+ lines.append(Line(start=(x*x_each_unit,func(x)*y_each_unit,0),end=(x*x_each_unit,0,0),color=GREEN))
+ for i in range(10):
+ dots[i].shift(ORIGIN+RIGHT*x_each_unit*dotShifts[i]+y_each_unit*UP*func(dotShifts[i]))
+ updatedGraph=VGroup(dots[0],
+ dots[1],
+ dots[2],
+ dots[3],
+ dots[4],
+ dots[5],
+ dots[6],
+ dots[7],
+ dots[8],
+ dots[9])
+ updatedGraph1=VGroup(
+ lines[0],
+ lines[1],
+ lines[2],
+ lines[3],
+ lines[4],
+ lines[5],
+ lines[6],
+ lines[7],
+ lines[8],
+ lines[9])
+
+ self.play(FadeOut(functionDot))
+ self.play(FadeOut(function),FadeIn(updatedGraph))
+ self.play(FadeOut(functionArea),FadeIn(updatedGraph1))
+ self.play(FadeOut(bottomText2),FadeIn(aboveText2))
+ self.wait(2) \ No newline at end of file
diff --git a/FSF-2020/calculus/series-and-transformations/Z-Transform/video2_ZTransformOfDelta.py b/FSF-2020/calculus/series-and-transformations/Z-Transform/video2_ZTransformOfDelta.py
new file mode 100644
index 0000000..3063aa6
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Z-Transform/video2_ZTransformOfDelta.py
@@ -0,0 +1,121 @@
+from manimlib.imports import *
+import numpy as np
+import math
+
+class deltaTransformation(GraphScene):
+ CONFIG = {
+ "x_min": -3,
+ "x_max": 3,
+ "y_min": -5,
+ "y_max": 5,
+ "graph_origin": ORIGIN,
+ "function_color": RED,
+ "axes_color": BLUE,
+ "x_axis_label": "$t$",
+ "y_axis_label": "$f(t)$",
+ "x_labeled_nums": range(-3, 4, 1),
+ # "y_axis_height": 4,
+ # "x_axis_width": 6,
+ }
+ def construct(self):
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+ self.setup_axes(animate=True,scalee=0.8)
+ function=TextMobject("$f(t) = 2{ \delta }_{ 0 }(t)+3{ \delta }_{ 1 }(t)+4{ \delta }_{ 2 }(t)$").scale(0.4).shift(5*RIGHT+3*UP).set_color(RED)
+ self.play(FadeIn(function))
+ twoDGraph=[
+ Line(start=(0,0,0),end=(0,2*y_each_unit,0),color=GREEN),
+ Line(start=(1*x_each_unit,0,0),end=(x_each_unit,3*y_each_unit,0),color=GREEN),
+ Line(start=(2*x_each_unit,0,0),end=(2*x_each_unit,4*y_each_unit,0),color=GREEN)
+ ]
+ groupGraph=VGroup(twoDGraph[1],twoDGraph[2],self.axes,twoDGraph[0])
+ self.play(Write(twoDGraph[0]),ShowCreation(twoDGraph[1]),ShowCreation(twoDGraph[2]))
+ self.wait(1.2)
+ self.play(ApplyMethod(groupGraph.scale,0.7))
+ self.play(ApplyMethod(groupGraph.shift,5*LEFT),ApplyMethod(function.move_to,5*LEFT+3*UP))
+ self.graph_origin=2*RIGHT+2.5*DOWN
+ self.x_axis_width=6
+ self.x_axis_label="$|z|$"
+ self.y_axis_label="$|F(t)|$"
+ self.x_min=-3
+ self.x_max=6
+ self.y_min=-1
+ self.y_max=7
+ self.x_labeled_nums=range(-3,7,1)
+ self.setup_axes(animate=True,scalee=0.6)
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+ rightSideGraphs=[
+ self.get_graph(lambda x:2,x_min=0,x_max=6,color=GREEN),
+ self.get_graph(lambda x:2+3/x,x_min=0.6,x_max=6,color=GREEN),
+ self.get_graph(lambda x:2+(3/x)+(4/x**2),x_min=1.24,x_max=6,color=GREEN)
+ ]
+ graphCoeff=[
+ TextMobject("$2$").scale(0.4).shift(self.graph_origin+x_each_unit*RIGHT*2+UP*y_each_unit*2+DOWN*y_each_unit*0.5).set_color(RED),
+ TextMobject("$2+\\frac { 3 }{ |z| }$").scale(0.4).shift(self.graph_origin+x_each_unit*RIGHT*3+UP*y_each_unit*2).set_color(RED),
+ TextMobject("$2+\\frac { 3 }{ |z| } +\\frac { 4 }{ { |z| }^{ 2 } } $").scale(0.4).shift(self.graph_origin+x_each_unit*RIGHT*3.5+UP*y_each_unit*2).set_color(RED)
+ ]
+ self.play(ReplacementTransform(twoDGraph[0],rightSideGraphs[0]),FadeIn(graphCoeff[0]))
+ self.wait(0.5)
+ self.play(FadeOut(rightSideGraphs[0]),ReplacementTransform(twoDGraph[1],rightSideGraphs[1]),ReplacementTransform(graphCoeff[0],graphCoeff[1]))
+ self.wait(0.5)
+ self.play(FadeOut(rightSideGraphs[1]),ReplacementTransform(twoDGraph[2],rightSideGraphs[2]),ReplacementTransform(graphCoeff[1],graphCoeff[2]))
+
+ self.wait(2)
+
+
+class graphCont(GraphScene,MovingCameraScene):
+ CONFIG = {
+ "x_min": -3,
+ "x_max": 6,
+ "y_min": -1,
+ "y_max": 7,
+ "graph_origin": 2*RIGHT+2.5*DOWN,
+ "function_color": RED,
+ "axes_color": BLUE,
+ "x_axis_label": "$|z|$",
+ "y_axis_label": "$|F(t)|$",
+ "exclude_zero_label": True,
+ "x_labeled_nums": range(-3, 7, 1),
+ "x_axis_width": 6,
+ }
+ def setup(self):
+ GraphScene.setup(self)
+ MovingCameraScene.setup(self)
+
+ def construct(self):
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+
+ coeff=TextMobject("$2+\\frac { 3 }{ |z| } +\\frac { 4 }{ { |z| }^{ 2 } } $").scale(0.4).shift(self.graph_origin+x_each_unit*RIGHT*3.5+UP*y_each_unit*2).set_color(RED)
+ self.setup_axes(scalee=0.6)
+ graph=self.get_graph(lambda x:2+(3/x)+(4/x**2),x_min=1.24,x_max=6,color=GREEN)
+ xAxis=self.get_graph(lambda x:0,x_min=1.24,x_max=6).shift(3*LEFT)
+ self.add(graph)
+ self.add(coeff)
+ self.play(ApplyMethod((self.axes).shift,3*LEFT),ApplyMethod(coeff.shift,3*LEFT),ApplyMethod(graph.shift,3*LEFT))
+ topText=TextMobject("Here we get","output","for","any value of $|z|$").scale(0.4).shift(3*UP+3*RIGHT).set_color_by_tex_to_color_map({"output":YELLOW,"any value of $|z|$":BLUE})
+ topText1=TextMobject("Except for $|z|=0$").scale(0.7).shift(2.5*UP+3*RIGHT).set_color(RED)
+ dot1=Dot(color=WHITE,radius=0.06)
+ dot2=Dot(color=WHITE,radius=0.06)
+ self.play(Write(topText))
+ self.play(MoveAlongPath(dot1,graph),MoveAlongPath(dot2,xAxis),run_time=2)
+ self.play(Write(topText1))
+ self.play(FadeOut(dot1),FadeOut(dot2))
+ self.wait(0.5)
+ path=self.get_graph(lambda x:2+(3/x)+(4/x**2),x_min=1.24,x_max=0.8)
+ path1=self.get_graph(lambda x:0,x_min=1.24,x_max=0.8)
+ graphUpdated=self.get_graph(lambda x:2+(3/x)+(4/x**2),x_min=0.8,x_max=6,color=GREEN)
+ self.camera_frame.save_state()
+ self.play(FadeOut(graph),Write(graphUpdated))
+ self.play(self.camera_frame.set_width, 30,
+ MoveAlongPath(dot1,path),MoveAlongPath(dot2,path1),run_time=2)
+ self.wait(1)
+
+ self.play(FadeOut(dot1),FadeOut(dot2),FadeOut(graphUpdated),FadeIn(graph),self.camera_frame.set_width,15)
+ self.wait(1)
+
+
+
+
+
diff --git a/FSF-2020/calculus/series-and-transformations/Z-Transform/video3_RegionOfConvergence.py b/FSF-2020/calculus/series-and-transformations/Z-Transform/video3_RegionOfConvergence.py
new file mode 100644
index 0000000..bdfd8b3
--- /dev/null
+++ b/FSF-2020/calculus/series-and-transformations/Z-Transform/video3_RegionOfConvergence.py
@@ -0,0 +1,144 @@
+from manimlib.imports import *
+import numpy as np
+import math
+
+class graph1(GraphScene):
+ CONFIG = {
+ "x_min": -3,
+ "x_max": 5,
+ "y_min": -1,
+ "y_max": 1,
+ "graph_origin": ORIGIN,
+ "function_color": RED,
+ "axes_color": BLUE,
+ "x_axis_label": "$n$",
+ "y_axis_label": "$x(n)$",
+ "x_labeled_nums": range(-3, 6, 1),
+ "y_axis_height": 7,
+ "y_tick_frequency": 0.1,
+ }
+ def func(self,x,n):
+ summ=0
+ for i in range(n+1):
+ summ+=(1/(math.pow(x,i)))
+ return summ
+
+ def finalFunc(self,x):
+ if(x!=0):
+ return 1/(1-(1/(2*x)))
+
+
+ def construct(self):
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+ self.setup_axes(animate=True,scalee=0.8)
+ function=TextMobject("$X(t)=\sum _{ n=0 }^{ \infty }{ { (0.5) }^{ n }{ z }^{ -n } }$").scale(0.4).shift(5*RIGHT+3*UP).set_color(RED)
+ self.play(FadeIn(function))
+ twoDGraph=[]
+ for i in range(5):
+ twoDGraph.append(Line(start=(i*x_each_unit,0,0),end=(i*x_each_unit,math.pow(0.5,i)*y_each_unit,0),color=GREEN))
+
+ groupGraph=VGroup(self.axes,twoDGraph[0],twoDGraph[1],twoDGraph[2],twoDGraph[3],twoDGraph[4])
+ self.play(Write(twoDGraph[0]),ShowCreation(twoDGraph[1]),ShowCreation(twoDGraph[2]),ShowCreation(twoDGraph[3]),ShowCreation(twoDGraph[4]))
+ self.wait(1.2)
+
+ self.play(ApplyMethod(groupGraph.scale,0.7))
+ self.play(ApplyMethod(groupGraph.shift,6*LEFT),ApplyMethod(function.move_to,5*LEFT+3*UP))
+
+ someText1=TextMobject("Since it is a","summation","of","infinite terms",", it might").shift(2*RIGHT+2*UP).scale(0.5).set_color_by_tex_to_color_map({"summation":YELLOW,"infinite terms":BLUE})
+ someText2=TextMobject("Converge","or","Diverge").shift(2*RIGHT+0.5*DOWN+2*UP).scale(0.7).set_color_by_tex_to_color_map({"Converge":GREEN,"Diverge":RED})
+ someText3=TextMobject("depending upon","$|z|$").shift(2*RIGHT+UP).scale(0.5).set_color_by_tex_to_color_map({"$|z|$":YELLOW})
+ self.play(Write(someText1))
+ self.play(FadeIn(someText2))
+ self.play(Write(someText3))
+ self.wait(1)
+ self.play(FadeOut(someText1),FadeOut(someText2),FadeOut(someText3))
+
+ self.graph_origin=2*RIGHT+DOWN
+ self.x_axis_width=6
+ self.y_axis_height=5
+ self.y_tick_frequency=1
+ self.x_axis_label="$|z|$"
+ self.y_axis_label="$|X(n)|$"
+ self.x_min=-3
+ self.x_max=5
+ self.y_min=-1
+ self.y_max=5
+ self.x_labeled_nums=range(-3,6,1)
+ self.setup_axes(animate=True,scalee=0.6)
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+ rightSideGraphs=[]
+ xmins=[0,0.25,0.65,0.9,1]
+ for i in range(5):
+ rightSideGraphs.append(self.get_graph(lambda x:self.func(x,i),x_min=xmins[i],x_max=5,color=GREEN))
+ rightSideGraphs.append(self.get_graph(lambda x:1/(1-(1/(2*x))),x_min=0.63,x_max=5,color=GREEN))
+
+ graphCoeff=[
+ TextMobject("$1$").scale(0.4).shift(self.graph_origin+x_each_unit*RIGHT*2+0.65*UP*y_each_unit*2+DOWN*y_each_unit*0.5).set_color(RED),
+ TextMobject("$1+\\frac { 1 }{ 2|z| }$").scale(0.4).shift(self.graph_origin+x_each_unit*RIGHT*2+UP*y_each_unit).set_color(RED),
+ TextMobject("$1+\\frac { 1 }{ 2|z| } +\\frac { 1 }{ { 2|z| }^{ 2 } } $").scale(0.4).shift(self.graph_origin+x_each_unit*RIGHT*2+UP*y_each_unit).set_color(RED),
+ TextMobject("$1+\\frac { 1 }{ 2|z| } +\\frac { 1 }{ { (2|z|) }^{ 2 } } +\\frac { 1 }{ { (2|z|) }^{ 3 } }$").scale(0.4).shift(self.graph_origin+x_each_unit*RIGHT*2+UP*y_each_unit).set_color(RED),
+ TextMobject("$1+\\frac { 1 }{ 2|z| } +\\frac { 1 }{ { (2|z|) }^{ 2 } } +\\frac { 1 }{ { (2|z|) }^{ 3 } } +\\frac { 1 }{ (2|z|)^{ 4 } } $").scale(0.4).shift(self.graph_origin+x_each_unit*RIGHT*2+UP*y_each_unit).set_color(RED),
+ TextMobject("$\\frac { 1 }{ (1-\\frac { 1 }{ 2z } ) } $").scale(0.4).shift(self.graph_origin+x_each_unit*RIGHT*2+UP*y_each_unit).set_color(RED)
+ ]
+
+ self.play(ReplacementTransform(twoDGraph[0],rightSideGraphs[0]),FadeIn(graphCoeff[0]))
+ self.wait(0.5)
+ self.play(FadeOut(rightSideGraphs[0]),ReplacementTransform(twoDGraph[1],rightSideGraphs[1]),ReplacementTransform(graphCoeff[0],graphCoeff[1]))
+ self.wait(0.5)
+ self.play(FadeOut(rightSideGraphs[1]),ReplacementTransform(twoDGraph[2],rightSideGraphs[2]),ReplacementTransform(graphCoeff[1],graphCoeff[2]))
+ self.wait(0.5)
+ self.play(FadeOut(rightSideGraphs[2]),ReplacementTransform(twoDGraph[3],rightSideGraphs[3]),ReplacementTransform(graphCoeff[2],graphCoeff[3]))
+ self.wait(0.5)
+ self.play(FadeOut(rightSideGraphs[3]),ReplacementTransform(twoDGraph[4],rightSideGraphs[4]),ReplacementTransform(graphCoeff[3],graphCoeff[4]))
+ self.wait(0.5)
+ self.play(FadeOut(rightSideGraphs[4]),ShowCreation(rightSideGraphs[5]),ReplacementTransform(graphCoeff[4],graphCoeff[5]))
+
+ self.wait(2)
+ # #self.play(FadeOut(self.axes),FadeOut(function),FadeOut(twoDGraph[0]),FadeOut(twoDGraph[1]),FadeOut(twoDGraph[2]))
+
+
+class graphCont(GraphScene,MovingCameraScene):
+ CONFIG = {
+ "x_min": -3,
+ "x_max": 5,
+ "y_min": -1,
+ "y_max": 5,
+ "graph_origin": 2*RIGHT+DOWN,
+ "function_color": RED,
+ "axes_color": BLUE,
+ "x_axis_label": "$|z|$",
+ "y_axis_label": "$|X(n)|$",
+ "x_labeled_nums": range(-3, 6, 1),
+ "x_axis_width": 6,
+ "y_axis_height": 5
+ }
+ def setup(self):
+ GraphScene.setup(self)
+ MovingCameraScene.setup(self)
+
+ def construct(self):
+ x_each_unit = self.x_axis_width / (self.x_max - self.x_min)
+ y_each_unit = self.y_axis_height / (self.y_max - self.y_min)
+
+ coeff=TextMobject("$\\frac { 1 }{ (1-\\frac { 1 }{ 2z } ) } $").scale(0.4).shift(self.graph_origin+x_each_unit*RIGHT*2+UP*y_each_unit).set_color(RED)
+ self.setup_axes(scalee=0.6)
+ graph=self.get_graph(lambda x:1/(1-(1/(2*x))),x_min=0.63,x_max=5,color=GREEN)
+
+ self.add(graph)
+ self.add(coeff)
+
+ self.play(ApplyMethod((self.axes).shift,3*LEFT),ApplyMethod(coeff.shift,3*LEFT),ApplyMethod(graph.shift,3*LEFT))
+ self.wait(1)
+
+ dashLine=DashedLine(start=self.graph_origin+3*LEFT+0.5*x_each_unit*RIGHT,end=self.graph_origin+3*LEFT+0.5*x_each_unit*RIGHT+y_each_unit*UP*5,color=YELLOW)
+ pt=TextMobject("0.5").scale(0.3).shift(self.graph_origin+3*LEFT+0.5*x_each_unit*RIGHT+DOWN*y_each_unit*0.3)
+ self.play(Write(dashLine))
+ self.play(Write(pt))
+ self.wait(0.6)
+ rectRegion=Rectangle(height=y_each_unit*5,width=x_each_unit*5,fill_color=WHITE,fill_opacity=0.3,opacity=0.3,color=BLACK).shift(1.6*RIGHT*x_each_unit+0.5*DOWN*y_each_unit+1.5*UP)
+ self.play(ShowCreation(rectRegion))
+ text=TextMobject("Region Of Convergence!").scale(0.4).shift(4.6*RIGHT+1.5*UP).set_color(GREEN)
+ self.play(FadeIn(text))
+ self.wait(2)
diff --git a/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/README.md b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/README.md
new file mode 100644
index 0000000..832aa5d
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/README.md
@@ -0,0 +1,18 @@
+# Contributer: Archit Sangal
+My Github Account : <a href="https://github.com/architsangal">architsangal</a> (https://github.com/architsangal)
+<br/></br>
+
+## Sub-Topics Covered:
++ Gramm-Schmidt Orthogonalization Process
+
+#### Video 1: Introduction to Gram-Schmidt Orthogonalization Process
+![GIF1](file7.gif)
+
+#### Video 2: Obtaining orthogonal vectors using projections
+![GIF2](file8.gif)
+
+#### Video 3: Visual Explanation of how Gram-Schmidt Orthogonalization Process give mutually orthonormal vectors
+![GIF3](file5.gif)
+
+#### Video 4: Example of Orthonormal Vectors which are different from standard basis
+![GIF4](file6.gif) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file1_introduction.py b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file1_introduction.py
new file mode 100644
index 0000000..ccd23c9
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file1_introduction.py
@@ -0,0 +1,33 @@
+from manimlib.imports import *
+
+class Orthonormal(Scene):
+ def construct(self):
+ Centre = DOWN
+ arrow_1 = Arrow(start = Centre+ORIGIN,end = Centre+1.414*(UP+RIGHT))
+ arrow_2 = Arrow(start = Centre+ORIGIN,end = Centre+2*UP)
+ arrow_1.scale(1.35)
+ arrow_2.scale(1.35)
+ text = TextMobject("This is a set of linearly independent vectors")
+ text.scale(0.75)
+ text.move_to(3*UP+3*LEFT)
+ text.set_color(PURPLE_E)
+ arrow_1.set_color(PURPLE_E)
+ arrow_2.set_color(PURPLE_E)
+ self.play(Write(text))
+ self.play(ShowCreation(arrow_1), ShowCreation(arrow_2))
+ self.wait(2)
+ text1 = TextMobject("After we apply Gram-Schmidt Orthogonalization Process to set of linearly independent vectors")
+ text1.scale(0.6)
+ text1.move_to(3*UP+2*LEFT)
+ text1.set_color(GREEN)
+ arrow_a = Arrow(start = Centre+ORIGIN,end = Centre+0.707*(UP+RIGHT))
+ arrow_a.set_color(GREEN)
+ arrow_a.scale(2)
+ self.play(Transform(text,text1))
+ self.wait(2)
+ self.play(Transform(arrow_1,arrow_a))
+ arrow_b = Arrow(start = Centre+ORIGIN,end = Centre+0.707*(UP+LEFT))
+ arrow_b.set_color(GREEN)
+ arrow_b.scale(2)
+ self.play(Transform(arrow_2,arrow_b))
+ self.wait(2) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file2_projections.py b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file2_projections.py
new file mode 100755
index 0000000..dd4b8d4
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file2_projections.py
@@ -0,0 +1,79 @@
+from manimlib.imports import *
+
+class Projections(GraphScene):
+ CONFIG = {
+ "x_min": -6,
+ "x_max": 6,
+ "y_min": -4,
+ "y_max": 4,
+ "graph_origin" : ORIGIN ,
+ }
+ def construct(self):
+
+ self.setup_axes(animate=True)
+
+ XTD = self.x_axis_width/(self.x_max-self.x_min)
+ YTD = self.y_axis_height/(self.y_max-self.y_min)
+
+ arrow_a = Arrow(start = ORIGIN, end = 4*XTD*RIGHT)
+ arrow_a.scale(1.2)
+ arrow_a.set_color(DARK_BLUE)
+ arrow_b = Arrow(start = ORIGIN, end = 2*YTD*UP+2*XTD*RIGHT)
+ arrow_b.scale(1.3)
+ arrow_b.set_color(DARK_BLUE)
+ self.play(ShowCreation(arrow_a), ShowCreation(arrow_b))
+
+ text = TextMobject(r"Consider 2 linearly independent vectors $a$ and $b$")
+ text.set_color(DARK_BLUE)
+ text.scale(0.6)
+ text.move_to(3*YTD*UP+5*XTD*LEFT)
+ text_a = TextMobject("a")
+ text_a.move_to(0.4*YTD*DOWN+3*XTD*RIGHT)
+ text_a.set_color(DARK_BLUE)
+ text_b = TextMobject("b")
+ text_b.move_to(1.5*YTD*UP+RIGHT*XTD)
+ text_b.set_color(DARK_BLUE)
+
+ self.play(Write(text),Write(text_a), Write(text_b))
+ self.wait()
+
+ arrow_b_copy = Arrow(start = ORIGIN, end = 2*YTD*UP+2*XTD*RIGHT)
+ arrow_b_copy.scale(1.25)
+
+ arrow_p = Arrow(start = ORIGIN, end = 2*XTD*RIGHT)
+ arrow_p.scale(1.5)
+ arrow_p.set_color(GOLD_E)
+
+ text_p = TextMobject("p")
+ text_p.move_to(0.25*DOWN+RIGHT)
+ text_p.set_color(GOLD_E)
+
+ self.play(FadeOut(text), Transform(arrow_b_copy,arrow_p), FadeOut(text_a), FadeOut(text_b))
+ text = TextMobject(r"$p$ is the projection of $b$ on $a$")
+ text.set_color(GOLD_E)
+ text.move_to(3*UP+4*LEFT)
+ text.scale(0.8)
+ self.play(Write(text),Write(text_p))
+ self.wait()
+
+ self.play(FadeIn(text_a), FadeIn(text_b))
+
+ arrow_o = Arrow(start = 2*XTD*RIGHT, end = 2*YTD*UP+2*XTD*RIGHT)
+ arrow_o.scale(1.5)
+ arrow_o.set_color(GREEN_E)
+
+ text_o = TextMobject("b-p")
+ text_o.move_to(UP*YTD+2.7*XTD*RIGHT)
+ text_o.set_color(GREEN_E)
+
+ self.play(ShowCreation(arrow_o))
+ self.play(FadeOut(text),Write(text_o))
+
+ text = TextMobject(r"Observe, ($b-p$) is orthogonal to $a$")
+ text.set_color(GREEN_E)
+ text.move_to(2*DOWN+4*LEFT)
+ text.scale(0.8)
+ self.play(Write(text))
+ self.wait(2)
+
+ self.play(FadeOut(self.axes), FadeOut(arrow_a), FadeOut(arrow_b), FadeOut(arrow_b_copy), FadeOut(arrow_o), FadeOut(text_a), FadeOut(text_b), FadeOut(text_o), FadeOut(text_p), FadeOut(text)) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file3_orthonormal.py b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file3_orthonormal.py
new file mode 100644
index 0000000..a74b641
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file3_orthonormal.py
@@ -0,0 +1,335 @@
+from manimlib.imports import *
+
+class Algo(ThreeDScene):
+ def construct(self):
+
+ axes = ThreeDAxes(x_min = -5,x_max=5,y_min=-3,y_max=3,z_min=-4,z_max=4)
+ self.play(ShowCreation(axes))
+
+ text = TextMobject(r"This is the vector $\beta_1 =\left[\begin{array}{c} 4\\0\\0 \end{array}\right]$")
+ text.set_color(GREEN)
+ text.scale(0.6)
+ text.move_to(3*UP+5*LEFT)
+ self.play(Write(text))
+
+ arrow_a = Arrow(start = ORIGIN, end = 4*RIGHT)
+ arrow_a.set_color(GREEN)
+ arrow_a.scale(1.15)
+ self.play(ShowCreation(arrow_a))
+
+ text_a = TextMobject(r"$\beta_1$")
+ text_a.move_to(0.4*DOWN+3*RIGHT)
+ text_a.set_color(GREEN)
+ text_a.scale(0.75)
+ self.play(Write(text_a))
+ self.wait()
+ self.play(FadeOut(text))
+
+ text = TextMobject(r"Normalize $\beta_1$ to get $\alpha_1$")
+ text.set_color(DARK_BLUE)
+ text.scale(0.75)
+ text.move_to(3*UP+5*LEFT)
+ self.play(Write(text))
+
+ alpha_1 = Arrow(start = ORIGIN,end = RIGHT)
+ alpha_1.scale(1.9)
+ alpha_1.set_color(DARK_BLUE)
+ text_alpha_1 = TextMobject(r"$\alpha_1$")
+ text_alpha_1.move_to(0.4*DOWN+RIGHT)
+ text_alpha_1.set_color(DARK_BLUE)
+ text_alpha_1.scale(0.75)
+ self.play(Transform(text_a,text_alpha_1), Transform(arrow_a,alpha_1))
+ self.wait()
+ self.play(FadeOut(text))
+
+ text = TextMobject(r"Consider another vector $\beta_2=\left[\begin{array}{c} 2\\2\\0 \end{array}\right]$")
+ text1 = TextMobject(r"which is linearly independent to $\beta_1$")
+ text.set_color(GREEN)
+ text1.set_color(GREEN)
+ text.scale(0.6)
+ text1.scale(0.6)
+ text.move_to(3*UP+4*LEFT)
+ text1.move_to(2*UP+4*LEFT)
+ self.play(Write(text))
+ self.play(Write(text1))
+
+ arrow_b = Arrow(start = ORIGIN, end = 2*UP+2*RIGHT)
+ arrow_b.scale(1.2)
+ arrow_b.set_color(GREEN)
+ text_b = TextMobject(r"$\beta_2$")
+ text_b.move_to(1.5*UP+RIGHT)
+ text_b.set_color(GREEN)
+ text_b.scale(0.75)
+
+ self.play(ShowCreation(arrow_b), Write(text_b))
+ self.wait()
+
+ arrow_b_copy = Arrow(start = ORIGIN, end = 2*UP+2*RIGHT)
+ arrow_b_copy.scale(1.2)
+
+ arrow_p = Arrow(start = ORIGIN, end = 2*RIGHT)
+ arrow_p.scale(1.35)
+ arrow_p.set_color(GOLD_E)
+
+ text_p = TextMobject("p")
+ text_p.move_to(0.25*DOWN+RIGHT)
+ text_p.set_color(GOLD_E)
+
+ self.play(FadeOut(text), FadeOut(text1), Transform(arrow_b_copy,arrow_p), FadeOut(text_a), FadeOut(text_b))
+ text = TextMobject(r"$p$ is the projection of $\beta_2$ on $\alpha_1$")
+ text.set_color(GOLD_E)
+ text.move_to(3*UP+4*LEFT)
+ text.scale(0.8)
+ self.play(Write(text),Write(text_p))
+ self.wait()
+
+ self.play(FadeIn(text_b))
+
+ arrow_o = Arrow(start = 2*RIGHT, end = 2*UP+2*RIGHT)
+ arrow_o.scale(1.35)
+ arrow_o.set_color(PURPLE_E)
+
+ text_o = TextMobject(r"$\beta_2-p$")
+ text_o.move_to(UP+2.7*RIGHT)
+ text_o.scale(0.75)
+ text_o.set_color(PURPLE_E)
+
+ self.play(ShowCreation(arrow_o))
+ self.play(FadeOut(text),Write(text_o))
+
+ text = TextMobject(r"$\beta_2-p$ is orthogonal to p")
+ text1 = TextMobject(r"(and hence orthogonal to $\alpha_1$ also)")
+ text.set_color(PURPLE_E)
+ text1.set_color(PURPLE_E)
+ text.scale(0.7)
+ text1.scale(0.7)
+ text.move_to(3*UP+4*LEFT)
+ text1.move_to(2.5*UP+4*LEFT)
+ self.play(Write(text))
+ self.play(Write(text1))
+ self.wait(2)
+
+ self.play(FadeOut(text_p), FadeIn(arrow_a), FadeOut(text), FadeOut(text1), FadeOut(arrow_b_copy), FadeOut(arrow_p), FadeOut(text_b), FadeOut(arrow_b))
+ self.play(ApplyMethod(arrow_o.move_to,UP), ApplyMethod(text_o.move_to,RIGHT+UP))
+
+ text = TextMobject(r"Now, Normalize $\beta_2-p$")
+ text.set_color(DARK_BLUE)
+ text.scale(0.6)
+ text.move_to(3*UP+4*LEFT)
+ self.play(Write(text))
+
+ alpha_2 = Arrow(start = ORIGIN,end = UP)
+ alpha_2.scale(1.9)
+ alpha_2.set_color(DARK_BLUE)
+ text_alpha_2 = TextMobject(r"$\alpha_2$")
+ text_alpha_2.move_to(0.4*LEFT+UP)
+ text_alpha_2.set_color(DARK_BLUE)
+ text_alpha_2.scale(0.75)
+ self.play(Transform(text_o,text_alpha_2), Transform(arrow_o,alpha_2), FadeIn(text_a))
+ self.wait()
+ self.play(FadeOut(text),FadeOut(text_a),FadeOut(text_o))
+
+ self.add(axes)
+ #############################################################################
+ axis = TextMobject(r"$\alpha_1$",r"$\alpha_2$",r"$\alpha_3$",r"$\beta_3$",r"$\alpha_3$",r"$\alpha_3$",r"$\alpha_3$",r"$\alpha_3$")
+ axis.scale(0.5)
+ axis[0].move_to(0.5*RIGHT+[0,0,-0.5])
+ axis[1].move_to(0.5*UP+[0,0,-0.5])
+ axis[2].move_to(np.array([0,0,0.5]))
+ axis[3].move_to(np.array([1,1,1.5]))
+ self.add_fixed_orientation_mobjects(axis[0])
+ self.add_fixed_orientation_mobjects(axis[1])
+ #############################################################################
+
+ self.move_camera(phi=70*DEGREES,theta=30*DEGREES,run_time=3)
+ xy_plane = Polygon(5*RIGHT+3*UP,-5*RIGHT+3*UP,-5*RIGHT-3*UP,5*RIGHT-3*UP)
+ xy_plane.set_color("#333333")
+ xy_plane.set_fill("#333333")
+ xy_plane.set_opacity(1)
+ xy_plane.fade(0.7)
+ self.play(ShowCreation(xy_plane))
+
+ #self.begin_ambient_camera_rotation(rate=0.1)
+
+ line1 = Line(start = ORIGIN,end = 1*RIGHT)
+ line1.set_color(DARK_BLUE)
+ tip1 = Polygon(RIGHT,0.8*RIGHT-0.2*DOWN,0.8*RIGHT-0.2*UP)
+ tip1.set_opacity(1)
+ tip1.set_fill(DARK_BLUE)
+ tip1.set_color(DARK_BLUE)
+
+ arrow2 = Line(start = ORIGIN,end = 1*UP)
+ arrow2.set_color(DARK_BLUE)
+ tip2 = Polygon(UP,0.8*UP-0.2*RIGHT,0.8*UP-0.2*LEFT)
+ tip2.set_opacity(1)
+ tip2.set_fill(DARK_BLUE)
+ tip2.set_color(DARK_BLUE)
+ arrow2.set_color(DARK_BLUE)
+
+ self.play(ShowCreation(line1), ShowCreation(tip1), ShowCreation(arrow2), ShowCreation(tip2), FadeOut(arrow_a), FadeOut(arrow_o))
+ self.wait()
+
+ a_line = Line(start = ORIGIN,end = 2*UP+2*RIGHT+[0,0,2])
+ a_line.set_color(GOLD_E)
+ a_tip = Polygon(2*UP+2*RIGHT+[0,0,2],2*UP+1.6*RIGHT+[0,0,1.8],1.6*UP+2*RIGHT+[0,0,1.8])
+ a_tip.set_opacity(1)
+ a_tip.set_fill(GOLD_E)
+ a_tip.set_color(GOLD_E)
+
+ a_line_c1 = Line(start = ORIGIN,end = 2*UP+2*RIGHT+[0,0,2])
+ a_line_c1.set_color(GOLD_E)
+ a_tip_c1 = Polygon(2*UP+2*RIGHT+[0,0,2],2*UP+1.6*RIGHT+[0,0,1.8],1.6*UP+2*RIGHT+[0,0,1.8])
+ a_tip_c1.set_opacity(1)
+ a_tip_c1.set_fill(GOLD_E)
+ a_tip_c1.set_color(GOLD_E)
+
+ self.play(ShowCreation(a_line), ShowCreation(a_tip), ShowCreation(a_line_c1), ShowCreation(a_tip_c1))
+
+ text = TextMobject(r"Now, we have a vector $\beta_3=\left[\begin{array}{c} 2\\2\\2 \end{array}\right]$")
+ text.set_color(GOLD_E)
+ text.scale(0.7)
+ self.add_fixed_in_frame_mobjects(text)
+ self.add_fixed_orientation_mobjects(axis[3])
+ text.move_to(3*(DOWN+RIGHT))
+ self.play(Write(text))
+ self.wait()
+ self.play(FadeOut(text))
+
+ p_line1 = Line(start = ORIGIN,end = 2*RIGHT)
+ p_line1.set_color(GOLD_E)
+ p_tip1 = Polygon(2*RIGHT,1.8*RIGHT+0.2*DOWN,1.8*RIGHT+0.2*UP)
+
+ p_tip1.set_opacity(1)
+ p_tip1.set_fill(GOLD_E)
+ p_tip1.set_color(GOLD_E)
+
+ self.play(Transform(a_line_c1,p_line1),Transform(a_tip_c1,p_tip1))
+
+ text = TextMobject(r"Take projection of $\beta_3$ on $\alpha_1$")
+ text.scale(0.6)
+ text.set_color(GOLD_E)
+ self.add_fixed_in_frame_mobjects(text)
+ text.move_to(3*(DOWN+RIGHT))
+ self.play(Write(text))
+ self.begin_ambient_camera_rotation(rate=0.05)
+ self.wait()
+ self.play(FadeOut(text))
+
+ o_line1 = Line(start = 2*RIGHT,end = 2*UP+2*RIGHT+[0,0,2])
+ o_line1.set_color(GREEN_E)
+ o_tip1 = Polygon(2*UP+2*RIGHT+[0,0,2],1.8*UP+2*RIGHT+[0,0,1.8]+0.2*RIGHT,1.8*UP+2*RIGHT+[0,0,1.8]-0.2*RIGHT)
+ o_tip1.set_opacity(1)
+ o_tip1.set_fill(GREEN_E)
+ o_tip1.set_color(GREEN_E)
+
+ a_line1 = Line(start = ORIGIN,end = 2*UP+[0,0,2])
+ a_line1.set_color(GREEN_E)
+ a_tip1 = Polygon(2*UP+[0,0,2],1.8*UP+[0,0,1.8]+0.2*RIGHT,1.8*UP+[0,0,1.8]-0.2*RIGHT)
+ a_tip1.set_opacity(1)
+ a_tip1.set_fill(GREEN_E)
+ a_tip1.set_color(GREEN_E)
+
+ a_line1_c1 = Line(start = ORIGIN,end = 2*UP+[0,0,2])
+ a_line1_c1.set_color(GREEN_E)
+ a_tip1_c1 = Polygon(2*UP+[0,0,2],1.8*UP+[0,0,1.8]+0.2*RIGHT,1.8*UP+[0,0,1.8]-0.2*RIGHT)
+ a_tip1_c1.set_opacity(1)
+ a_tip1_c1.set_fill(GREEN_E)
+ a_tip1_c1.set_color(GREEN_E)
+
+ text = TextMobject(r"$\beta_3$-(projection of $\beta_3$ on $\alpha_1$)")
+ text.set_color(GREEN_E)
+ text.scale(0.6)
+ self.add_fixed_in_frame_mobjects(text)
+ text.move_to(3*(DOWN+RIGHT))
+ self.play(Write(text))
+
+ self.play(ShowCreation(o_line1), ShowCreation(o_tip1))
+ self.wait(2)
+ self.play(FadeOut(a_line_c1), FadeOut(a_tip_c1),
+ FadeOut(a_line), FadeOut(a_tip), FadeOut(axis[3]),
+ Transform(o_line1,a_line1), Transform(o_tip1,a_tip1))
+
+ self.wait()
+ self.play(FadeOut(text))
+
+ p_arrow2 = Line(start = ORIGIN,end = 2*UP)
+ p_arrow2.set_color(GOLD_E)
+ p_tip2 = Polygon(2*UP,1.8*UP+0.2*RIGHT,1.8*UP+0.2*LEFT)
+ p_tip2.set_opacity(1)
+ p_tip2.set_fill(GOLD_E)
+ p_tip2.set_color(GOLD_E)
+ p_arrow2.set_color(GOLD_E)
+
+ last_a = Line(start = 2*UP,end = [0,2,2])
+ last_a.set_color(PURPLE_E)
+ last_a_tip = Polygon([0,0,2],[0,0,1.8]+0.2*RIGHT,[0,0,1.8]+0.2*LEFT)
+ last_a_tip.move_to([0,2,2])
+ last_a_tip.set_opacity(1)
+ last_a_tip.set_fill(PURPLE_E)
+ last_a_tip.set_color(PURPLE_E)
+
+ self.wait(5)
+ text = TextMobject(r"Take projection on $\alpha_2$")
+ text.scale(0.6)
+ text.set_color(GOLD_E)
+ self.add_fixed_in_frame_mobjects(text)
+ text.move_to(3*(DOWN+RIGHT))
+ self.play(Write(text))
+ self.play(Transform(a_line1_c1,p_arrow2),Transform(a_tip1_c1,p_tip2))
+ self.wait()
+ self.play(FadeOut(text))
+
+ text = TextMobject(r"$\beta_3$-(projection of $\beta_3$ on $\alpha_1$ + projection of $\beta_3$ on $\alpha_2$)")
+ text.set_color(PURPLE_E)
+ text.scale(0.6)
+ self.add_fixed_in_frame_mobjects(text)
+ text.move_to(3*DOWN+3.5*RIGHT)
+ self.play(Write(text))
+ #self.play(ShowCreation(o_line1), ShowCreation(o_tip1))
+ self.wait(2)
+ self.play(ShowCreation(last_a_tip), ShowCreation(last_a))
+ self.wait()
+ self.play(FadeOut(text))
+
+ larrow3 = Line(start = ORIGIN,end = [0,0,2])
+ larrow3.set_color(PURPLE_E)
+ ltip3 = Polygon([0,0,2],[0,0,1.8]+0.2*RIGHT,[0,0,1.8]+0.2*LEFT)
+ ltip3.set_opacity(1)
+ ltip3.set_fill(PURPLE_E)
+ ltip3.set_color(PURPLE_E)
+ self.wait()
+ self.play(FadeOut(o_line1), FadeOut(o_tip1), FadeOut(a_line1_c1), FadeOut(a_tip1_c1), Transform(last_a,larrow3), Transform(last_a_tip,ltip3))
+
+ text = TextMobject(r"Normalize, the vector")
+ text1 = TextMobject(r"$\beta_3$-(projection of $\beta_3$ on $\alpha_1$ + projection of $\beta_3$ on $\alpha_2)$")
+ text.set_color(PURPLE_E)
+ text1.set_color(PURPLE_E)
+ text.scale(0.55)
+ text1.scale(0.55)
+ self.add_fixed_in_frame_mobjects(text)
+ text.move_to(3*DOWN+3*RIGHT)
+ text1.move_to(3.5*DOWN+3.25*RIGHT)
+ self.play(Write(text))
+ self.add_fixed_in_frame_mobjects(text1)
+ self.play(Write(text1))
+
+ arrow3 = Line(start = ORIGIN,end = [0,0,1])
+ arrow3.set_color(DARK_BLUE)
+ tip3 = Polygon([0,0,1],[0,0,0.8]-0.2*RIGHT,[0,0,0.8]-0.2*LEFT)
+ tip3.set_opacity(1)
+ tip3.set_fill(DARK_BLUE)
+ tip3.set_color(DARK_BLUE)
+ self.play(Transform(last_a,arrow3), Transform(last_a_tip,tip3))
+ self.add_fixed_orientation_mobjects(axis[2])
+
+ self.wait()
+ self.play(FadeOut(text),FadeOut(text1))
+
+ text = TextMobject(r"These are the three orthonormal vectors $\alpha_1, \alpha_2, \alpha_3$")
+ text.set_color(DARK_BLUE)
+ self.add_fixed_in_frame_mobjects(text)
+ text.scale(0.6)
+ text.move_to(3*DOWN+3.5*RIGHT)
+ self.play(Write(text))
+
+ self.wait(8)
diff --git a/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file4_Non_Standard_Basis.py b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file4_Non_Standard_Basis.py
new file mode 100644
index 0000000..1d23aa2
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file4_Non_Standard_Basis.py
@@ -0,0 +1,69 @@
+from manimlib.imports import *
+
+class NSB(ThreeDScene):
+ def construct(self):
+
+ line1 = Line(start = ORIGIN,end = 1*RIGHT)
+ line1.set_color(DARK_BLUE)
+ tip1 = Polygon(RIGHT,0.9*RIGHT-0.1*DOWN,0.9*RIGHT-0.1*UP)
+ tip1.set_opacity(1)
+ tip1.set_fill(DARK_BLUE)
+ tip1.set_color(DARK_BLUE)
+
+ arrow2 = Line(start = ORIGIN,end = 1*UP)
+ arrow2.set_color(DARK_BLUE)
+ tip2 = Polygon(UP,0.9*UP-0.1*RIGHT,0.9*UP-0.1*LEFT)
+ tip2.set_opacity(1)
+ tip2.set_fill(DARK_BLUE)
+ tip2.set_color(DARK_BLUE)
+ arrow2.set_color(DARK_BLUE)
+
+ arrow3 = Line(start = ORIGIN,end = [0,0,1])
+ arrow3.set_color(DARK_BLUE)
+ tip3 = Polygon([0,0,1],[0,0,0.9]-0.1*RIGHT,[0,0,0.9]-0.1*LEFT)
+ tip3.set_opacity(1)
+ tip3.set_fill(DARK_BLUE)
+ tip3.set_color(DARK_BLUE)
+
+ axes = ThreeDAxes(x_min = -3,x_max=3,y_min=-3,y_max=3,z_min=-3,z_max=3)
+ self.play(ShowCreation(axes))
+ self.move_camera(phi=70*DEGREES,theta=0*DEGREES,run_time=3)
+ self.begin_ambient_camera_rotation(rate=0.2)
+
+ #matrix = [[1,0,0],[0,1,0],[0,0,1]]
+ matrix = [[0.70710678118,-0.57735026919,-0.57735026919],[0.70710678118,0.57735026919,0.57735026919],[0,-0.57735026919,0.57735026919]]
+ matrix1 = [[0.70710678118,0,0],[0.70710678118,1,0],[0,0,1]]
+
+ matrix1 = [[0.70710678118,-0.70710678118,0],[0.70710678118,0.70710678118,0],[0,0,1]]
+ matrix2 = [[1,0,0],[0,0.70710678118,0.70710678118],[0,-0.70710678118,0.70710678118]]
+
+
+ line1.apply_matrix(matrix1)
+ tip1.apply_matrix(matrix1)
+ arrow2.apply_matrix(matrix1)
+ tip2.apply_matrix(matrix1)
+ arrow3.apply_matrix(matrix1)
+ tip3.apply_matrix(matrix1)
+
+ line1.apply_matrix(matrix2)
+ tip1.apply_matrix(matrix2)
+ arrow2.apply_matrix(matrix2)
+ tip2.apply_matrix(matrix2)
+ arrow3.apply_matrix(matrix2)
+ tip3.apply_matrix(matrix2)
+
+ self.play(ShowCreation(line1),
+ ShowCreation(tip1),
+ ShowCreation(arrow2),
+ ShowCreation(tip2),
+ ShowCreation(arrow3),
+ ShowCreation(tip3))
+
+ text = TextMobject(r"This is also a set of Orthonormal Vectors")
+ text.set_color(DARK_BLUE)
+ self.add_fixed_in_frame_mobjects(text)
+ text.scale(0.6)
+ text.move_to(3*DOWN+3.5*RIGHT)
+ self.play(Write(text))
+
+ self.wait(22)
diff --git a/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file5.gif b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file5.gif
new file mode 100644
index 0000000..cdc0f2d
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file5.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file6.gif b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file6.gif
new file mode 100644
index 0000000..e03f265
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file6.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file7.gif b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file7.gif
new file mode 100644
index 0000000..19a13dd
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file7.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file8.gif b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file8.gif
new file mode 100644
index 0000000..0ef4551
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Gram-Schmidt-Orthonormalization-Process/file8.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/README.md b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/README.md
new file mode 100644
index 0000000..2a46424
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/README.md
@@ -0,0 +1,30 @@
+# Contributer: Archit Sangal
+My Github Account : <a href="https://github.com/architsangal">architsangal</a> (https://github.com/architsangal)
+<br/></br>
+
+## Sub-Topics Covered:
++ Linear Transformations (Linear Maps)
+
+#### Video 1: Visually understanding linear transformation(using grid)
+![GIF1](file12.gif)
+
+#### Video 2: Linear Transformation when form 1 is given
+![GIF2](file11.gif)
+
+#### Video 3: Matrix Representation Of Linear Transformation
+![GIF3](file9.gif)
+
+#### Video 4: Understand Linear Transformations visually
+![GIF4](file13.gif)
+
+#### Video 5: Uniform Scaling
+![GIF5](file14.gif)
+
+#### Fig.1 Horizontal Shear
+![GIF6](file6_Horizontal_Shear_gif.gif)
+
+#### Fig.2 Vertical Shear
+![GIF7](file7_Vertical_Shear_gif.gif)
+
+#### Video 6: Rotation by an angle of in anticlockwise direction
+![GIF8](file10.gif) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file10.gif b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file10.gif
new file mode 100644
index 0000000..d996130
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file10.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file11.gif b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file11.gif
new file mode 100644
index 0000000..d8c64b7
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file11.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file12.gif b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file12.gif
new file mode 100644
index 0000000..92bdff6
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file12.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file13.gif b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file13.gif
new file mode 100644
index 0000000..ba6c156
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file13.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file14.gif b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file14.gif
new file mode 100644
index 0000000..fd9bc7b
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file14.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file1_transformations.py b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file1_transformations.py
new file mode 100644
index 0000000..0182bd9
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file1_transformations.py
@@ -0,0 +1,73 @@
+from manimlib.imports import *
+
+class text(Scene):
+ def construct(self):
+ text1 = TextMobject("For a grid, undergoing a linear transformation, all its straight lines")
+ text1.scale(0.9)
+ text2 = TextMobject("must either remain straight lines or sends to a point in the grid formed")
+ text2.scale(0.9)
+ text3 = TextMobject("Origin must remain where it was before transformation.")
+ text3.scale(0.9)
+ text1.move_to(ORIGIN+UP)
+ text2.move_to(ORIGIN)
+ text3.move_to(ORIGIN+DOWN)
+ self.play(Write(text1))
+ self.play(Write(text2))
+ self.play(Write(text3))
+ self.wait()
+ self.play(FadeOut(text1),FadeOut(text2),FadeOut(text3))
+
+class LinearTransformation(LinearTransformationScene):
+ CONFIG = {
+ "basis_vector_stroke_width": 3,
+ "leave_ghost_vectors": True,
+ }
+
+ def construct(self):
+ self.setup()
+ matrix = [[0.866,-0.5],[0.5,0.866]]
+ self.apply_matrix(matrix)
+ text = TextMobject("This is a Linear","Trasformation")
+ text[0].move_to(DOWN+4*LEFT)
+ text[1].move_to(1.5*DOWN+4*LEFT)
+ text.add_background_rectangle()
+ self.play(Write(text))
+ self.wait()
+
+class NonLinearTransformation(Scene):
+ def construct(self):
+ grid = NumberPlane()
+ self.play(ShowCreation(grid),run_time =2)
+ # I have taken reference from purusharth's code
+ NonLinearTrans = lambda coordinates : coordinates + np.array([np.sin(coordinates[1]),np.sin(coordinates[0]),0,])
+ grid.prepare_for_nonlinear_transform()
+ self.play(grid.apply_function,NonLinearTrans)
+ text = TextMobject("While, this is not a","Linear Trasformation")
+ text[0].move_to(DOWN+4*LEFT)
+ text[1].move_to(1.5*DOWN+4*LEFT)
+ text.add_background_rectangle()
+ self.play(Write(text))
+ self.wait()
+
+class MoveOrigin(LinearTransformationScene):
+
+ CONFIG = {
+ "show_basis_vectors": False,
+ }
+ def construct(self):
+ self.wait()
+
+ dot = Dot(ORIGIN, color = YELLOW)
+ self.add_transformable_mobject(dot)
+ self.apply_nonlinear_transformation(self.func)
+ text = TextMobject("This is also not a linear transformation as the origin moves from its original position")
+ text.move_to(2*DOWN)
+ text.scale(0.5)
+ text.set_color(YELLOW)
+ text.add_background_rectangle()
+ self.play(Write(text))
+ self.wait()
+
+ def func(self, point):
+ matrix_transform = self.get_matrix_transformation([[1, -1], [1, 1]])
+ return matrix_transform(point) + UP+ RIGHT
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file2_before_matrix.py b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file2_before_matrix.py
new file mode 100755
index 0000000..1f6badd
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file2_before_matrix.py
@@ -0,0 +1,233 @@
+from manimlib.imports import *
+
+class Linear(GraphScene):
+
+ CONFIG = {
+ "x_min": -5,
+ "x_max": 5,
+ "y_min": -5,
+ "y_max": 5,
+ "graph_origin": ORIGIN,
+ "x_labeled_nums": list(range(-5, 6)),
+ "y_labeled_nums": list(range(-5, 6)),
+ "x_axis_width": 7,
+ "y_axis_height": 7,
+ }
+
+ def construct(self):
+
+ XTD = self.x_axis_width/(self.x_max- self.x_min)
+ YTD = self.y_axis_height/(self.y_max- self.y_min)
+
+ self.setup_axes(animate = True)
+ heading = TextMobject(r"$T(x,y) = T(x+2y,x-y)$")
+ heading.move_to(UP*3+LEFT*4)
+ heading.scale(0.7)
+ self.play(Write(heading))
+ self.wait()
+
+ before = TextMobject("Before Linear Transformation")
+ before.set_color(ORANGE)
+ before.move_to(3*UP+4*RIGHT)
+ before.scale(0.75)
+ dot1 = Dot().shift(self.graph_origin+1*XTD*RIGHT+1*YTD*UP)
+ dot2 = Dot().shift(self.graph_origin+2*XTD*RIGHT+1*YTD*UP)
+ dot1.set_color(ORANGE)
+ dot2.set_color(ORANGE)
+ p1 = TextMobject(r"$P_1$")
+ p1.scale(0.75)
+ p1.set_color(ORANGE)
+ p1.move_to(self.graph_origin+1*XTD*RIGHT+1.5*YTD*UP)
+ p2 = TextMobject(r"$P_2$")
+ p2.set_color(ORANGE)
+ p2.scale(0.75)
+ p2.move_to(self.graph_origin+2*XTD*RIGHT+1.5*YTD*UP)
+
+ after = TextMobject("After applying Linear Transformation")
+ after.set_color(YELLOW)
+ after.move_to(3*UP+4.5*RIGHT)
+ after.scale(0.5)
+ dot3 = Dot().shift(self.graph_origin+3*XTD*RIGHT+0*YTD*UP)
+ dot4 = Dot().shift(self.graph_origin+4*XTD*RIGHT+1*YTD*UP)
+ dot3.set_color(YELLOW)
+ dot4.set_color(YELLOW)
+ p3 = TextMobject(r"$T(P_1)$")
+ p3.scale(0.7)
+ p3.set_color(YELLOW)
+ p3.move_to(self.graph_origin+3*XTD*RIGHT-1.1*YTD*UP)
+ p4 = TextMobject(r"$T(P_2)$")
+ p4.scale(0.7)
+ p4.set_color(YELLOW)
+ p4.move_to(self.graph_origin+4*XTD*RIGHT+1.5*YTD*UP)
+
+ self.play(Write(before), ShowCreation(dot1), ShowCreation(dot2),Write(p1), Write(p2))
+ self.wait(3)
+ self.play(Transform(before,after), Transform(dot1,dot3), Transform(dot2,dot4), Transform(p2,p4), Transform(p1,p3))
+ self.wait(3)
+
+
+class withgrid(LinearTransformationScene):
+ def construct(self):
+
+ heading = TextMobject(r"Now, imagine this happening for all the points")
+ heading.scale(0.5)
+ heading.move_to(UP*2.5+LEFT*4)
+ self.play(Write(heading))
+ self.wait()
+
+ before = TextMobject("Before Linear Transformation")
+ before.set_color(ORANGE)
+ before.move_to(3.5*UP+4*RIGHT)
+ before.scale(0.75)
+ dot1 = Dot().shift(1*RIGHT+1*UP)
+ dot2 = Dot().shift(2*RIGHT+1*UP)
+ dot1.set_color(ORANGE)
+ dot2.set_color(ORANGE)
+
+ dot1_c = Dot(radius = 0.05).shift(1*RIGHT+1*UP)
+ dot2_c = Dot(radius = 0.05).shift(2*RIGHT+1*UP)
+ dot1_c.set_color(YELLOW)
+ dot2_c.set_color(YELLOW)
+ self.add_transformable_mobject(dot1_c)
+ self.add_transformable_mobject(dot2_c)
+
+ p1 = TextMobject(r"$P_1$")
+ p1.scale(0.75)
+ p1.set_color(ORANGE)
+ p1.move_to(1*RIGHT+1.5*UP)
+ p2 = TextMobject(r"$P_2$")
+ p2.scale(0.75)
+ p2.set_color(ORANGE)
+ p2.move_to(2*RIGHT+1.5*UP)
+
+ after = TextMobject("After applying Linear Transformation")
+ after.set_color(YELLOW)
+ after.move_to(3.5*UP+3.5*RIGHT)
+ after.scale(0.75)
+ dot3 = Dot().shift(3*RIGHT+0*UP)
+ dot4 = Dot().shift(4*RIGHT+1*UP)
+ dot3.set_color(YELLOW)
+ dot4.set_color(YELLOW)
+ p3 = TextMobject(r"$T(P_1)$")
+ p3.scale(0.75)
+ p3.set_color(YELLOW)
+ p3.move_to(3*RIGHT-0.6*UP)
+ p4 = TextMobject(r"$T(P_2)$")
+ p4.scale(0.75)
+ p4.set_color(YELLOW)
+ p4.move_to(4*RIGHT+1.5*UP)
+
+ self.play(Write(before), ShowCreation(dot1), ShowCreation(dot2),Write(p1), Write(p2))
+ self.wait(3)
+ matrix = [[1,2],[1,-1]]
+ dot1.set_color(GREY)
+ dot2.set_color(GREY)
+ self.play(FadeIn(dot1),FadeIn(dot2))
+ self.apply_matrix(matrix)
+ self.play(Transform(before,after), Transform(p2,p4), Transform(p1,p3))
+ self.play(Transform(before,after))
+ self.wait(3)
+
+ ending = TextMobject(r"$T(\left[\begin{array}{c}x \\ y\end{array}\right]) = \left[\begin{array}{c} x+2y \\ x-y\end{array}\right]$")
+ ending.move_to(UP*2+LEFT*4)
+ self.play(Transform(heading,ending))
+ self.wait()
+
+from manimlib.imports import *
+class ThreeDExplanation(ThreeDScene):
+
+ def construct(self):
+
+ text = TextMobject(r"$T(x,y) = (x+y,x-y,x+2y)$")
+ text.scale(0.75)
+ text.move_to(UP*2.5+LEFT*4)
+ text.move_to(-UP*3+LEFT*4)
+ self.add_fixed_in_frame_mobjects(text)
+ self.play(Write(text))
+ self.wait()
+
+ before = TextMobject("Before Linear Transformation")
+ self.add_fixed_in_frame_mobjects(before)
+ before.set_color(ORANGE)
+ before.move_to(3.5*UP+4*RIGHT)
+ before.scale(0.75)
+
+ p1 = TextMobject(r"$P_1$")
+ p2 = TextMobject(r"$P_2$")
+ p3 = TextMobject(r"$P_3$")
+ p1.scale(0.75)
+ p2.scale(0.75)
+ p3.scale(0.75)
+ dot1 = Dot().shift(1*RIGHT+1*UP)
+ dot2 = Dot().shift(2*RIGHT+1*UP)
+ dot3 = Dot().shift(1*RIGHT+1*DOWN)
+ dot1.set_color(ORANGE)
+ dot2.set_color(ORANGE)
+ dot3.set_color(ORANGE)
+ self.play(ShowCreation(before))
+
+ p1.move_to(1*RIGHT+1*UP+[0,0,0.5])
+ p2.move_to(2*RIGHT+1*UP+[0,0,0.5])
+ p3.move_to(1*RIGHT-1*UP+[0,0,0.5])
+
+ dot1_c = Dot(radius = 0.05).shift(1*RIGHT+1*UP)
+ dot2_c = Dot(radius = 0.05).shift(0*RIGHT+2*UP)
+ dot3_c = Dot(radius = 0.05).shift(1*RIGHT-1*UP)
+ dot1_c.set_color(YELLOW)
+ dot2_c.set_color(YELLOW)
+ dot3_c.set_color(YELLOW)
+
+ axes = ThreeDAxes(x_min = -7,x_max=7,y_min=-4,y_max=4,z_min=-4,z_max=4)
+ self.play(ShowCreation(axes))
+ self.move_camera(distance = 100, phi=30*DEGREES,theta=45*DEGREES,run_time=3)
+
+ self.begin_ambient_camera_rotation(rate=0.3)
+ self.wait(1)
+ self.stop_ambient_camera_rotation()
+
+ plane = NumberPlane()
+ self.add_fixed_orientation_mobjects(p1)
+ self.add_fixed_orientation_mobjects(p2)
+ self.add_fixed_orientation_mobjects(p3)
+ self.play(ShowCreation(dot1),ShowCreation(dot3),ShowCreation(dot2),ShowCreation(plane))
+
+ self.play(FadeOut(before))
+ after = TextMobject("After applying Linear Transformation")
+ self.add_fixed_in_frame_mobjects(after)
+ after.set_color(YELLOW)
+ after.move_to(3.5*UP+3.5*RIGHT)
+ after.scale(0.75)
+
+ self.play(FadeOut(p1),FadeOut(p2),FadeOut(p3))
+ matrix = [[1,1],[1,-1],[2,1]]
+ self.play(FadeOut(dot1),FadeOut(dot2),FadeOut(dot3),ApplyMethod(plane.apply_matrix,matrix),ApplyMethod(dot1_c.apply_matrix,matrix),ApplyMethod(dot3_c.apply_matrix,matrix),ApplyMethod(dot2_c.apply_matrix,matrix))
+
+ p4 = TextMobject(r"$T(P_1)$")
+ p5 = TextMobject(r"$T(P_2)$")
+ p6 = TextMobject(r"$T(P_3)$")
+ p4.scale(0.75)
+ p5.scale(0.75)
+ p6.scale(0.75)
+ p4.move_to(2*RIGHT+0*UP+[0,0,3.5])
+ p5.move_to(2*RIGHT-2*UP+[0,0,2.5])
+ p6.move_to(0*RIGHT+2*UP+[0,0,1.5])
+ self.add_fixed_orientation_mobjects(p5)
+ self.add_fixed_orientation_mobjects(p4)
+ self.add_fixed_orientation_mobjects(p6)
+
+ self.begin_ambient_camera_rotation(rate=0.3)
+ self.wait(3)
+ self.stop_ambient_camera_rotation()
+
+ ending = TextMobject(r"$T(\left[\begin{array}{c}x \\ y\end{array}\right])$ = ",r"$\left[\begin{array}{c} x+y \\ x-y\\ x+2y \end{array}\right]$") #\begin{array}{c} x+y \\ x-y -- \\ x+2y -- \end{array}\right]$")
+ ending.scale(0.75)
+ ending.move_to(-UP*3+LEFT*4)
+ self.add_fixed_in_frame_mobjects(ending)
+ self.play(FadeOut(text),Write(ending))
+
+ self.play(FadeOut(plane))
+ self.wait(2)
+
+ self.begin_ambient_camera_rotation(rate=0.3)
+ self.wait(8)
+ self.stop_ambient_camera_rotation()
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file3_square.py b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file3_square.py
new file mode 100644
index 0000000..e828de4
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file3_square.py
@@ -0,0 +1,246 @@
+from manimlib.imports import *
+
+class Linear(GraphScene):
+ CONFIG = {
+ "x_min": -5,
+ "x_max": 5,
+ "y_min": -5,
+ "y_max": 5,
+ "graph_origin": ORIGIN,
+ "x_labeled_nums": list(range(-5, 6)),
+ "y_labeled_nums": list(range(-5, 6)),
+ "x_axis_width": 7,
+ "y_axis_height": 7,
+ }
+ def construct(self):
+
+ text = TextMobject("T(x,y) = T(x+y,y)")
+ text.scale(0.75)
+ text.set_color(PURPLE)
+ text.move_to(3*UP+5*LEFT)
+ self.play(Write(text))
+
+ XTD = self.x_axis_width/(self.x_max- self.x_min)
+ YTD = self.y_axis_height/(self.y_max- self.y_min)
+
+ self.setup_axes(animate = True)
+
+ text1 = TextMobject("Before Linear Transformation")
+ text1.scale(0.6)
+ text1.move_to(UP*3+3*RIGHT)
+
+ a = TextMobject("(1,1)")
+ b = TextMobject("(3,1)")
+ c = TextMobject("(3,2)")
+ d = TextMobject("(1,2)")
+ a.scale(0.5)
+ b.scale(0.5)
+ c.scale(0.5)
+ d.scale(0.5)
+ a.move_to(self.graph_origin+0.6*UP+0.6*RIGHT)
+ b.move_to(self.graph_origin+0.6*UP+3.4*RIGHT)
+ c.move_to(self.graph_origin+2.4*UP+3.4*RIGHT)
+ d.move_to(self.graph_origin+2.6*UP+0.6*RIGHT)
+
+ square = Polygon(self.graph_origin+UP+RIGHT,self.graph_origin+UP+3*RIGHT,self.graph_origin+2*UP+3*RIGHT,self.graph_origin+2*UP+RIGHT)
+
+ self.play(Write(text1), Write(a), Write(b), Write(c), Write(d), ShowCreation(square))
+ self.wait(2)
+ self.play(FadeOut(text1), FadeOut(a), FadeOut(b), FadeOut(c), FadeOut(d), ApplyMethod(square.apply_matrix,[[1,1],[0,1]]))
+
+ a = TextMobject("(2,1)")
+ b = TextMobject("(4,1)")
+ c = TextMobject("(3,2)")
+ d = TextMobject("(5,2)")
+ a.scale(0.5)
+ b.scale(0.5)
+ c.scale(0.5)
+ d.scale(0.5)
+ a.move_to(self.graph_origin+0.6*UP+1.6*RIGHT)
+ b.move_to(self.graph_origin+0.6*UP+4.4*RIGHT)
+ d.move_to(self.graph_origin+2.4*UP+5.4*RIGHT)
+ c.move_to(self.graph_origin+2.4*UP+2.6*RIGHT)
+
+ text1 = TextMobject("After Linear Transformation")
+ text1.scale(0.6)
+ text1.move_to(UP*3+3*RIGHT)
+
+ self.play(Write(text1), Write(a), Write(b), Write(c), Write(d))
+
+ self.wait(2)
+
+class grid(LinearTransformationScene):
+ def construct(self):
+
+ text = TextMobject("Now, consider all the vectors.")
+ text.scale(0.75)
+ text.set_color(PURPLE)
+ text.move_to(2.5*UP+3*LEFT)
+ self.play(Write(text))
+
+ text1 = TextMobject("Before Linear Transformation")
+ text1.scale(0.6)
+ text1.move_to(UP*3.5+3.5*RIGHT)
+
+ square = Polygon(UP+RIGHT,UP+3*RIGHT,2*UP+3*RIGHT,2*UP+RIGHT)
+ square.set_color(YELLOW)
+
+ self.play(Write(text1), ShowCreation(square))
+ self.wait(2)
+ self.play(FadeOut(text1))
+ self.add_transformable_mobject(square)
+
+ text1 = TextMobject("After Linear Transformation")
+ text1.scale(0.6)
+ text1.move_to(UP*3.5+3.5*RIGHT)
+
+ matrix = [[1,1],[0,1]]
+
+ self.apply_matrix(matrix)
+ self.play(Write(text1))
+
+ self.wait()
+
+class grid2(LinearTransformationScene):
+ CONFIG = {
+ "include_background_plane": True,
+ "include_foreground_plane": False,
+ "show_coordinates": True,
+ "show_basis_vectors": True,
+ "basis_vector_stroke_width": 3,
+ "i_hat_color": X_COLOR,
+ "j_hat_color": Y_COLOR,
+ "leave_ghost_vectors": True,
+ }
+
+ def construct(self):
+
+ text = TextMobject("Now, let us focus only on the standard basis")
+ text.scale(0.7)
+ text.set_color(PURPLE)
+ text.move_to(2.5*UP+3.5*LEFT)
+ self.play(Write(text))
+
+ text1 = TextMobject("Before Linear Transformation")
+ text1.scale(0.6)
+ text1.move_to(UP*3.5+3.5*RIGHT)
+
+ square = Polygon(UP+RIGHT,UP+3*RIGHT,2*UP+3*RIGHT,2*UP+RIGHT)
+ square.set_color(YELLOW)
+
+ self.play(Write(text1), ShowCreation(square))
+ self.wait(2)
+ self.play(FadeOut(text1))
+ self.add_transformable_mobject(square)
+
+ text1 = TextMobject("After Linear Transformation")
+ text1.scale(0.6)
+ text1.move_to(UP*3.5+3.5*RIGHT)
+
+ matrix = [[1,1],[0,1]]
+
+ self.apply_matrix(matrix)
+ self.play(Write(text1))
+
+ self.play(FadeOut(square), FadeOut(text1))
+
+ cor_x = TextMobject("(1,0)")
+ cor_y = TextMobject("(1,1)")
+ cor_x.scale(0.65)
+ cor_y.scale(0.65)
+ cor_y.move_to(1.25*RIGHT+1.5*UP)
+ cor_x.move_to(0.75*RIGHT-0.5*UP)
+ cor_x.set_color(GREEN)
+ cor_y.set_color(RED)
+
+ x_cor = TextMobject(r"$\left[\begin{array}{c} 1\\0\end{array}\right]$")
+ x_cor.set_color(GREEN)
+ x_cor.scale(0.5)
+ y_cor = TextMobject(r"$\left[\begin{array}{c} 1\\1\end{array}\right]$")
+ x_cor.move_to(0.75*RIGHT-0.5*UP)
+ y_cor.move_to(1.25*RIGHT+1.5*UP)
+ y_cor.set_color(RED)
+ y_cor.scale(0.5)
+
+ text1 = TextMobject(r"$T(\left[\begin{array}{c} x\\y \end{array}\right]) = $",r"$\left[\begin{array}{c} x+y\\y \end{array}\right]$")
+ text1.scale(0.7)
+ text1.set_color(PURPLE)
+ text1.move_to(1.5*UP+3*LEFT)
+
+ text = TextMobject(r"$T(x,y) = (x+y,y)$")
+ text.scale(0.6)
+ text.set_color(PURPLE)
+ text.move_to(1.5*UP+3*LEFT)
+
+ self.play(FadeIn(text),FadeIn(cor_x), FadeIn(cor_y))
+ self.wait()
+
+ self.play(Transform(text,text1), Transform(cor_x,x_cor), Transform(cor_y,y_cor))
+
+ text3 = TextMobject(r"$\left[\begin{array}{c} x+y\\y \end{array}\right]$")
+ text3.scale(0.7)
+ text3.set_color(PURPLE)
+ text3.move_to(1.5*DOWN+5*LEFT)
+
+ equal = TextMobject("=")
+ equal.move_to(1.5*DOWN+3.5*LEFT)
+
+ text3 = TextMobject("[")
+ text4 = TextMobject(r"$\begin{array}{c} (1)x\\(0)x \end{array}$")
+ text5 = TextMobject(r"$\begin{array}{c} + \\ + \end{array}$")
+ text6 = TextMobject(r"$\begin{array}{c} (1)y\\(1)y \end{array}$")
+ text7 = TextMobject("]")
+ text3.scale(2)
+ text4.scale(0.7)
+ text5.scale(0.7)
+ text6.scale(0.7)
+ text7.scale(2)
+ text4.set_color(GREEN)
+ text5.set_color(PURPLE)
+ text6.set_color(RED)
+ text3.move_to(1.5*DOWN+3*LEFT)
+ text4.move_to(1.5*DOWN+2.5*LEFT)
+ text5.move_to(1.5*DOWN+2*LEFT)
+ text6.move_to(1.5*DOWN+1.5*LEFT)
+ text7.move_to(1.5*DOWN+1*LEFT)
+
+ text1[1].scale(1.2)
+ self.play(FadeOut(text1[0]), ApplyMethod(text1[1].move_to,1.5*DOWN+5*LEFT), FadeIn(text3), FadeIn(equal), FadeIn(text4), FadeIn(text5), FadeIn(text6), FadeIn(text7))
+
+ self.wait()
+ self.play(FadeOut(text1[1]))
+
+ self.play(ApplyMethod(text3.move_to,1.5*DOWN+6*LEFT),
+ ApplyMethod(text4.move_to,1.5*DOWN+5.5*LEFT),
+ ApplyMethod(text5.move_to,1.5*DOWN+5*LEFT),
+ ApplyMethod(text6.move_to,1.5*DOWN+4.5*LEFT),
+ ApplyMethod(text7.move_to,1.5*DOWN+4*LEFT))
+
+ text10 = TextMobject("[")
+ text11 = TextMobject(r"$\begin{array}{c} 1\\0 \end{array}$")
+ text13 = TextMobject(r"$\begin{array}{c} 1\\1 \end{array}$")
+ text14 = TextMobject("]")
+ text10.scale(2)
+ text11.scale(0.7)
+ text13.scale(0.7)
+ text14.scale(2)
+ text11.set_color(GREEN)
+ text13.set_color(RED)
+ text10.move_to(1.5*DOWN+3*LEFT)
+ text11.move_to(1.5*DOWN+2.75*LEFT)
+ text13.move_to(1.5*DOWN+2.25*LEFT)
+ text14.move_to(1.5*DOWN+2*LEFT)
+
+ self.play(FadeIn(text10), Transform(x_cor,text11), Transform(y_cor,text13), FadeIn(text14))
+
+ text15 = TextMobject(r"$\left[\begin{array}{c} x\\y \end{array}\right]$")
+ text15.scale(0.7)
+ text15.set_color(PURPLE)
+ text15.move_to(1.5*DOWN+1.5*LEFT)
+
+ self.play(FadeIn(text15))
+ self.play(FadeOut(text3), FadeOut(text4), FadeOut(text5), FadeOut(text7), FadeOut(text6))
+
+ text1[0].scale(1.2)
+ self.play(ApplyMethod(text1[0].move_to,1.5*DOWN+4.5*LEFT), FadeOut(equal))
+ self.wait(2) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file1_Understand_Linear_Transformations_visually.py b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file4_Understand_Linear_Transformations_visually.py
index 577032d..577032d 100644
--- a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file1_Understand_Linear_Transformations_visually.py
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file4_Understand_Linear_Transformations_visually.py
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file2_Uniform_Scaling.py b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file5_Uniform_Scaling.py
index a7856a5..a7856a5 100644
--- a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file2_Uniform_Scaling.py
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file5_Uniform_Scaling.py
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file3_Horizontal_Shear.py b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file6_Horizontal_Shear.py
index 91f098e..91f098e 100644
--- a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file3_Horizontal_Shear.py
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file6_Horizontal_Shear.py
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file3_Horizontal_Shear_gif.gif b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file6_Horizontal_Shear_gif.gif
index 9bef1b6..9bef1b6 100644
--- a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file3_Horizontal_Shear_gif.gif
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file6_Horizontal_Shear_gif.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file4_Vertical_Shear.py b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file7_Vertical_Shear.py
index 718e4e0..718e4e0 100644
--- a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file4_Vertical_Shear.py
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file7_Vertical_Shear.py
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file4_Vertical_Shear_gif.gif b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file7_Vertical_Shear_gif.gif
index 7ca323f..7ca323f 100644
--- a/FSF-2020/linear-algebra/linear-transformations/Linear Transformations (Linear Maps)/file4_Vertical_Shear_gif.gif
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file7_Vertical_Shear_gif.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file8_linear_transformation.py b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file8_linear_transformation.py
new file mode 100755
index 0000000..01a0cef
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file8_linear_transformation.py
@@ -0,0 +1,27 @@
+from manimlib.imports import *
+class LinearTrans(LinearTransformationScene,MovingCameraScene):
+ CONFIG = {
+ "basis_vector_stroke_width": 1,
+ "leave_ghost_vectors": True,
+ }
+
+ def setup(self):
+ LinearTransformationScene.setup(self)
+ MovingCameraScene.setup(self)
+
+ def construct(self):
+ self.setup()
+ self.camera_frame.save_state()
+ self.play(self.camera_frame.set_width, 7)
+ matrix = [[0.866,-0.5],[0.5,0.866]]
+ self.apply_matrix(matrix)
+ arc1 = Arc(radius = 0.25,angle=TAU/12)
+ arc2 = Arc(radius = 0.25,angle=TAU/12,start_angle=TAU/4)
+ text1 = TextMobject(r"$\theta$")
+ text1.scale(0.5)
+ text1.move_to(0.5*UP+0.125*LEFT)
+ text2 = TextMobject(r"$\theta$")
+ text2.scale(0.5)
+ text2.move_to(0.5*RIGHT+0.125*UP)
+ self.play(ShowCreation(arc1),ShowCreation(arc2),Write(text1),Write(text2),run_time=1)
+ self.wait()
diff --git a/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file9.gif b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file9.gif
new file mode 100644
index 0000000..017e0c7
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Linear-Transformations-(Linear-Maps)/file9.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/README.md b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/README.md
new file mode 100644
index 0000000..e287fa1
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/README.md
@@ -0,0 +1,15 @@
+# Contributer: Archit Sangal
+My Github Account : <a href="https://github.com/architsangal">architsangal</a> (https://github.com/architsangal)
+<br/></br>
+
+## Sub-Topics Covered:
++ Orthonormal Bases
+
+#### Video 1: Example of Orthonormal bases
+![GIF1](file4.gif)
+
+#### Video 2: Adding the projections of a vector on orthonormal basis will produce the same vector
+![GIF2](file5.gif)
+
+#### Video 3: Relating the example and the property
+![GIF3](file6.gif) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file1_orthogonal.py b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file1_orthogonal.py
new file mode 100755
index 0000000..a5d96f5
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file1_orthogonal.py
@@ -0,0 +1,40 @@
+from manimlib.imports import *
+
+class Orthogonal(ThreeDScene):
+ def construct(self):
+ axes = ThreeDAxes()
+ self.play(ShowCreation(axes))
+ self.move_camera(phi=60*DEGREES,theta=45*DEGREES,run_time=3)
+
+ text = TextMobject(r"$\hat{i}$",r"$\hat{j}$",r"$\hat{k}$")
+ text[0].move_to(0.7*DOWN+0.8*LEFT)
+ text[1].move_to(0.75*DOWN+0.7*RIGHT)
+ text[2].move_to(0.75*UP+0.4*RIGHT)
+ self.add_fixed_in_frame_mobjects(text)
+ self.play(Write(text))
+
+ line1 = Line(start = ORIGIN,end = RIGHT)
+ line1.set_color(DARK_BLUE)
+ tip1 = Polygon(-0.95*LEFT,-0.8*LEFT-0.1*DOWN,-0.8*LEFT-0.1*UP)
+ tip1.set_opacity(1)
+ tip1.set_fill(DARK_BLUE)
+ tip1.set_color(DARK_BLUE)
+
+ arrow2 = Line(start = ORIGIN,end = UP)
+ arrow2.set_color(DARK_BLUE)
+ tip2 = Polygon(0.95*UP,0.8*UP-0.1*RIGHT,0.8*UP-0.1*LEFT)
+ tip2.set_opacity(1)
+ tip2.set_fill(DARK_BLUE)
+ tip2.set_color(DARK_BLUE)
+ arrow2.set_color(DARK_BLUE)
+
+ arrow3 = Line(start = ORIGIN,end = [0,0,1])
+ arrow3.set_color(DARK_BLUE)
+ tip3 = Polygon([0,0,0.95],[0,0,0.8]-0.1*RIGHT,[0,0,0.8]-0.1*LEFT)
+ tip3.set_opacity(1)
+ tip3.set_fill(DARK_BLUE)
+ tip3.set_color(DARK_BLUE)
+
+ self.play(ShowCreation(line1), ShowCreation(tip1), ShowCreation(arrow2), ShowCreation(tip2), ShowCreation(arrow3), ShowCreation(tip3))
+
+ self.wait()
diff --git a/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file2_sum_of_projections_part1.py b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file2_sum_of_projections_part1.py
new file mode 100755
index 0000000..141e99b
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file2_sum_of_projections_part1.py
@@ -0,0 +1,133 @@
+from manimlib.imports import *
+class LinearTrans(LinearTransformationScene):
+ CONFIG = {
+ "show_basis_vectors": True,
+ "basis_vector_stroke_width": 1,
+ "leave_ghost_vectors": False,
+ "show_coordinates": True,
+ }
+
+ def construct(self):
+
+ self.setup()
+
+ matrix = [[0.6,-0.8],[0.8,0.6]]
+ self.apply_matrix(matrix)
+
+ self.wait(2)
+ orthonormal = TextMobject(r"These are 2 orthonormal vectors($v_1$ and $v_2$)")
+ orthonormal.scale(0.7)
+ orthonormal.move_to(DOWN+LEFT*3.5)
+ orthonormal.add_background_rectangle()
+ v1 = TextMobject(r"$v_1$")
+ v1.scale(0.75)
+ v1.set_color(X_COLOR)
+ v1.move_to(0.75*UP+RIGHT)
+ v1.add_background_rectangle()
+ v2 = TextMobject(r"$v_2$")
+ v2.scale(0.75)
+ v2.set_color(Y_COLOR)
+ v2.move_to(0.75*UP+LEFT*1.25)
+ v2.add_background_rectangle()
+ self.play(Write(orthonormal))
+ self.play(Write(v1),Write(v2))
+ self.wait()
+ self.play(FadeOut(orthonormal), FadeOut(v1), FadeOut(v2))
+
+ arrow = Arrow(start = ORIGIN,end = 3*RIGHT+UP)
+ arrow.scale(1.2)
+ arrow.set_color(BLUE)
+ arrow.apply_matrix(matrix)
+ text3 = TextMobject("v")
+ text3.move_to(3.2*UP+1.2*RIGHT)
+ text3.add_background_rectangle()
+ self.play(ShowCreation(arrow),Write(text3))
+ self.wait()
+ v_cor = TextMobject("(1 , 3)")
+ v_cor.move_to(3.2*UP+1.3*RIGHT)
+ v_cor.set_color(BLUE)
+ v_cor.scale(0.75)
+ v_cor.add_background_rectangle()
+ self.play(Transform(text3,v_cor))
+
+ line1 = DashedLine(start = 1*UP+3*RIGHT, end = 3*RIGHT)
+ line2 = DashedLine(start = 1*UP+3*RIGHT, end = UP)
+ line1.apply_matrix(matrix)
+ line2.apply_matrix(matrix)
+ self.play(ShowCreation(line1),ShowCreation(line2),run_time = 2)
+
+ v1 = Arrow(start = ORIGIN,end = 3*RIGHT+UP)
+ v1.scale(1.2)
+ v1.set_color(BLUE)
+ v1.apply_matrix(matrix)
+ arrow1 = Arrow(start = ORIGIN,end = 3*RIGHT)
+ arrow1.scale(1.2)
+ arrow1.set_color("#6B8E23")
+ arrow1.apply_matrix(matrix)
+ self.play(Transform(v1,arrow1))
+ v1_cor = TextMobject(r"$<v,v_1> v_1$")
+ v1_cor.move_to(2.5*UP+3*RIGHT)
+ v1_cor.scale(0.75)
+ v1_cor.add_background_rectangle()
+ self.play(Write(v1_cor))
+ self.wait(0.5)
+ text1 = TextMobject("(1.8 , 2.4)")
+ text1.move_to(2.1*UP+2.5*RIGHT)
+ text1.scale(0.75)
+ text1.set_color("#6B8E23")
+ text1.add_background_rectangle()
+ self.play(Transform(v1_cor,text1))
+
+ v2 = Arrow(start = ORIGIN,end = 3*RIGHT+UP)
+ v2.scale(1.2)
+ v2.set_color("#8b0000")
+ v2.apply_matrix(matrix)
+ arrow2 = Arrow(start = ORIGIN,end = UP)
+ arrow2.scale(2.1)
+ arrow2.set_color("#8b0000")
+ arrow2.apply_matrix(matrix)
+ self.wait(0.5)
+ self.play(Transform(v2,arrow2))
+ self.wait(0.5)
+ v2_cor = TextMobject(r"$<v,v_2> v_2$")
+ v2_cor.move_to(0.75*UP+2.5*LEFT)
+ v2_cor.scale(0.75)
+ v2_cor.add_background_rectangle()
+ self.play(Write(v2_cor))
+ self.wait(0.5)
+ text2 = TextMobject("(-0.8 , 0.6)")
+ text2.move_to(0.75*UP+1.75*LEFT)
+ text2.scale(0.75)
+ text2.set_color("#8b0000")
+ text2.add_background_rectangle()
+ self.play(Transform(v2_cor,text2))
+
+ self.wait()
+
+ self.play(ApplyMethod(v2.move_to,1.4*RIGHT+2.7*UP),FadeOut(v1_cor),FadeOut(v2_cor),FadeOut(v_cor))
+
+ self.wait()
+
+ ending = TextMobject(r"$v = <v,v_1> v_1 + <v,v_2> v_2$")
+ ending.scale(0.7)
+ ending.move_to(DOWN)
+ ending.add_background_rectangle()
+ self.play(Write(ending))
+ self.wait()
+ self.play(FadeOut(ending))
+
+ ending = TextMobject(r"$\left[ \begin{array} {c} 1\\ 3 \end{array}\right] = \left[ \begin{array} {c}1.8 \\ 2.4 \end{array}\right] + \left[ \begin{array} {c} -0.8\\ 0.6 \end{array}\right]$")
+ ending.scale(0.7)
+ ending.move_to(DOWN)
+ ending.add_background_rectangle()
+ self.play(Write(ending))
+ self.wait()
+ self.play(FadeOut(ending))
+
+ ending = TextMobject(r"$v$ is the sum of projections on the orthonormal vectors")
+ ending.scale(0.7)
+ ending.move_to(DOWN)
+ ending.add_background_rectangle()
+ self.play(Write(ending))
+ self.wait()
+ self.play(FadeOut(ending)) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file3_sum_of_projections_part2.py b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file3_sum_of_projections_part2.py
new file mode 100644
index 0000000..2899286
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file3_sum_of_projections_part2.py
@@ -0,0 +1,181 @@
+from manimlib.imports import *
+class ThreeDExplanation(ThreeDScene):
+
+ def construct(self):
+
+ basis = TextMobject(r"Set of Orthonormal Basis - $\left(\begin{array}{c}\frac{1}{\sqrt{2}}\\\frac{1}{\sqrt{2}}\\0\end{array}\right),\left(\begin{array}{c}\frac{-1}{\sqrt{2}}\\\frac{1}{\sqrt{2}}\\0\end{array}\right),\left(\begin{array}{c}0\\0\\1\end{array}\right)$")
+ basis.scale(0.75)
+ basis.move_to(UP*1.5)
+ self.play(Write(basis))
+ v = TextMobject(r"$v_1$",r"$v_2$",r"$v_3$")
+ v[0].move_to(UP*0.5+RIGHT*0.75)
+ v[1].move_to(UP*0.5+RIGHT*2.5)
+ v[2].move_to(UP*0.5+RIGHT*4)
+ eq = TextMobject(r"$v = \left(\begin{array}{c}3\\4\\5\end{array}\right)$")
+ eq1 = TextMobject(r"$<v,v_1> = \frac{3}{\sqrt{2}} + \frac{4}{\sqrt{2}} + 0 = \frac{7}{\sqrt{2}}$")
+ eq2 = TextMobject(r"$<v,v_2> = \frac{-3}{\sqrt{2}} + \frac{4}{\sqrt{2}} + 0 =\frac{1}{\sqrt{2}}$")
+ eq3 = TextMobject(r"$<v,v_3> =  0 + 0 + 5 =5$")
+ eq.move_to(4*LEFT+DOWN)
+ eq1.move_to(0.5*DOWN+2*RIGHT)
+ eq2.move_to(1.5*DOWN+2*RIGHT)
+ eq3.move_to(2.5*DOWN+2*RIGHT)
+ self.play(Write(v))
+ self.play(Write(eq))
+ self.play(Write(eq1))
+ self.play(Write(eq2))
+ self.play(Write(eq3))
+ self.wait()
+ self.play(FadeOut(basis), FadeOut(eq), FadeOut(v), FadeOut(eq1), FadeOut(eq2), FadeOut(eq3))
+ self.wait()
+
+ text = TextMobject("These are the 3 mutually orthonormal basis of the set(", r"$v_1$, ", r"$v_2$, ", r"$v_3$",")")
+ text[1].set_color(DARK_BLUE)
+ text[2].set_color(RED)
+ text[3].set_color(YELLOW)
+ text.scale(0.75)
+ self.add_fixed_in_frame_mobjects(text)
+ text.move_to(3*DOWN)
+ self.play(Write(text))
+ self.wait()
+
+ axes = ThreeDAxes(x_min = -6,x_max=6,y_min=-6,y_max=6,z_min=-6,z_max=6)
+ self.play(ShowCreation(axes))
+ self.move_camera(distance = 100, phi=45*DEGREES,theta=45*DEGREES,run_time=5)
+ self.begin_ambient_camera_rotation(rate=0.1)
+
+ xy_plane = Polygon(6*RIGHT+6*UP,-6*RIGHT+6*UP,-6*RIGHT-6*UP,6*RIGHT-6*UP)
+ xy_plane.set_color("#333333")
+ xy_plane.set_fill("#333333")
+ xy_plane.set_opacity(1)
+ xy_plane.fade(0.7)
+ self.play(ShowCreation(xy_plane))
+
+ dashedline1 = DashedLine(start = -6*(UP+RIGHT), end = 6*(UP+RIGHT))
+ dashedline2 = DashedLine(start = -6*(UP+LEFT), end = 6*(UP+LEFT))
+ dashedline3 = DashedLine(start = 4*UP+3*RIGHT+[0,0,5], end = 3.5*UP+3.5*RIGHT)
+ dashedline4 = DashedLine(start = 4*UP+3*RIGHT+[0,0,5], end = 0.5*UP+0.5*LEFT)
+ dashedline5 = DashedLine(start = 4*UP+3*RIGHT+[0,0,5], end = [0,0,5])
+
+ self.play(ShowCreation(dashedline1), ShowCreation(dashedline2))
+
+ line1 = Line(start = ORIGIN,end = 0.707*RIGHT + 0.707*UP)
+ line1.set_color(DARK_BLUE)
+ tip1 = Polygon(0.707*RIGHT + 0.707*UP, 0.707*RIGHT + 0.607*UP, 0.607*RIGHT + 0.707*UP)
+ tip1.set_opacity(1)
+ tip1.set_fill(DARK_BLUE)
+ tip1.set_color(DARK_BLUE)
+ self.play(ShowCreation(line1), ShowCreation(tip1))
+
+ line2 = Line(start = ORIGIN,end = 0.707*LEFT + 0.707*UP)
+ line2.set_color(RED)
+ tip2 = Polygon(0.707*LEFT + 0.707*UP, 0.707*LEFT + 0.607*UP, 0.607*LEFT + 0.707*UP)
+ tip2.set_opacity(1)
+ tip2.set_fill(RED)
+ tip2.set_color(RED)
+
+ self.play(ShowCreation(line2), ShowCreation(tip2))
+
+ line3 = Line(start = ORIGIN,end = [0,0,1])
+ line3.set_color(YELLOW)
+ tip3 = Polygon([0,0,1],[0,0,0.8]-0.2*RIGHT,[0,0,0.8]-0.2*LEFT)
+ tip3.set_opacity(1)
+ tip3.set_fill(YELLOW)
+ tip3.set_color(YELLOW)
+ self.play(ShowCreation(line3), ShowCreation(tip3))
+ self.wait()
+
+ self.play(FadeOut(text))
+
+ text = TextMobject("Take the projection of ", r"$v$", " on the mutually orthonormal vectors")
+ text[1].set_color(GOLD_E)
+ text.scale(0.75)
+ self.add_fixed_in_frame_mobjects(text)
+ text.move_to(3*DOWN)
+ self.play(Write(text))
+ self.wait(2)
+
+ a_line = Line(start = ORIGIN,end = 4*UP+3*RIGHT+[0,0,5])
+ a_line.set_color(GOLD_E)
+ a_tip = Polygon(3.92*UP+2.94*RIGHT+[0,0,4.9],3.6*UP+2.7*RIGHT+[0,0,4.5]+0.1*UP+0.1*LEFT,3.6*UP+2.7*RIGHT+[0,0,4.5]+0.1*DOWN+0.1*RIGHT)
+ a_tip.set_opacity(1)
+ a_tip.set_fill(GOLD_E)
+ a_tip.set_color(GOLD_E)
+
+ self.play(ShowCreation(a_line), ShowCreation(a_tip))
+ self.stop_ambient_camera_rotation()
+ self.move_camera(distance = 100, phi=45*DEGREES,theta=135*DEGREES,run_time=5)
+
+ self.play(ShowCreation(dashedline3),ShowCreation(dashedline4),ShowCreation(dashedline5))
+ self.wait()
+
+ pv1 = Line(start = ORIGIN,end = 4*UP+3*RIGHT+[0,0,5])
+ pv1.set_color(GOLD_E)
+ pv1tip = Polygon(4*UP+3*RIGHT+[0,0,5],3.6*UP+2.7*RIGHT+[0,0,4.5]+0.1*UP+0.1*LEFT,3.6*UP+2.7*RIGHT+[0,0,4.5]+0.1*DOWN+0.1*RIGHT)
+ pv1tip.set_opacity(1)
+ pv1tip.set_fill(GOLD_E)
+ pv1tip.set_color(GOLD_E)
+
+ v1_p = Line(start = ORIGIN,end = 3.5*RIGHT + 3.5*UP)
+ v1_p.set_color(BLUE_E)
+ v1_p_tip = Polygon(3.5*RIGHT + 3.5*UP, 3.5*RIGHT + 3.4*UP, 3.4*RIGHT + 3.5*UP)
+ v1_p_tip.set_opacity(1)
+ v1_p_tip.set_fill(BLUE_E)
+ v1_p_tip.set_color(BLUE_E)
+
+ pv2 = Line(start = ORIGIN,end = 4*UP+3*RIGHT+[0,0,5])
+ pv2.set_color(GOLD_E)
+ pv2tip = Polygon(4*UP+3*RIGHT+[0,0,5],3.6*UP+2.7*RIGHT+[0,0,4.5]+0.1*UP+0.1*LEFT,3.6*UP+2.7*RIGHT+[0,0,4.5]+0.1*DOWN+0.1*RIGHT)
+ pv2tip.set_opacity(1)
+ pv2tip.set_fill(GOLD_E)
+ pv2tip.set_color(GOLD_E)
+
+ v2_p = Line(start = ORIGIN,end = 0.5*LEFT + 0.5*UP)
+ v2_p.set_color(RED_E)
+ v2_p_tip = Polygon(0.5*LEFT + 0.5*UP, 0.5*LEFT + 0.4*UP, 0.4*LEFT + 0.5*UP)
+ v2_p_tip.set_opacity(1)
+ v2_p_tip.set_fill(RED_E)
+ v2_p_tip.set_color(RED_E)
+
+ pv3 = Line(start = ORIGIN,end = 4*UP+3*RIGHT+[0,0,5])
+ pv3.set_color(GOLD_E)
+ pv3tip = Polygon(4*UP+3*RIGHT+[0,0,5],3.6*UP+2.7*RIGHT+[0,0,4.5]+0.1*UP+0.1*LEFT,3.6*UP+2.7*RIGHT+[0,0,4.5]+0.1*DOWN+0.1*RIGHT)
+ pv3tip.set_opacity(1)
+ pv3tip.set_fill(GOLD_E)
+ pv3tip.set_color(GOLD_E)
+
+ v3_p = Line(start = ORIGIN,end = [0,0,5])
+ v3_p.set_color(YELLOW_E)
+ v3_p_tip = Polygon([0,0,5.15],[0,0,4.8]+0.2*RIGHT,[0,0,4.8]+0.2*LEFT)
+ v3_p_tip.set_opacity(1)
+ v3_p_tip.set_fill(YELLOW_E)
+ v3_p_tip.set_color(YELLOW_E)
+
+ #self.stop_ambient_camera_rotation()
+ self.play(Transform(pv1,v1_p),
+ Transform(pv1tip,v1_p_tip),
+ Transform(pv2,v2_p),
+ Transform(pv2tip,v2_p_tip),
+ Transform(pv3,v3_p),
+ Transform(pv3tip,v3_p_tip))
+ self.play(FadeOut(dashedline1),
+ FadeOut(dashedline2),
+ FadeOut(dashedline3),
+ FadeOut(dashedline4),
+ FadeOut(dashedline5),
+ FadeOut(line1),
+ FadeOut(tip1),
+ FadeOut(line2),
+ FadeOut(tip2),
+ FadeOut(line3),
+ FadeOut(tip3),
+ FadeOut(text))
+
+ text = TextMobject(r"$v$ is the sum of projections on the orthonormal vectors")
+ text.set_color(GOLD_E)
+ text.scale(0.75)
+ self.add_fixed_in_frame_mobjects(text)
+ text.move_to(3*DOWN)
+ self.play(Write(text), ApplyMethod(pv2.move_to,(3.5*RIGHT + 3.5*UP+3*RIGHT+4*UP)/2), ApplyMethod(pv2tip.move_to,(3.1*RIGHT + 3.9*UP)))
+ self.play(ApplyMethod(pv3.move_to,3*RIGHT + 4*UP + [0,0,2.5]), ApplyMethod(pv3tip.move_to,(3*RIGHT + 4*UP + [0,0,4.8])))
+
+ self.wait(3) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file4.gif b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file4.gif
new file mode 100644
index 0000000..4891350
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file4.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file5.gif b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file5.gif
new file mode 100644
index 0000000..d7eb0bc
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file5.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file6.gif b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file6.gif
new file mode 100644
index 0000000..1df6413
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/Orthonormal-Basis/file6.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/README.md b/FSF-2020/linear-algebra/linear-transformations/README.md
index 692201e..067755e 100644
--- a/FSF-2020/linear-algebra/linear-transformations/README.md
+++ b/FSF-2020/linear-algebra/linear-transformations/README.md
@@ -1,9 +1,10 @@
# Contributer: Archit Sangal
-My Github Account : <a href="https://github.com/architsangal">architsangal</a>
+My Github Account : <a href="https://github.com/architsangal">architsangal</a> (https://github.com/architsangal). These code were written during the course of FOSSEE Summer Fellowship 2020 under the FLOSS: Mathematics using Python.
<br/></br>
+
## Sub-Topics Covered:
-+ Vector Space Homomorphisms (Linear Maps)
++ Linear Transformations (Linear Maps)
+ The Four Fundamental Subspaces
+ Rank-Nullity Theorem
+ Orthonormal basis
-+ Gramm-Schmidt Orthogonalization Process
++ Gramm-Schmidt Orthogonalization Process \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/README.md b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/README.md
new file mode 100644
index 0000000..6c90bf4
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/README.md
@@ -0,0 +1,30 @@
+# Contributer: Archit Sangal
+My Github Account : <a href="https://github.com/architsangal">architsangal</a> (https://github.com/architsangal)
+<br/></br>
+
+## Sub-Topics Covered:
++ The Four Fundamental Subspaces
+
+#### Video 1: Writing System of linear equations in form of Ax=b
+![GIF1](file11.gif)
+
+#### Video 2: Column Space is same as the image of Linear Transformation
+![GIF2](file14.gif)
+
+#### Video 3: Existance of Solution w.r.t. vector b
+![GIF3](file17.gif)
+
+#### Video 4: Null Space (Visually)
+![GIF4](file12.gif)
+
+#### Video 5: Definition 1 is equivalent to Definition 2
+![GIF5](file13.gif)
+
+#### Video 6: Relation between Row Space and Null Space
+![GIF6](file16.gif)
+
+#### Fig. 1 Naming of the left null space
+![GIF7](file10_Left_Null_Space_pSv8iio_d5Sy9qS.gif)
+
+#### Video 7: Left Null Space(Visually)
+![GIF8](file15.gif) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file10_Left_Null_Space_pSv8iio_d5Sy9qS.gif b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file10_Left_Null_Space_pSv8iio_d5Sy9qS.gif
new file mode 100644
index 0000000..3f50635
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file10_Left_Null_Space_pSv8iio_d5Sy9qS.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file11.gif b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file11.gif
new file mode 100644
index 0000000..8f74202
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file11.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file12.gif b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file12.gif
new file mode 100644
index 0000000..aa7403b
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file12.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file13.gif b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file13.gif
new file mode 100644
index 0000000..34b54c7
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file13.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file14.gif b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file14.gif
new file mode 100644
index 0000000..b77791b
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file14.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file15.gif b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file15.gif
new file mode 100644
index 0000000..8bb24bf
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file15.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file16.gif b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file16.gif
new file mode 100644
index 0000000..87e0026
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file16.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file17.gif b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file17.gif
new file mode 100644
index 0000000..eec819a
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file17.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file18_NOT_in_lecture_note_Column_Space.py b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file18_NOT_in_lecture_note_Column_Space.py
new file mode 100644
index 0000000..afe4f9a
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file18_NOT_in_lecture_note_Column_Space.py
@@ -0,0 +1,30 @@
+from manimlib.imports import *
+
+class Column_Space(Scene):
+ def construct(self):
+
+ A = TextMobject(r"$A = $",r"$\left( \begin{array}{c c c} 1 & 2 & 1 \\ 1 & 3 & 1 \\ 2 & 1 & 4 \\ 3 & 2 & 3 \end{array} \right)$")
+ A.move_to(2*UP)
+ A[1].set_color(color = DARK_BLUE)
+ A.scale(0.75)
+
+ self.play(Write(A),run_time = 1)
+
+ CS_A = TextMobject(r"Column Space of $A = x_{1}$",r"$\left( \begin{array}{c} 1 \\ 1 \\ 2 \\ 3 \end{array} \right)$",r"$+x_{2}$",r"$ \left( \begin{array}{c} 2 \\ 3 \\ 1 \\ 2 \end{array} \right)$",r"$ + x_{3}$",r"$\left( \begin{array}{c} 1 \\ 1 \\ 4 \\ 3 \end{array} \right)$")
+ CS_A.move_to(1.5*LEFT+1*DOWN)
+ CS_A[1].set_color(color = DARK_BLUE)
+ CS_A[3].set_color(color = DARK_BLUE)
+ CS_A[5].set_color(color = DARK_BLUE)
+ CS_A.scale(0.75)
+
+ self.play(Write(CS_A),run_time = 2)
+
+ arrow1 = Arrow(start = 1.25*UP,end = 0.25*DOWN+1.75*LEFT)
+ arrow2 = Arrow(start = 1.35*UP+0.5*RIGHT,end = 0.25*DOWN+0.5*RIGHT)
+ arrow3 = Arrow(start = 1.25*UP+0.75*RIGHT,end = 0.25*DOWN+2.9*RIGHT)
+
+ Defn = TextMobject("Linear Combination of Columns of Matrix")
+ Defn.move_to(3*DOWN)
+
+ self.play(Write(Defn), ShowCreation(arrow1), ShowCreation(arrow2), ShowCreation(arrow3),run_time = 1)
+ self.wait(1) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file1_Axb.py b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file1_Axb.py
new file mode 100755
index 0000000..95d1021
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file1_Axb.py
@@ -0,0 +1,77 @@
+from manimlib.imports import *
+
+class Axb(Scene):
+
+ def construct(self):
+
+ text0 = TextMobject("Linear System Of Equations")
+ text1 = TextMobject(r"$x_{1}+x_{2}+x_{3} =b_{1}$")
+ text2 = TextMobject(r"$x_{1}+2x_{2}+x_{3} =b_{2}$")
+ text3 = TextMobject(r"$x_{1}+x_{2}+3x_{3} =b_{3}$")
+ text0.move_to(UP*2+LEFT*2)
+ text0.set_color(DARK_BLUE)
+ text1.move_to(UP)
+ text2.move_to(ORIGIN)
+ text3.move_to(DOWN)
+
+ text0.scale(0.75)
+ text1.scale(0.75)
+ text2.scale(0.75)
+ text3.scale(0.75)
+ self.play(Write(text0))
+ self.play(Write(text1))
+ self.play(Write(text2))
+ self.play(Write(text3))
+ self.play(ApplyMethod(text0.move_to,3*UP+LEFT*2), ApplyMethod(text1.move_to,2.5*UP), ApplyMethod(text2.move_to,2*UP), ApplyMethod(text3.move_to,1.5*UP))
+
+ A = TextMobject(r"$\left( \begin{array}{c c c} 1 & 1 & 1 \\ 1 & 2 & 1 \\ 1 & 1 & 3 \end{array}\right) \left[ \begin{array} {c} x_{1} \\ x_{2} \\ x_{3} \end{array}\right] =$", r"$\left[ \begin{array}{c} x_{1}+x_{2}+x_{3} \\ x_{1}+2x_{2}+x_{3} \\ x_{1}+x_{2}+3x_{3} \end{array}\right]$")
+ A.scale(0.75)
+ self.play(FadeIn(A))
+
+ textA = TextMobject("A")
+ textx = TextMobject("x")
+ textb = TextMobject("Ax")
+
+ textA.move_to(DOWN+3*LEFT)
+ textx.move_to(1.1*DOWN+0.5*LEFT)
+ textb.move_to(DOWN-2*LEFT)
+
+ self.play(Write(textA), Write(textx), Write(textb))
+
+ circle1 = Circle(radius = 0.24)
+ circle2 = Circle(radius = 0.24)
+ square = Square(side_length = 0.6)
+
+ circle1.move_to(UP*0.5+LEFT*3.05)
+ circle2.move_to(UP*0.4+LEFT*0.5)
+ square.move_to(UP*0.4+RIGHT*1.3)
+
+ self.play(FadeIn(circle1), FadeIn(circle2),FadeIn(square))
+
+ self.play(ApplyMethod(circle1.move_to,UP*0.5+LEFT*2.45), ApplyMethod(circle2.move_to,LEFT*0.5), ApplyMethod(square.move_to,UP*0.4+RIGHT*2.2))
+ self.play(ApplyMethod(circle1.move_to,UP*0.5+LEFT*1.85), ApplyMethod(circle2.move_to,DOWN*0.5+LEFT*0.5), ApplyMethod(square.move_to,UP*0.4+RIGHT*3.1))
+
+ self.play(ApplyMethod(circle1.move_to,LEFT*3.05), ApplyMethod(circle2.move_to,UP*0.4+LEFT*0.5), ApplyMethod(square.move_to,RIGHT*1.3))
+ self.play(ApplyMethod(circle1.move_to,LEFT*2.45), ApplyMethod(circle2.move_to,LEFT*0.5), ApplyMethod(square.move_to,RIGHT*2.2))
+ self.play(ApplyMethod(circle1.move_to,LEFT*1.85), ApplyMethod(circle2.move_to,DOWN*0.5+LEFT*0.5), ApplyMethod(square.move_to,RIGHT*3.1))
+
+ self.play(ApplyMethod(circle1.move_to,0.4*DOWN+LEFT*3.05), ApplyMethod(circle2.move_to,UP*0.4+LEFT*0.5), ApplyMethod(square.move_to,0.4*DOWN+RIGHT*1.3))
+ self.play(ApplyMethod(circle1.move_to,0.4*DOWN+LEFT*2.45), ApplyMethod(circle2.move_to,LEFT*0.5), ApplyMethod(square.move_to,0.4*DOWN+RIGHT*2.2))
+ self.play(ApplyMethod(circle1.move_to,0.4*DOWN+LEFT*1.85), ApplyMethod(circle2.move_to,DOWN*0.5+LEFT*0.5), ApplyMethod(square.move_to,0.4*DOWN+RIGHT*3.1))
+
+ self.play(FadeOut(circle1), FadeOut(circle2), FadeOut(square))
+ self.play(FadeOut(A[0]), ApplyMethod(A[1].move_to,2*LEFT),ApplyMethod(textb.move_to,DOWN+1.7*LEFT), FadeOut(textx), FadeOut(textA))
+ b = TextMobject(r"$=\left[ \begin{array}{c} b_{1} \\ b_{2} \\ b_{3} \end{array}\right]$")
+ b.move_to(RIGHT)
+ textB = TextMobject("b")
+ textB.move_to(1.2*DOWN+1.1*RIGHT)
+ self.play(FadeIn(b),FadeIn(textB))
+
+ self.wait()
+
+ self.play(FadeOut(text0), FadeOut(text1), FadeOut(text2), FadeOut(text3))
+
+ axb = TextMobject("Ax = b")
+ self.play(FadeIn(axb), FadeOut(textb), FadeOut(textB), FadeOut(b), FadeOut(A[1]))
+
+ self.wait() \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file2_CSasImage.py b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file2_CSasImage.py
new file mode 100644
index 0000000..70547cb
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file2_CSasImage.py
@@ -0,0 +1,169 @@
+from manimlib.imports import *
+
+class Column_Space(Scene):
+ def construct(self):
+
+ A = TextMobject(r"$A = $",r"$\left( \begin{array}{c c} 1 & 2 \\ 3 & 4 \end{array} \right)$")
+ A.move_to(2*UP)
+ A[1].set_color(color = DARK_BLUE)
+ A.scale(0.75)
+
+ self.play(Write(A),run_time = 1)
+
+ CS_A = TextMobject(r"Column Space of $A = x_{1}$",r"$\left( \begin{array}{c} 1 \\ 3 \end{array} \right)$",r"$+x_{2}$",r"$ \left( \begin{array}{c} 2 \\ 4\end{array} \right)$")
+ CS_A.move_to(1.5*LEFT+1*DOWN)
+ CS_A[1].set_color(color = DARK_BLUE)
+ CS_A[3].set_color(color = DARK_BLUE)
+ CS_A.scale(0.75)
+
+ self.play(Write(CS_A),run_time = 2)
+
+ arrow1 = Arrow(start = 1.25*UP,end = (0.25*DOWN+1.75*LEFT+0.25*DOWN+1.2*RIGHT)/2)
+ arrow3 = Arrow(start = 1.25*UP+0.75*RIGHT,end = (0.25*DOWN+2.9*RIGHT+0.25*DOWN)/2)
+
+ arrow1.scale(1.5)
+ arrow3.scale(1.5)
+
+ Defn = TextMobject("Linear Combination of Columns of Matrix")
+ Defn.move_to(3*DOWN)
+
+ self.play(Write(Defn), ShowCreation(arrow1), ShowCreation(arrow3),run_time = 1)
+ self.wait(1)
+
+class solution(LinearTransformationScene):
+ def construct(self):
+
+ self.setup()
+ self.wait()
+
+ o = TextMobject(r"Consider the vector space $R^2$")
+ o.move_to(2*DOWN)
+ o.scale(0.75)
+ o.add_background_rectangle()
+ self.play(Write(o))
+ self.wait()
+ self.play(FadeOut(o))
+
+ A = TextMobject(r"Let $A$ be ",r"$\left[\begin{array}{c c} 1 & -1 \\ 1 & -1 \end{array}\right]$",r". $A$ denotes the matrix the of this linear transformation.")
+ A.move_to(2*DOWN)
+ A.scale(0.75)
+ A.add_background_rectangle()
+ self.play(Write(A))
+ matrix = [[1,-1],[1,-1]]
+ self.apply_matrix(matrix)
+ self.wait()
+ self.play(FadeOut(A))
+
+ o = TextMobject(r"This is the transformed vector space")
+ o.move_to(2*DOWN)
+ o.scale(0.75)
+ o.add_background_rectangle()
+ self.play(Write(o))
+ self.wait()
+ self.play(FadeOut(o))
+
+ texti = TextMobject(r"$\left[\begin{array}{c}1\\1\end{array}\right]$")
+ textj = TextMobject(r"$\left[\begin{array}{c}-1\\-1\end{array}\right]$")
+ texti.set_color(GREEN)
+ textj.set_color(RED)
+ texti.scale(0.7)
+ textj.scale(0.7)
+ texti.move_to(1.35*RIGHT+0.5*UP)
+ textj.move_to(-(1.5*RIGHT+0.5*UP))
+
+ text1 = TextMobject("[")
+ text2 = TextMobject(r"$\begin{array}{c} 1 \\ 1 \end{array}$")
+ text3 = TextMobject(r"$\begin{array}{c} -1 \\ -1 \end{array}$")
+ text4 = TextMobject("]")
+
+ text2.set_color(GREEN)
+ text3.set_color(RED)
+
+ text1.scale(2)
+ text4.scale(2)
+ text2.scale(0.7)
+ text3.scale(0.7)
+
+ text1.move_to(2.5*UP+6*LEFT)
+ text2.move_to(2.5*UP+5.75*LEFT)
+ text3.move_to(2.5*UP+5.25*LEFT)
+ text4.move_to(2.5*UP+5*LEFT)
+
+ self.play(Write(texti), Write(textj))
+ self.wait()
+ self.play(FadeIn(text1), Transform(texti,text2), Transform(textj,text3), FadeIn(text4))
+ self.wait()
+
+ o = TextMobject(r"Now, you can observe the Image of Linear Transformation")
+ o1 = TextMobject(r"and Column Space(i.e. span of columns of matrix $A$) are same")
+ o.move_to(2.5*DOWN)
+ o1.move_to(3*DOWN)
+ o.scale(0.75)
+ o1.scale(0.75)
+ o.add_background_rectangle()
+ o1.add_background_rectangle()
+ self.play(Write(o))
+ self.play(Write(o1))
+ self.wait()
+ self.play(FadeOut(o),FadeOut(o1))
+
+class solution2nd(LinearTransformationScene):
+ def construct(self):
+
+ self.setup()
+ self.wait()
+
+ arrow1 = Arrow(start = ORIGIN,end = 2*DOWN+RIGHT)
+ arrow2 = Arrow(start = ORIGIN,end = UP+LEFT)
+ arrow3 = Arrow(start = ORIGIN,end = 3*UP+4*RIGHT)
+ arrow1.set_color(YELLOW)
+ arrow2.set_color(ORANGE)
+ arrow3.set_color(PURPLE)
+ arrow1.scale(1.3)
+ arrow2.scale(1.5)
+ arrow3.scale(1.1)
+
+ self.play(ShowCreation(arrow1), ShowCreation(arrow2), ShowCreation(arrow3))
+
+ self.add_transformable_mobject(arrow1)
+ self.add_transformable_mobject(arrow2)
+ self.add_transformable_mobject(arrow3)
+ o = TextMobject(r"Consider any vector in the original vector space $R^2$")
+ o.move_to(2.5*DOWN)
+ o.scale(0.75)
+ o.add_background_rectangle()
+ self.play(Write(o))
+ self.wait()
+ self.play(FadeOut(o))
+
+ A = TextMobject(r"Let the matrix the of this linear transformation be $A$ =",r"$\left[\begin{array}{c c} 1 & -1 \\ 1 & -1 \end{array}\right]$",r" again.")
+ A.move_to(2*DOWN)
+ A.scale(0.75)
+ A.add_background_rectangle()
+ self.play(Write(A))
+ matrix = [[1,-1],[1,-1]]
+ self.apply_matrix(matrix)
+ self.wait()
+ self.play(FadeOut(A))
+
+ o = TextMobject(r"This is the transformed vector space")
+ o.move_to(2*DOWN)
+ o.scale(0.75)
+ o.add_background_rectangle()
+ self.play(Write(o))
+ self.wait()
+ self.play(FadeOut(o))
+
+ o = TextMobject(r"Each and every vector of original vector space $R^2$ will transform")
+ o1 = TextMobject(r"to this new vector space which is spanned by $\mathbf{CS}(A)$")
+ o.move_to(2.5*DOWN)
+ o1.move_to(3*DOWN)
+ o.scale(0.75)
+ o1.scale(0.75)
+ o.add_background_rectangle()
+ o1.add_background_rectangle()
+ self.play(Write(o))
+ self.play(Write(o1))
+ self.wait()
+ self.play(FadeOut(o))
+ self.play(FadeOut(o1)) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file3_solution.py b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file3_solution.py
new file mode 100644
index 0000000..eb310f3
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file3_solution.py
@@ -0,0 +1,77 @@
+from manimlib.imports import *
+class solution(LinearTransformationScene):
+ def construct(self):
+
+ self.setup()
+ self.wait()
+
+ o = TextMobject(r"This is the original vector space $R^2$ (before Linear Transformation)")
+ o.move_to(3*DOWN)
+ o.scale(0.75)
+ o.add_background_rectangle()
+ self.play(Write(o))
+ self.wait()
+ self.play(FadeOut(o))
+
+ A = TextMobject(r"Consider the matrix the of this linear transformation $A$ = $\left[\begin{array}{c c} 1 & -1 \\ 1 & -1 \end{array}\right]$")
+ A.move_to(3*DOWN)
+ A.scale(0.75)
+ A.add_background_rectangle()
+ self.play(Write(A))
+ matrix = [[1,-1],[1,-1]]
+ self.apply_matrix(matrix)
+ self.wait()
+ self.play(FadeOut(A))
+
+ o = TextMobject(r"This is the transformed vector space")
+ o.move_to(3*DOWN)
+ o.scale(0.75)
+ o.add_background_rectangle()
+ self.play(Write(o))
+ self.wait()
+ self.play(FadeOut(o))
+
+ arrow2 = Arrow(start = ORIGIN, end = 2*DOWN+2*LEFT)
+ arrow2.set_color(PURPLE)
+ arrow2.scale(1.2)
+ self.play(ShowCreation(arrow2))
+ self.wait()
+
+ o1 = TextMobject("If the ","vector b"," lies in the transformed vector space")
+ o2 = TextMobject("(the line) then the solution exist")
+ o1.move_to(2.5*DOWN+2*RIGHT)
+ o1[1].set_color(PURPLE)
+ o2.move_to(3*DOWN+2.5*RIGHT)
+ o1.scale(0.75)
+ o2.scale(0.75)
+ o1.add_background_rectangle()
+ o2.add_background_rectangle()
+ self.play(Write(o1))
+ self.play(Write(o2))
+ self.wait()
+ self.play(FadeOut(o1), FadeOut(o2))
+
+ self.play(FadeOut(arrow2))
+
+ arrow1 = Arrow(start = ORIGIN, end = 2*UP+RIGHT)
+ arrow1.set_color(ORANGE)
+ arrow1.scale(1.3)
+ self.play(ShowCreation(arrow1))
+ self.wait()
+
+ o1 = TextMobject("If the ","vector b"," does lies in the transformed")
+ o2 = TextMobject("vector space then the does not solution exist")
+ o1.move_to(2.5*DOWN+2*RIGHT)
+ o1[1].set_color(ORANGE)
+ o2.move_to(3*DOWN+2.5*RIGHT)
+ o1.scale(0.75)
+ o2.scale(0.75)
+ o1.add_background_rectangle()
+ o2.add_background_rectangle()
+ self.play(Write(o1))
+ self.play(Write(o2))
+ self.wait()
+ self.play(FadeOut(o1), FadeOut(o2))
+
+ self.play(FadeOut(arrow1))
+ \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file4_null_space.py b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file4_null_space.py
new file mode 100644
index 0000000..3c52677
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file4_null_space.py
@@ -0,0 +1,91 @@
+from manimlib.imports import *
+class null_space(LinearTransformationScene):
+ def construct(self):
+
+ self.setup()
+ self.wait()
+
+ o = TextMobject(r"This is the original vector space $R^2$(before Linear Transformation)")
+ o.move_to(3*DOWN)
+ o.scale(0.75)
+ o.add_background_rectangle()
+ self.play(Write(o))
+ self.wait()
+ self.play(FadeOut(o))
+
+ o1 = TextMobject("Consider a set of vectors which are linear")
+ o2 = TextMobject(r"span of a particular vector $\left(\begin{array}{c} 1 \\ 1 \end{array}\right)$")
+ o1.move_to(2*DOWN+3*RIGHT)
+ o2.move_to(2.75*DOWN+3*RIGHT)
+ o1.scale(0.7)
+ o2.scale(0.7)
+ o1.add_background_rectangle()
+ o2.add_background_rectangle()
+ self.play(Write(o1))
+ self.play(Write(o2))
+
+ arrow = Arrow(start = ORIGIN, end = UP+RIGHT)
+ arrow1 = Arrow(start = ORIGIN, end = 2*(UP+RIGHT))
+ arrow2 = Arrow(start = ORIGIN, end = 3*(UP+RIGHT))
+ arrow3 = Arrow(start = ORIGIN, end = 4*(UP+RIGHT))
+ arrow4 = Arrow(start = ORIGIN, end = DOWN+LEFT)
+ arrow5 = Arrow(start = ORIGIN, end = 2*(DOWN+LEFT))
+ arrow6 = Arrow(start = ORIGIN, end = 3*(DOWN+LEFT))
+ arrow7 = Arrow(start = ORIGIN, end = 4*(DOWN+LEFT))
+
+ arrow.scale(1.5)
+ arrow1.scale(1.2)
+ arrow2.scale(1.15)
+ arrow3.scale(1.1)
+ arrow4.scale(1.5)
+ arrow5.scale(1.2)
+ arrow6.scale(1.15)
+ arrow7.scale(1.1)
+
+ self.play(ShowCreation(arrow),
+ ShowCreation(arrow1),
+ ShowCreation(arrow2),
+ ShowCreation(arrow3),
+ ShowCreation(arrow4),
+ ShowCreation(arrow5),
+ ShowCreation(arrow6),
+ ShowCreation(arrow7),
+ )
+
+ self.wait(2)
+ self.play(FadeOut(o1), FadeOut(o2))
+
+ self.add_transformable_mobject(arrow)
+ self.add_transformable_mobject(arrow1)
+ self.add_transformable_mobject(arrow2)
+ self.add_transformable_mobject(arrow3)
+ self.add_transformable_mobject(arrow4)
+ self.add_transformable_mobject(arrow5)
+ self.add_transformable_mobject(arrow6)
+ self.add_transformable_mobject(arrow7)
+
+ o1 = TextMobject("Notice, entire set of vectors which belongs to the vector")
+ o2 = TextMobject(r"subspace(Linear Span of $\left(\begin{array}{c} 1 \\ 1 \end{array}\right)$) transforms to zero")
+ o1.move_to(2*DOWN+2.5*RIGHT)
+ o2.move_to(2.75*DOWN+2.5*RIGHT)
+ o1.scale(0.7)
+ o2.scale(0.7)
+ o1.add_background_rectangle()
+ o2.add_background_rectangle()
+ self.play(Write(o1))
+ self.play(Write(o2))
+ self.wait()
+
+ matrix = [[1,-1],[1,-1]]
+ self.apply_matrix(matrix)
+ self.wait()
+
+ self.play(FadeOut(o1), FadeOut(o2))
+
+ o = TextMobject(r"Hence, the vector space formed by linear span of $\left(\begin{array}{c} 1 \\ 1 \end{array}\right)$ is the null space of $A$")
+ o.move_to(3*DOWN)
+ o.scale(0.75)
+ o.add_background_rectangle()
+ self.play(Write(o))
+ self.wait(2)
+ self.play(FadeOut(o), FadeOut(arrow), FadeOut(arrow1), FadeOut(arrow2), FadeOut(arrow3), FadeOut(arrow4), FadeOut(arrow5), FadeOut(arrow6), FadeOut(arrow7))
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file5_Row_Space_part_1.py b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file5_Row_Space_part_1.py
new file mode 100644
index 0000000..5259eb4
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file5_Row_Space_part_1.py
@@ -0,0 +1,68 @@
+from manimlib.imports import *
+class LS(Scene):
+ def construct(self):
+ text1 = TextMobject(r"Consider a matrix $A =$")
+ text2 = TextMobject(r"[")
+ text3 = TextMobject(r"$\begin{array}{c c} 1 & -2\end{array}$")
+ text4 = TextMobject(r"$\begin{array}{c c} 1 & -1\end{array}$")
+ text5 = TextMobject(r"]")
+
+ text2.scale(2)
+ text5.scale(2)
+
+ text1.set_color(DARK_BLUE)
+ text2.set_color(DARK_BLUE)
+ text3.set_color(PURPLE)
+ text4.set_color(YELLOW)
+ text5.set_color(DARK_BLUE)
+
+ text1.move_to(3.5*LEFT+3*UP+2*RIGHT)
+ text2.move_to(0.75*LEFT+3*UP+2*RIGHT)
+ text3.move_to(3.25*UP+2*RIGHT)
+ text4.move_to(2.75*UP+2*RIGHT)
+ text5.move_to(0.75*RIGHT+3*UP+2*RIGHT)
+
+ self.play(FadeIn(text1), FadeIn(text2), FadeIn(text3), FadeIn(text4), FadeIn(text5))
+ self.wait()
+
+ ttext1 = TextMobject(r"$A^T =$")
+ ttext2 = TextMobject(r"[")
+ ttext3 = TextMobject(r"$\begin{array}{c} 1 \\ -2\end{array}$")
+ ttext4 = TextMobject(r"$\begin{array}{c} 1 \\ -1\end{array}$")
+ ttext5 = TextMobject(r"]")
+
+ ttext2.scale(2)
+ ttext5.scale(2)
+
+ ttext1.set_color(DARK_BLUE)
+ ttext2.set_color(DARK_BLUE)
+ ttext3.set_color(PURPLE)
+ ttext4.set_color(YELLOW)
+ ttext5.set_color(DARK_BLUE)
+
+ ttext1.move_to(2*LEFT+1.5*UP+2*RIGHT)
+ ttext2.move_to(1*LEFT+1.5*UP+2*RIGHT)
+ ttext3.move_to(0.5*LEFT+1.5*UP+2*RIGHT)
+ ttext4.move_to(0.5*RIGHT+1.5*UP+2*RIGHT)
+ ttext5.move_to(1*RIGHT+1.5*UP+2*RIGHT)
+
+ self.play(FadeIn(ttext1), FadeIn(ttext2), FadeIn(ttext3), FadeIn(ttext4), FadeIn(ttext5))
+
+ rtext = TextMobject(r"Row Space of $A$ = Column Space of $A^T = a_1$",r"$\left[\begin{array}{c} 1 \\ -2\end{array}\right]$",r"$+a_2$",r"$\left[\begin{array}{c} 1 \\ -1\end{array}\right]$")
+ rtext[1].set_color(PURPLE)
+ rtext[3].set_color(YELLOW)
+ rtext.move_to(2*DOWN+1.5*LEFT)
+ rtext.scale(0.75)
+
+ self.play(Write(rtext))
+ self.wait()
+
+ arrow1 = Arrow(start = 1.5*RIGHT+UP, end = 1.25*(DOWN+RIGHT))
+ arrow2 = Arrow(start = 2.5*RIGHT+UP, end = 1.25*DOWN+3.25*RIGHT)
+ arrow1.scale(1.25)
+ arrow2.scale(1.25)
+ arrow1.set_color(PURPLE)
+ arrow2.set_color(YELLOW)
+
+ self.play(ShowCreation(arrow1), ShowCreation(arrow2))
+ self.wait(2)
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file6_Row_Space_part_2.py b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file6_Row_Space_part_2.py
new file mode 100644
index 0000000..b16a32a
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file6_Row_Space_part_2.py
@@ -0,0 +1,145 @@
+from manimlib.imports import *
+
+class Row_Space(Scene):
+ def construct(self):
+
+ Heading = TextMobject("Row Space")
+ defn1 = TextMobject("Definition 1: Row Space of a matrix is the linear combination of the rows of that matrix.")
+ defn2 = TextMobject("Definition 2: It is a vector space generated by a linear combination of the columns of $A^{T}$.")
+ equivalent = TextMobject(r"Definition 1 $\equiv$ Definition 2")
+
+ Heading.move_to(2*UP)
+ Heading.set_color(color = DARK_BLUE)
+
+ defn1.move_to(UP)
+ defn1.scale(0.75)
+
+ defn2.scale(0.75)
+
+ equivalent.move_to(DOWN)
+
+ self.play(Write(Heading))
+ self.play(Write(defn1))
+ self.play(Write(defn2))
+ self.play(Write(equivalent))
+
+ self.wait(2)
+ self.play(FadeOut(Heading),FadeOut(defn1),FadeOut(defn2),ApplyMethod(equivalent.move_to,2*UP))
+
+ how = TextMobject("Let us see, How?")
+ how.move_to(UP)
+ self.play(Write(how))
+ self.play(FadeOut(equivalent),FadeOut(how))
+
+ A = TextMobject(r"$A = $",r"$\left( \begin{array}{c c c} 1 & 2 & 1 \\ 1 & 3 & 1 \\ 2 & 1 & 4 \\ 3 & 2 & 3 \end{array} \right)$")
+ A.move_to(2*UP+3*LEFT)
+ A[1].set_color(color = DARK_BLUE)
+ A.scale(0.80)
+
+ self.play(Write(A))
+
+ rows = TextMobject(r"Rows of A $\rightarrow$",
+ r"$\left( \begin{array}{c c c} 1 & 2 & 1 \end{array} \right)$,",
+ r"$ \left( \begin{array}{c c c} 1 & 3 & 1 \end{array} \right)$,",
+ r"$\left( \begin{array}{c c c} 2 & 1 & 4 \end{array} \right)$,",
+ r"$ \left( \begin{array}{c c c} 3 & 2 & 3 \end{array} \right)$")
+ rows.scale(0.75)
+ rows[1:5].set_color(DARK_BLUE)
+ self.play(Write(rows))
+
+ ac_defn1 = TextMobject("According to Definition 1 : ")
+ ac_defn1.move_to(DOWN)
+
+ RS_A = TextMobject(r"Row Space of $A = x_{1}$",
+ r"$\left( \begin{array}{c c c} 1 & 2 & 1 \end{array} \right)$",
+ r"$+x_{2}$",
+ r"$ \left( \begin{array}{c c c} 1 & 3 & 1 \end{array} \right)$",
+ r"$ + x_{3}$",
+ r"$\left( \begin{array}{c c c} 2 & 1 & 4 \end{array} \right)$",
+ r"$+x_{4}$",
+ r"$ \left( \begin{array}{c c c} 3 & 2 & 3 \end{array} \right)$")
+ RS_A.move_to(DOWN+DOWN)
+ RS_A[6].move_to(2*DOWN+DOWN)
+ RS_A[7].move_to(2*DOWN+2*RIGHT+DOWN)
+ RS_A[1].set_color(color = DARK_BLUE)
+ RS_A[3].set_color(color = DARK_BLUE)
+ RS_A[5].set_color(color = DARK_BLUE)
+ RS_A[7].set_color(color = DARK_BLUE)
+ RS_A.scale(0.75)
+
+ self.play(FadeOut(rows[0]),Transform(rows[1],RS_A[1]),Transform(rows[2],RS_A[3]),Transform(rows[3],RS_A[5]),Transform(rows[4],RS_A[7]))
+ self.play(FadeIn(ac_defn1), Write(RS_A))
+ self.wait(1)
+
+ self.play(FadeOut(rows[1]), FadeOut(rows[2]), FadeOut(rows[3]), FadeOut(rows[4]), FadeOut(RS_A), FadeOut(ac_defn1))
+
+ A_T = TextMobject(r"$A^{T} = $",r"$\left( \begin{array}{c c c c} 1 & 1 & 2 & 3 \\ 2 & 3 & 1 & 2 \\ 1 & 1 & 4 & 3 \end{array} \right)$")
+ A_T.move_to(2*UP+3*RIGHT)
+ A_T[1].set_color(color = DARK_BLUE)
+ A_T.scale(0.80)
+
+ self.play(Write(A_T))
+
+ change1 = TextMobject(r"Rows of $A\equiv$ Columns of $A^{T}$")
+ change2 = TextMobject(r"Columns of $A\equiv$ Rows of $A^{T}$")
+ change2.move_to(DOWN)
+
+ change3 = TextMobject(r"Row Space of $A$ = Linear Combination of",r"Rows","of",r"A")
+ change3.move_to(2*DOWN)
+ change3[1].set_color(DARK_BLUE)
+ change3[3].set_color(DARK_BLUE)
+
+ self.play(Write(change1))
+ self.play(Write(change2))
+ self.play(Write(change3))
+
+ columns = TextMobject("Columns")
+ columns.scale(0.6)
+ columns.set_color(DARK_BLUE)
+ columns.move_to(2*DOWN+4.1*RIGHT)
+
+ a = TextMobject(r"$A^{T}$")
+ a.set_color(DARK_BLUE)
+ a.move_to(1.95*DOWN+5.6*RIGHT)
+
+ self.wait(0.5)
+
+ self.play(Transform(change3[1],columns), Transform(change3[3],a))
+
+ equal = TextMobject(r"= Column Space($A^{T}$)")
+ equal.move_to(3*DOWN+0.5*RIGHT)
+
+ self.play(Write(equal))
+
+ self.play(FadeOut(A_T), FadeOut(change1), FadeOut(change2), FadeOut(change3), FadeOut(A), FadeOut(equal))
+
+ ac_defn1.move_to(3*UP)
+ RS_A.move_to(1.5*UP)
+ RS_A[6].move_to(UP)
+ RS_A[7].move_to(UP+1.5*RIGHT)
+
+ self.play(Write(RS_A),FadeIn(ac_defn1))
+
+ CS_AT = TextMobject(r"Row Space of $A = x_{1}$",
+ r"$\left( \begin{array}{c} 1 \\ 2 \\ 1 \end{array} \right)$",
+ r"$+x_{2}$",
+ r"$ \left( \begin{array}{c} 1 \\ 3 \\ 1 \end{array} \right)$",
+ r"$ + x_{3}$",
+ r"$\left( \begin{array}{c} 2 \\ 1 \\ 4 \end{array} \right)$",
+ r"$+x_{4}$",
+ r"$ \left( \begin{array}{c} 3 \\ 2 \\ 3 \end{array} \right)$")
+ CS_AT.move_to(1.5*DOWN)
+ CS_AT[1].set_color(color = DARK_BLUE)
+ CS_AT[3].set_color(color = DARK_BLUE)
+ CS_AT[5].set_color(color = DARK_BLUE)
+ CS_AT[7].set_color(color = DARK_BLUE)
+ CS_AT.scale(0.75)
+
+ ac_defn2 = TextMobject("According to Definition 2 : ")
+ equivalent = TextMobject(r"Hence, Definition 1 $\equiv$ Definition 2")
+ equivalent.move_to(3*DOWN)
+
+ self.play(Write(CS_AT),FadeIn(ac_defn2))
+ self.play(Write(equivalent))
+
+ self.wait()
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file7_Row_space_Orthogonal_Complements.py b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file7_Row_space_Orthogonal_Complements.py
new file mode 100644
index 0000000..c81d370
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file7_Row_space_Orthogonal_Complements.py
@@ -0,0 +1,150 @@
+from manimlib.imports import *
+class row_space(LinearTransformationScene):
+ def construct(self):
+
+ self.setup()
+ self.wait()
+
+ o = TextMobject(r"This is the original vector space $R^2$(before Linear Transformation)")
+ o.move_to(DOWN)
+ o.scale(0.75)
+ o.add_background_rectangle()
+ self.play(Write(o))
+ self.wait()
+ self.play(FadeOut(o))
+
+ o1 = TextMobject("Consider a set of vectors which are linear")
+ o2 = TextMobject(r"span of a $\left(\begin{array}{c} 1 \\ 1 \end{array}\right)$i.e. the null space.")
+ o1.move_to(2*DOWN+3*RIGHT)
+ o2.move_to(2.75*DOWN+3*RIGHT)
+ o1.scale(0.7)
+ o2.scale(0.7)
+ o1.add_background_rectangle()
+ o2.add_background_rectangle()
+ self.play(Write(o1))
+ self.play(Write(o2))
+
+ arrow = Arrow(start = ORIGIN, end = UP+RIGHT)
+ arrow.set_color(YELLOW)
+ arrow1 = Arrow(start = ORIGIN, end = 2*(UP+RIGHT))
+ arrow1.set_color(YELLOW)
+ arrow2 = Arrow(start = ORIGIN, end = 3*(UP+RIGHT))
+ arrow2.set_color(YELLOW)
+ arrow3 = Arrow(start = ORIGIN, end = 4*(UP+RIGHT))
+ arrow3.set_color(YELLOW)
+ arrow4 = Arrow(start = ORIGIN, end = DOWN+LEFT)
+ arrow4.set_color(YELLOW)
+ arrow5 = Arrow(start = ORIGIN, end = 2*(DOWN+LEFT))
+ arrow5.set_color(YELLOW)
+ arrow6 = Arrow(start = ORIGIN, end = 3*(DOWN+LEFT))
+ arrow6.set_color(YELLOW)
+ arrow7 = Arrow(start = ORIGIN, end = 4*(DOWN+LEFT))
+ arrow7.set_color(YELLOW)
+
+ arrow.scale(1.5)
+ arrow1.scale(1.2)
+ arrow2.scale(1.15)
+ arrow3.scale(1.1)
+ arrow4.scale(1.5)
+ arrow5.scale(1.2)
+ arrow6.scale(1.15)
+ arrow7.scale(1.1)
+
+ self.play(ShowCreation(arrow),
+ ShowCreation(arrow1),
+ ShowCreation(arrow2),
+ ShowCreation(arrow3),
+ ShowCreation(arrow4),
+ ShowCreation(arrow5),
+ ShowCreation(arrow6),
+ ShowCreation(arrow7),
+ )
+
+ self.wait(2)
+ self.play(FadeOut(o1), FadeOut(o2))
+
+ o1 = TextMobject("Consider a set of vectors which are linear")
+ o2 = TextMobject(r"span of a $\left(\begin{array}{c} 1 \\ -1 \end{array}\right)$i.e. the row space.")
+ o1.move_to(2*DOWN+3*RIGHT)
+ o2.move_to(2.75*DOWN+3*RIGHT)
+ o1.scale(0.7)
+ o2.scale(0.7)
+ o1.add_background_rectangle()
+ o2.add_background_rectangle()
+ self.play(Write(o1))
+ self.play(Write(o2))
+
+ rarrow = Arrow(start = ORIGIN, end = -UP+RIGHT)
+ rarrow.set_color(PURPLE)
+ rarrow1 = Arrow(start = ORIGIN, end = 2*(-UP+RIGHT))
+ rarrow1.set_color(PURPLE)
+ rarrow2 = Arrow(start = ORIGIN, end = 3*(-UP+RIGHT))
+ rarrow2.set_color(PURPLE)
+ rarrow3 = Arrow(start = ORIGIN, end = 4*(-UP+RIGHT))
+ rarrow3.set_color(PURPLE)
+ rarrow4 = Arrow(start = ORIGIN, end = -DOWN+LEFT)
+ rarrow4.set_color(PURPLE)
+ rarrow5 = Arrow(start = ORIGIN, end = 2*(-DOWN+LEFT))
+ rarrow5.set_color(PURPLE)
+ rarrow6 = Arrow(start = ORIGIN, end = 3*(-DOWN+LEFT))
+ rarrow6.set_color(PURPLE)
+ rarrow7 = Arrow(start = ORIGIN, end = 4*(-DOWN+LEFT))
+ rarrow7.set_color(PURPLE)
+
+ rarrow.scale(1.5)
+ rarrow1.scale(1.2)
+ rarrow2.scale(1.15)
+ rarrow3.scale(1.1)
+ rarrow4.scale(1.5)
+ rarrow5.scale(1.2)
+ rarrow6.scale(1.15)
+ rarrow7.scale(1.1)
+
+ self.play(ShowCreation(rarrow),
+ ShowCreation(rarrow1),
+ ShowCreation(rarrow2),
+ ShowCreation(rarrow3),
+ ShowCreation(rarrow4),
+ ShowCreation(rarrow5),
+ ShowCreation(rarrow6),
+ ShowCreation(rarrow7),
+ )
+
+ self.wait(2)
+ self.play(FadeOut(o1), FadeOut(o2))
+
+ self.add_transformable_mobject(arrow)
+ self.add_transformable_mobject(arrow1)
+ self.add_transformable_mobject(arrow2)
+ self.add_transformable_mobject(arrow3)
+ self.add_transformable_mobject(arrow4)
+ self.add_transformable_mobject(arrow5)
+ self.add_transformable_mobject(arrow6)
+ self.add_transformable_mobject(arrow7)
+
+ self.add_transformable_mobject(rarrow)
+ self.add_transformable_mobject(rarrow1)
+ self.add_transformable_mobject(rarrow2)
+ self.add_transformable_mobject(rarrow3)
+ self.add_transformable_mobject(rarrow4)
+ self.add_transformable_mobject(rarrow5)
+ self.add_transformable_mobject(rarrow6)
+ self.add_transformable_mobject(rarrow7)
+
+ o1 = TextMobject("Notice, entire set of vectors which belong to the null space of $A$ transforms to zero")
+ o2 = TextMobject(r"and entire set of vectors which belong to the row space of $A$ transforms to column space of $A$.")
+ o1.move_to(2.5*DOWN)
+ o2.move_to(3.5*DOWN)
+ o1.scale(0.7)
+ o2.scale(0.7)
+ o1.add_background_rectangle()
+ o2.add_background_rectangle()
+ self.play(Write(o1))
+ self.play(Write(o2))
+ self.wait()
+
+ matrix = [[1,-1],[1,-1]]
+ self.apply_matrix(matrix)
+ self.wait(3)
+
+ self.play(FadeOut(o1), FadeOut(o2)) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file8_Left_Null_Space.py b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file8_Left_Null_Space.py
new file mode 100755
index 0000000..fd05e75
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file8_Left_Null_Space.py
@@ -0,0 +1,26 @@
+from manimlib.imports import *
+
+class Left_Null_Space(Scene):
+ def construct(self):
+
+ A = TextMobject(r"Left Null Space of A")
+ A.move_to(3*UP)
+ defn = TextMobject(r"It is a vector space that consists of all the solution $x$ to the equation $A^{T}x=0$")
+ defn.move_to(2*UP)
+ defn.scale(0.75)
+ eqn1 = TextMobject(r"$A^{T}x=0 \cdots (i)$")
+ eqn1.move_to(UP)
+ self.play(Write(A), Write(defn), Write(eqn1),run_time=1)
+ statement = TextMobject(r"Taking transpose of eqn $(i)$")
+ eqn = TextMobject(r"$(A^{T}x)^{T}=0$")
+ eqn.move_to(DOWN)
+ eqn2 = TextMobject(r"$x^{T}(A^{T})^{T}=0$")
+ eqn2.move_to(DOWN)
+ eqn3 = TextMobject(r"$x^{T}A=0$")
+ eqn3.move_to(DOWN)
+ self.play(Write(statement),Write(eqn),run_time=1)
+ self.wait(0.5)
+ self.play(Transform(eqn,eqn2),run_time=1)
+ self.wait(0.5)
+ self.play(Transform(eqn,eqn3),run_time=1)
+ self.wait(0.5) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file9_left_null_space.py b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file9_left_null_space.py
new file mode 100644
index 0000000..61285be
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Four-Fundamental-Subspaces/file9_left_null_space.py
@@ -0,0 +1,186 @@
+from manimlib.imports import *
+class row_space(LinearTransformationScene):
+ def construct(self):
+
+ self.setup()
+ self.wait()
+
+ o = TextMobject(r"This is the original vector space $R^2$(before Linear Transformation)")
+ o.move_to(DOWN)
+ o.scale(0.75)
+ o.add_background_rectangle()
+ self.play(Write(o))
+ self.wait()
+ self.play(FadeOut(o))
+
+ o1 = TextMobject("Consider a set of vectors which are linear")
+ o2 = TextMobject(r"span of a $\left(\begin{array}{c} 1 \\ 1 \end{array}\right)$i.e. the null space.")
+ o1.move_to(2*DOWN+3*RIGHT)
+ o2.move_to(2.75*DOWN+3*RIGHT)
+ o1.scale(0.7)
+ o2.scale(0.7)
+ o1.add_background_rectangle()
+ o2.add_background_rectangle()
+ self.play(Write(o1))
+ self.play(Write(o2))
+
+ arrow = Arrow(start = ORIGIN, end = UP+RIGHT)
+ arrow.set_color(YELLOW)
+ arrow1 = Arrow(start = ORIGIN, end = 2*(UP+RIGHT))
+ arrow1.set_color(YELLOW)
+ arrow2 = Arrow(start = ORIGIN, end = 3*(UP+RIGHT))
+ arrow2.set_color(YELLOW)
+ arrow3 = Arrow(start = ORIGIN, end = 4*(UP+RIGHT))
+ arrow3.set_color(YELLOW)
+ arrow4 = Arrow(start = ORIGIN, end = DOWN+LEFT)
+ arrow4.set_color(YELLOW)
+ arrow5 = Arrow(start = ORIGIN, end = 2*(DOWN+LEFT))
+ arrow5.set_color(YELLOW)
+ arrow6 = Arrow(start = ORIGIN, end = 3*(DOWN+LEFT))
+ arrow6.set_color(YELLOW)
+ arrow7 = Arrow(start = ORIGIN, end = 4*(DOWN+LEFT))
+ arrow7.set_color(YELLOW)
+
+ arrow.scale(1.5)
+ arrow1.scale(1.2)
+ arrow2.scale(1.15)
+ arrow3.scale(1.1)
+ arrow4.scale(1.5)
+ arrow5.scale(1.2)
+ arrow6.scale(1.15)
+ arrow7.scale(1.1)
+
+ self.play(ShowCreation(arrow),
+ ShowCreation(arrow1),
+ ShowCreation(arrow2),
+ ShowCreation(arrow3),
+ ShowCreation(arrow4),
+ ShowCreation(arrow5),
+ ShowCreation(arrow6),
+ ShowCreation(arrow7),
+ )
+
+ self.wait(2)
+ self.play(FadeOut(o1), FadeOut(o2))
+
+ o1 = TextMobject("Consider a set of vectors which are linear")
+ o2 = TextMobject(r"span of a vector $\left(\begin{array}{c} 1 \\ -1 \end{array}\right)$i.e. the row space.")
+ o1.move_to(2*DOWN+3*RIGHT)
+ o2.move_to(2.75*DOWN+3*RIGHT)
+ o1.scale(0.7)
+ o2.scale(0.7)
+ o1.add_background_rectangle()
+ o2.add_background_rectangle()
+ self.play(Write(o1))
+ self.play(Write(o2))
+
+ rarrow = Arrow(start = ORIGIN, end = -UP+RIGHT)
+ rarrow.set_color(PURPLE)
+ rarrow1 = Arrow(start = ORIGIN, end = 2*(-UP+RIGHT))
+ rarrow1.set_color(PURPLE)
+ rarrow2 = Arrow(start = ORIGIN, end = 3*(-UP+RIGHT))
+ rarrow2.set_color(PURPLE)
+ rarrow3 = Arrow(start = ORIGIN, end = 4*(-UP+RIGHT))
+ rarrow3.set_color(PURPLE)
+ rarrow4 = Arrow(start = ORIGIN, end = -DOWN+LEFT)
+ rarrow4.set_color(PURPLE)
+ rarrow5 = Arrow(start = ORIGIN, end = 2*(-DOWN+LEFT))
+ rarrow5.set_color(PURPLE)
+ rarrow6 = Arrow(start = ORIGIN, end = 3*(-DOWN+LEFT))
+ rarrow6.set_color(PURPLE)
+ rarrow7 = Arrow(start = ORIGIN, end = 4*(-DOWN+LEFT))
+ rarrow7.set_color(PURPLE)
+
+ rarrow.scale(1.5)
+ rarrow1.scale(1.2)
+ rarrow2.scale(1.15)
+ rarrow3.scale(1.1)
+ rarrow4.scale(1.5)
+ rarrow5.scale(1.2)
+ rarrow6.scale(1.15)
+ rarrow7.scale(1.1)
+
+ self.play(ShowCreation(rarrow),
+ ShowCreation(rarrow1),
+ ShowCreation(rarrow2),
+ ShowCreation(rarrow3),
+ ShowCreation(rarrow4),
+ ShowCreation(rarrow5),
+ ShowCreation(rarrow6),
+ ShowCreation(rarrow7),
+ )
+
+ self.wait(2)
+ self.play(FadeOut(o1), FadeOut(o2))
+
+ self.add_transformable_mobject(arrow)
+ self.add_transformable_mobject(arrow1)
+ self.add_transformable_mobject(arrow2)
+ self.add_transformable_mobject(arrow3)
+ self.add_transformable_mobject(arrow4)
+ self.add_transformable_mobject(arrow5)
+ self.add_transformable_mobject(arrow6)
+ self.add_transformable_mobject(arrow7)
+
+ self.add_transformable_mobject(rarrow)
+ self.add_transformable_mobject(rarrow1)
+ self.add_transformable_mobject(rarrow2)
+ self.add_transformable_mobject(rarrow3)
+ self.add_transformable_mobject(rarrow4)
+ self.add_transformable_mobject(rarrow5)
+ self.add_transformable_mobject(rarrow6)
+ self.add_transformable_mobject(rarrow7)
+
+ matrix = [[1,-1],[1,-1]]
+ self.apply_matrix(matrix)
+ self.wait(3)
+
+ o1 = TextMobject("Consider a set of vectors which are linear span of a vector")
+ o2 = TextMobject(r"$\left(\begin{array}{c} 1 \\ -1 \end{array}\right)$ which is orthogonal to column space i.e. Left Null Space")
+ o1.move_to(2*DOWN)
+ o2.move_to(2.75*DOWN)
+ o1.scale(0.7)
+ o2.scale(0.7)
+ o1.add_background_rectangle()
+ o2.add_background_rectangle()
+ self.play(Write(o1))
+ self.play(Write(o2))
+
+ rarrow = Arrow(start = ORIGIN, end = -UP+RIGHT)
+ rarrow.set_color(YELLOW)
+ rarrow1 = Arrow(start = ORIGIN, end = 2*(-UP+RIGHT))
+ rarrow1.set_color(YELLOW)
+ rarrow2 = Arrow(start = ORIGIN, end = 3*(-UP+RIGHT))
+ rarrow2.set_color(YELLOW)
+ rarrow3 = Arrow(start = ORIGIN, end = 4*(-UP+RIGHT))
+ rarrow3.set_color(YELLOW)
+ rarrow4 = Arrow(start = ORIGIN, end = -DOWN+LEFT)
+ rarrow4.set_color(YELLOW)
+ rarrow5 = Arrow(start = ORIGIN, end = 2*(-DOWN+LEFT))
+ rarrow5.set_color(YELLOW)
+ rarrow6 = Arrow(start = ORIGIN, end = 3*(-DOWN+LEFT))
+ rarrow6.set_color(YELLOW)
+ rarrow7 = Arrow(start = ORIGIN, end = 4*(-DOWN+LEFT))
+ rarrow7.set_color(YELLOW)
+
+ rarrow.scale(1.5)
+ rarrow1.scale(1.2)
+ rarrow2.scale(1.15)
+ rarrow3.scale(1.1)
+ rarrow4.scale(1.5)
+ rarrow5.scale(1.2)
+ rarrow6.scale(1.15)
+ rarrow7.scale(1.1)
+
+ self.play(ShowCreation(rarrow),
+ ShowCreation(rarrow1),
+ ShowCreation(rarrow2),
+ ShowCreation(rarrow3),
+ ShowCreation(rarrow4),
+ ShowCreation(rarrow5),
+ ShowCreation(rarrow6),
+ ShowCreation(rarrow7),
+ )
+
+ self.wait(2)
+ self.play(FadeOut(o1), FadeOut(o2))
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/README.md b/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/README.md
new file mode 100644
index 0000000..9d49b4f
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/README.md
@@ -0,0 +1,9 @@
+# Contributer: Archit Sangal
+My Github Account : <a href="https://github.com/architsangal">architsangal</a> (https://github.com/architsangal)
+<br/></br>
+
+## Sub-Topics Covered:
++ The Rank-Nullity Theorem
+
+#### Video 1: Visually understanding linear transformation(using grid)
+![GIF1](file2.gif) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file.txt b/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file.txt
new file mode 100644
index 0000000..5c48a13
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file.txt
@@ -0,0 +1,3 @@
+file 'RN_Line.mp4'
+file 'RN_Point.mp4'
+file 'RN_SameDim.mp4'
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file1_RN_Theorem.py b/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file1_RN_Theorem.py
new file mode 100755
index 0000000..e54276c
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file1_RN_Theorem.py
@@ -0,0 +1,97 @@
+from manimlib.imports import *
+class RN_Line(LinearTransformationScene):
+ def construct(self):
+
+ self.setup()
+ self.wait()
+
+ predim = TextMobject("Dimension of this vector space is 2")
+ predim.move_to(DOWN+4*LEFT)
+ predim.scale(0.75)
+ predim.add_background_rectangle()
+ self.play(Write(predim))
+ self.wait()
+ self.play(FadeOut(predim))
+
+ afterlt = TextMobject("After Linear transformation")
+ afterlt.move_to(DOWN+4*LEFT)
+ afterlt.scale(0.75)
+ afterlt.add_background_rectangle()
+
+ afterlt2 = TextMobject("Dimension of the vector space","changes to 1")
+ afterlt2[0].move_to(1.5*DOWN+4*LEFT)
+ afterlt2[1].move_to(2*DOWN+4*LEFT)
+ afterlt2.scale(0.75)
+ afterlt2.add_background_rectangle()
+ matrix = [[1,1],[1,1]]
+ self.apply_matrix(matrix)
+ self.play(Write(afterlt))
+ self.play(Write(afterlt2))
+ self.wait()
+ nullity = TextMobject("Hence, nullity = 1")
+ nullity.move_to(DOWN+4*LEFT)
+ self.play(FadeOut(afterlt),FadeOut(afterlt2),Write(nullity))
+ self.wait(1)
+ self.play(FadeOut(nullity))
+
+class RN_Point(LinearTransformationScene):
+ def construct(self):
+ self.setup()
+ self.wait()
+ predim = TextMobject("Another One")
+ predim.move_to(DOWN+4*LEFT)
+ predim.scale(0.75)
+ predim.add_background_rectangle()
+ self.play(Write(predim))
+ self.wait()
+ self.play(FadeOut(predim))
+ afterlt = TextMobject("After Linear transformation")
+ afterlt.move_to(DOWN+4*LEFT)
+ afterlt.scale(0.75)
+ afterlt.add_background_rectangle()
+ afterlt2 = TextMobject("Dimension of the vector space","changes to 0")
+ afterlt2[0].move_to(1.5*DOWN+4*LEFT)
+ afterlt2[1].move_to(2*DOWN+4*LEFT)
+ afterlt2.scale(0.75)
+ afterlt2.add_background_rectangle()
+ matrix = [[0,0],[0,0]]
+ self.apply_matrix(matrix)
+ self.play(Write(afterlt))
+ self.play(Write(afterlt2))
+ self.wait()
+ nullity = TextMobject("Hence, nullity = 2")
+ nullity.move_to(DOWN+4*LEFT)
+ self.play(FadeOut(afterlt),FadeOut(afterlt2),Write(nullity))
+ self.wait(1)
+ self.play(FadeOut(nullity))
+
+class RN_SameDim(LinearTransformationScene):
+ def construct(self):
+ self.setup()
+ self.wait()
+ predim = TextMobject("Let us look at another example")
+ predim.add_background_rectangle()
+ predim.move_to(DOWN+4*LEFT)
+ predim.scale(0.75)
+ self.play(Write(predim))
+ self.wait()
+ self.play(FadeOut(predim))
+ afterlt = TextMobject("After Linear transformation")
+ afterlt.move_to(DOWN+4*LEFT)
+ afterlt.scale(0.75)
+ afterlt.add_background_rectangle()
+ afterlt2 = TextMobject("Dimension of the vector space","remains to be 2")
+ afterlt2[0].move_to(1.5*DOWN+4*LEFT)
+ afterlt2[1].move_to(2*DOWN+4*LEFT)
+ afterlt2.scale(0.75)
+ afterlt2.add_background_rectangle()
+ matrix = [[1,1],[0,1]]
+ self.apply_matrix(matrix)
+ self.play(Write(afterlt))
+ self.play(Write(afterlt2))
+ self.wait()
+ nullity = TextMobject("Hence, nullity = 0")
+ nullity.move_to(DOWN+4*LEFT)
+ self.play(FadeOut(afterlt),FadeOut(afterlt2),Write(nullity))
+ self.wait(1)
+ self.play(FadeOut(nullity)) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file2.gif b/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file2.gif
new file mode 100644
index 0000000..46efc66
--- /dev/null
+++ b/FSF-2020/linear-algebra/linear-transformations/The-Rank-Nullity-Theorem/file2.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/README.md b/FSF-2020/linear-algebra/vector-spaces/README.md
index e69de29..03f6a03 100644
--- a/FSF-2020/linear-algebra/vector-spaces/README.md
+++ b/FSF-2020/linear-algebra/vector-spaces/README.md
@@ -0,0 +1,9 @@
+# Contributer: Simran Chhattani
+My Github Account : <a href="https://github.com/simranchhattani">simranchhattani</a>
+<br/></br>
+## Sub-Topics Covered:
++ Vector Spaces
++ Basis of a Vector Space and Subspace
++ Polynomial and Function Vector Space
++ Inner Product Spaces
++ Dual of a Vector Space
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Basis_of_a_dual_vector_space.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Basis_of_a_dual_vector_space.py
new file mode 100644
index 0000000..630670e
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Basis_of_a_dual_vector_space.py
@@ -0,0 +1,126 @@
+from manimlib.imports import *
+class DualVectorSpace(ZoomedScene):
+
+ def construct(self):
+ c1 = Ellipse(radius = 2,color=BLUE)
+ c2 = Ellipse(radius = 2,color=YELLOW)
+ c1.rotate(np.pi/2)
+ c2.rotate(np.pi/2)
+ c1.shift(2*LEFT+0.6*UP)
+ c2.shift(2*RIGHT+0.6*UP)
+ c1.scale(2)
+ c2.scale(2)
+ self.play(ShowCreation(c1))
+ self.play(ShowCreation(c2))
+ dot1 = SmallDot(color=BLUE).shift(2*LEFT+2*UP)
+ dot2 = SmallDot(color=BLUE).shift(2*LEFT+1.5*UP)
+ dot3 = SmallDot(color=BLUE).shift(2*LEFT+1*UP)
+ dot4 = SmallDot(color=BLUE).shift(2*LEFT+0.5*UP)
+ dot5 = SmallDot(color=BLUE).shift(2*LEFT)
+ dot6 = SmallDot(color=BLUE).shift(2*LEFT+0.5*DOWN)
+ dot7 = SmallDot(color=BLUE).shift(2*LEFT+1*DOWN)
+ text1 = TextMobject(r"$V$").scale(0.6).shift(3*UP+2*LEFT)
+ text2 = TextMobject(r"$V^* = \{T:V\rightarrow F\}$").scale(0.6).shift(3*UP+2.5*RIGHT)
+ self.play(ShowCreation(dot1),ShowCreation(dot2),ShowCreation(dot3),ShowCreation(dot4),ShowCreation(dot5),ShowCreation(dot6),ShowCreation(dot7))
+ v1 = TextMobject(r"$v_1$").scale(0.5).shift(2.2*LEFT+2*UP)
+ v2 = TextMobject(r"$v_2$").scale(0.5).shift(2.2*LEFT+1.5*UP)
+ v3 = TextMobject(r"$v_3$").scale(0.5).shift(2.2*LEFT+1*UP)
+ v4 = TextMobject(r"$v_4$").scale(0.5).shift(2.2*LEFT+0.5*UP)
+ v5 = TextMobject(r"$v_5$").scale(0.5).shift(2.2*LEFT)
+ v6 = TextMobject(r"$v_6$").scale(0.5).shift(2.2*LEFT+0.5*DOWN)
+ v7 = TextMobject(r"$v_7$").scale(0.5).shift(2.2*LEFT+1*DOWN)
+ self.play(ShowCreation(v1),ShowCreation(v2),ShowCreation(v3),ShowCreation(v4),ShowCreation(v5),ShowCreation(v6),ShowCreation(v7))
+ self.play(ShowCreation(text1))
+ dot9 = SmallDot(color=YELLOW).shift(2*RIGHT+2*UP)
+ dot10 = SmallDot(color=YELLOW).shift(2*RIGHT+1.5*UP)
+ dot11 = SmallDot(color=YELLOW).shift(2*RIGHT+1*UP)
+ dot12 = SmallDot(color=YELLOW).shift(2*RIGHT+0.5*UP)
+ dot13 = SmallDot(color=YELLOW).shift(2*RIGHT)
+ dot14 = SmallDot(color=YELLOW).shift(2*RIGHT+0.5*DOWN)
+ dot15 = SmallDot(color=YELLOW).shift(2*RIGHT+1*DOWN)
+ self.play(ShowCreation(dot9),ShowCreation(dot10),ShowCreation(dot11),ShowCreation(dot12),ShowCreation(dot13),ShowCreation(dot14),ShowCreation(dot15))
+ v9 = TextMobject(r"${T_1}$").scale(0.5).shift(2.2*RIGHT+2*UP)
+ v10 = TextMobject(r"${T_2}$").scale(0.5).shift(2.2*RIGHT+1.5*UP)
+ v11 = TextMobject(r"${T_3}$").scale(0.5).shift(2.2*RIGHT+1*UP)
+ v12 = TextMobject(r"${T_4}$").scale(0.5).shift(2.2*RIGHT+0.5*UP)
+ v13 = TextMobject(r"${T_5}$").scale(0.5).shift(2.2*RIGHT)
+ v14 = TextMobject(r"${T_6}$").scale(0.5).shift(2.2*RIGHT+0.5*DOWN)
+ v15 = TextMobject(r"${T_7}$").scale(0.5).shift(2.2*RIGHT+1*DOWN)
+ self.play(ShowCreation(v9),ShowCreation(v10),ShowCreation(v11),ShowCreation(v12),ShowCreation(v13),ShowCreation(v14),ShowCreation(v15))
+ self.play(ShowCreation(text2))
+ line1 = Line(start=dot1,end=dot9,stroke_width=0.95)
+ line2 = Line(start=dot2,end=dot10,stroke_width=0.95)
+ line3 = Line(start=dot3,end=dot11,stroke_width=0.95)
+ line4 = Line(start=dot4,end=dot12,stroke_width=0.95)
+ line5 = Line(start=dot5,end=dot13,stroke_width=0.95)
+ line6 = Line(start=dot6,end=dot14,stroke_width=0.95)
+ line7 = Line(start=dot7,end=dot15,stroke_width=0.95)
+ self.play(ShowCreation(line1),ShowCreation(line2),ShowCreation(line3),ShowCreation(line4),ShowCreation(line5),ShowCreation(line6),ShowCreation(line7))
+ self.wait(1.5)
+ rect1 = Rectangle(stroke_width=0.5,width=1,height=1.9).set_fill(color=BLUE,opacity=0.3)
+ vgroup1 = VGroup(dot3,dot4,v3,v4)
+ rect1.surround(vgroup1)
+ self.play(ShowCreation(rect1))
+ text3 = TextMobject(r"Basis of $V$ = $\{v_3, v_4\}$").shift(4.6*LEFT+1*UP).scale(0.5)
+ self.play(ShowCreation(text3))
+ self.wait(1.5)
+ rect2 = Rectangle(stroke_width=0.5,width=1,height=1.7).set_fill(color=YELLOW,opacity=0.3)
+ vgroup2 = VGroup(dot11,dot12,v11,v12)
+ rect2.surround(vgroup2)
+ self.play(ShowCreation(rect2))
+ text4 = TextMobject(r"Basis of $V^*$ = $\{{T_3},{T_4} \}$").shift(4.6*RIGHT+1*UP).scale(0.5)
+ self.play(ShowCreation(text4))
+ self.wait(2.5)
+ v9.move_to(3*LEFT+3*UP).scale(1.2).set_color(YELLOW)
+ colon = TextMobject(":").shift(3*UP+2.6*LEFT)
+ vgroup3 = VGroup(line1,line2,line3,line4,line5,line6,line7)
+ vgroup4 = VGroup(v10,v11,v12,v13,v14,v15,rect1,rect2,text3,text4,c2)
+ vgroup5 = VGroup(dot9,dot10,dot11,dot12,dot13,dot14,dot15)
+ text5 = TextMobject(r"$F$").scale(0.6).shift(3*UP+2*RIGHT)
+ dot9 = SmallDot(color=GREEN).shift(2*RIGHT+2*UP)
+ dot10 = SmallDot(color=GREEN).shift(2*RIGHT+1.5*UP)
+ dot11 = SmallDot(color=GREEN).shift(2*RIGHT+1*UP)
+ dot12 = SmallDot(color=GREEN).shift(2*RIGHT+0.5*UP)
+ dot13 = SmallDot(color=GREEN).shift(2*RIGHT)
+ dot14 = SmallDot(color=GREEN).shift(2*RIGHT+0.5*DOWN)
+ dot15 = SmallDot(color=GREEN).shift(2*RIGHT+1*DOWN)
+ f1 = TextMobject(r"${f_1}$").scale(0.5).shift(2.2*RIGHT+2*UP)
+ f2 = TextMobject(r"${f_2}$").scale(0.5).shift(2.2*RIGHT+1.5*UP)
+ f3 = TextMobject(r"${f_3}$").scale(0.5).shift(2.2*RIGHT+1*UP)
+ f4 = TextMobject(r"${f_4}$").scale(0.5).shift(2.2*RIGHT+0.5*UP)
+ f5 = TextMobject(r"${f_5}$").scale(0.5).shift(2.2*RIGHT)
+ f6 = TextMobject(r"${f_6}$").scale(0.5).shift(2.2*RIGHT+0.5*DOWN)
+ f7 = TextMobject(r"${f_7}$").scale(0.5).shift(2.2*RIGHT+1*DOWN)
+ vgroup6 = VGroup(f1,f2,f3,f4,f5,f6,f7)
+ arrow = Arrow(stroke_width=1.6).scale(1.5).shift(3*UP)
+ c3 = Ellipse(radius = 2,color=GREEN)
+ c3.rotate(np.pi/2)
+ c3.shift(2*RIGHT+0.6*UP)
+ c3.scale(2)
+ self.play(ShowCreation(v9))
+ self.wait(1.5)
+ self.play(ShowCreation(arrow),ShowCreation(colon),Transform(text2,text5),FadeOut(vgroup3),FadeOut(vgroup4),FadeOut(vgroup5))
+ self.play(ShowCreation(vgroup5),ShowCreation(vgroup6),ShowCreation(c3))
+ self.wait(0.7)
+ self.play(ShowCreation(vgroup3))
+ self.wait(3)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Dual_Basis_Example.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Dual_Basis_Example.py
new file mode 100644
index 0000000..d79ec3e
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Dual_Basis_Example.py
@@ -0,0 +1,97 @@
+from manimlib.imports import *
+import numpy as np
+
+class Dual_Basis(GraphScene):
+ CONFIG={
+ "x_min": -7,
+ "x_max": 7,
+ "y_min": -7,
+ "y_max": 7,
+ "graph_origin": ORIGIN,
+ "x_axis_label":"$X$",
+ "y_axis_label":"$Y$",
+ "x_labeled_nums": list(np.arange(-7, 8,1)),
+ "y_labeled_nums": list(np.arange(-7, 8,1)),
+ "x_axis_width": 10,
+ "y_axis_height": 10,
+ "x_tick_frequency":1,
+ "axes_color": GREY,
+ "area_opacity": 3,
+ "num_rects": 10,
+ }
+ def construct(self):
+ self.setup_axes(animate = True)
+ XD = self.x_axis_width/(self.x_max- self.x_min)
+ YD = self.y_axis_height/(self.y_max- self.y_min)
+ a1=2*XD*RIGHT+1*YD*UP
+ a2=3*XD*RIGHT+1*YD*UP
+ vec1=Vector(direction=a1,stroke_width=2).set_color(RED_E)
+ vec1.shift(self.graph_origin)
+ v1_label=TextMobject(r"$v_1$")
+ v1_label=(v1_label.shift(self.graph_origin+a1+0.1)).scale(.6)
+ self.play(ShowCreation(vec1),ShowCreation(v1_label))
+ text1=TextMobject(r"\text{$v_1$}",r"\text{$= (2,1)$}").scale(.6)
+ text1[0].set_color(RED_E)
+ text1.shift(5*LEFT+3.5*UP)
+ self.play(ShowCreation(text1))
+ self.wait(1.5)
+ vec2=Vector(direction=a2,stroke_width=2).set_color(YELLOW_E)
+ vec2.shift(self.graph_origin)
+ v2_label=TextMobject(r"$v_2$")
+ v2_label=(v2_label.shift(self.graph_origin+a2+0.1)).scale(.6)
+ self.play(ShowCreation(vec2),ShowCreation(v2_label))
+ text2=TextMobject(r"\text{$v_2$}",r"\text{$= (3,1)$}").scale(.6)
+ text2[0].set_color(YELLOW_E)
+ text2.shift(5*LEFT+3*UP)
+ self.play(ShowCreation(text2))
+ self.wait(1.5)
+ text3=TextMobject(r"\text{${T_2}$}",r"\text{$(v_1)$}",r"\text{$= 0$}").scale(.6)
+ text3[0].set_color(BLUE)
+ text3[1].set_color(RED_E)
+ text3.shift(4.94*LEFT+2.5*UP)
+ self.play(ShowCreation(text3))
+ self.wait(1.5)
+ text4=TextMobject(r"\text{${T_2}$}",r"\text{$= x - 2y$}").scale(.6)
+ text4[0].set_color(BLUE)
+ text4.shift(4.9*LEFT+2*UP)
+ self.play(ShowCreation(text4))
+ self.wait(1.5)
+ line1 = self.get_graph(lambda x : x/2, x_min = -5,x_max=5,color=BLUE)
+ v1_dual_label = TextMobject(r"${T_2}$").scale(.6).shift(3.9*RIGHT+1.85*UP)
+ self.play(ShowCreation(line1),ShowCreation(v1_dual_label))
+ self.wait(1.5)
+ text5=TextMobject(r"\text{${T_1}$}",r"\text{$(v_2)$}",r"\text{$= 0$}").scale(.6)
+ text5[1].set_color(YELLOW_E)
+ text5[0].set_color(PINK)
+ text5.shift(4.94*LEFT+1.5*UP)
+ self.play(ShowCreation(text5))
+ self.wait(1.5)
+ line2 = self.get_graph(lambda x : x/3, x_min = -5,x_max=5,color=PINK)
+ v2_dual_label = TextMobject(r"${T_1}$").scale(.6).shift(3.9*RIGHT+1.3*UP)
+ self.play(ShowCreation(line2),ShowCreation(v2_dual_label))
+ self.wait(1.5)
+ text6=TextMobject(r"\text{${T_1}$}",r"\text{$= - x + 3y$}").scale(.6)
+ text6[0].set_color(PINK)
+ text6.shift(4.76*LEFT+1*UP)
+ self.play(ShowCreation(text6))
+ self.wait(3)
+ text7 = TextMobject(r"\text{B =}",r"\text{$[$}",r"\text{$v_1,$}",r"\text{$v_2$}",r"\text{$]$}",r"\text{=}",r"\text{$[(2,1), (3,1)]$}").scale(0.6).shift(3*UP+4.5*LEFT)
+ text7[2].set_color(RED_E)
+ text7[3].set_color(YELLOW_E)
+ self.play(FadeOut(text1),FadeOut(text2),FadeOut(text3),FadeOut(text4),FadeOut(text5),FadeOut(text6))
+ self.play(ShowCreation(text7))
+ self.wait(0.7)
+ text8 = TextMobject(r"\text{B$^* =$}",r"\text{$[$}",r"\text{${T_1}$,}",r"\text{${T_2} $}",r"\text{$]$}",r"\text{=}",r"\text{$[-x + 3y, x - 2y]$}").scale(0.6).shift(2.3*UP+4.1*LEFT)
+ text8[3].set_color(BLUE)
+ text8[2].set_color(PINK)
+ self.play(ShowCreation(text8))
+ self.wait(3)
+
+
+
+
+
+
+
+
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Dual_of_a_Cube.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Dual_of_a_Cube.py
new file mode 100644
index 0000000..a6f501e
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Dual_of_a_Cube.py
@@ -0,0 +1,38 @@
+from manimlib.imports import *
+class Duality(ThreeDScene):
+
+
+ def construct(self):
+ axes = ThreeDAxes()
+ self.set_camera_orientation(phi = 65*DEGREES,theta =80*DEGREES)
+ self.begin_ambient_camera_rotation(rate=0.09)
+ cube = Cube(stroke_width=5,color=WHITE).scale(2)
+ cube.set_opacity(0.2)
+ self.play(ShowCreation(cube))
+ dot1= Dot(color=RED).scale(0.85).shift([2,0,0])
+ self.play(ShowCreation(dot1))
+ dot2= Dot(color=YELLOW).scale(0.85).shift([-2,0,0])
+ self.play(ShowCreation(dot2))
+ dot3= Dot(color=BLUE).scale(0.85).shift([0,-2,0])
+ self.play(ShowCreation(dot3))
+ dot4= Dot(color=GREEN).scale(0.85).shift([0,2,0])
+ self.play(ShowCreation(dot4))
+ dot5= Dot(color=ORANGE).scale(0.85).shift([0,0,2])
+ self.play(ShowCreation(dot5))
+ dot6= Dot(color=PINK).scale(0.85).shift([0,0,-2])
+ self.play(ShowCreation(dot6))
+ line1 = Line(start=[0,0,2],end=[2,0,0],stroke_width=2.5,color=BLACK)
+ line2 = Line(start=[0,0,2],end=[-2,0,0],stroke_width=2.5,color=BLACK)
+ line3 = Line(start=[0,0,2],end=[0,-2,0],stroke_width=2.5,color=BLACK)
+ line4 = Line(start=[0,0,2],end=[0,2,0],stroke_width=2.5,color=BLACK)
+ line5 = Line(start=[2,0,0],end=[0,0,-2],stroke_width=2.5,color=BLACK)
+ line6 = Line(start=[-2,0,0],end=[0,0,-2],stroke_width=2.5,color=BLACK)
+ line7 = Line(start=[0,-2,0],end=[0,0,-2],stroke_width=2.5,color=BLACK)
+ line8 = Line(start=[0,2,0],end=[0,0,-2],stroke_width=2.5,color=BLACK)
+ line9 = Line(start=[0,2,0],end=[-2,0,0],stroke_width=2.5,color=BLACK)
+ line10 = Line(start=[-2,0,0],end=[0,-2,0],stroke_width=2.5,color=BLACK)
+ line11 = Line(start=[0,-2,0],end=[2,0,0],stroke_width=2.5,color=BLACK)
+ line12 = Line(start=[2,0,0],end=[0,2,0],stroke_width=2.5,color=BLACK)
+ self.play(ShowCreation(line1),ShowCreation(line2),ShowCreation(line3),ShowCreation(line4),ShowCreation(line5),ShowCreation(line6),ShowCreation(line7),ShowCreation(line8),ShowCreation(line9),ShowCreation(line10),ShowCreation(line11),ShowCreation(line12))
+ self.wait(10)
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Duality_in_Sets.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Duality_in_Sets.py
new file mode 100644
index 0000000..693017e
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Duality_in_Sets.py
@@ -0,0 +1,25 @@
+from manimlib.imports import *
+import numpy as np
+class Duality_in_sets(Scene):
+ def construct(self):
+ circle1 = Circle(radius=0.4,color=BLACK).shift(2.3*LEFT)
+ circle1.set_fill(color=RED,opacity=200)
+ rect1=Rectangle(height=2,width=2,color=GREY).shift(2*LEFT)
+ rect1.set_fill(color=DARK_BLUE,opacity=1)
+ text1 = TextMobject("S").scale(0.7).shift(0.9*UP+0.7*LEFT)
+ text2 = TextMobject("X",color=BLACK,stroke_width=0.5).scale(0.5).shift(2.3*LEFT)
+ self.play(ShowCreation(rect1),ShowCreation(text1),ShowCreation(circle1),ShowCreation(text2))
+ circle2 = Circle(radius=0.4,color=BLACK).shift(1.7*RIGHT)
+ circle2.set_fill(color=BLACK,opacity=200)
+ rect2=Rectangle(height=2,width=2,color=GREY).shift(2*RIGHT)
+ rect2.set_fill(color=DARK_BLUE,opacity=1)
+ text3 = TextMobject("S").scale(0.7).shift(0.9*UP+3.3*RIGHT)
+ text4 = TextMobject(r"X$^c$",color=BLACK,stroke_width=0.2).scale(0.5).shift(2.55*RIGHT+0.6*UP)
+ text5 = TextMobject(r"\text{The subset}",r"\text{X$^c$}",r"\text{is the dual of subset}",r"\text{X}").scale(0.6).shift(2.7*UP+0.5*LEFT)
+ text5[1].set_color(GREY)
+ text5[3].set_color(GREY)
+ self.play(ShowCreation(rect2),ShowCreation(circle2),ShowCreation(text3),ShowCreation(text4))
+ self.wait(2)
+ self.play(ShowCreation(text5))
+ self.wait(3)
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Linear_Functional.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Linear_Functional.py
new file mode 100644
index 0000000..6edc918
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/Linear_Functional.py
@@ -0,0 +1,29 @@
+from manimlib.imports import *
+import numpy as np
+class LinearFunctional(Scene):
+ def construct(self):
+ big_box=Rectangle().scale(2.7)
+ box = Rectangle(height=2,width=2,color=DARK_GREY).set_fill(color=PURPLE,opacity=350)
+ arrow1 = Arrow(color=RED).shift(1.8*LEFT+0.5*UP)
+ arrow2 = Arrow(color=RED).shift(1.8*LEFT+0.5*DOWN)
+ arrow3 = Arrow(color=GREEN).shift(0.5*UP+1.8*RIGHT)
+ arrow4 = Arrow(color=GREEN).shift(0.5*DOWN+1.8*RIGHT)
+ Linear = TextMobject("LINEAR",color=BLACK).scale(0.5).shift(0.2*UP)
+ Functional = TextMobject("FUNCTIONAL",color=BLACK).scale(0.5).shift(0.2*DOWN)
+ u = TextMobject(r"$\vec{u}$",color=YELLOW).scale(0.7).shift(2.8*LEFT+0.5*UP)
+ v = TextMobject(r"$\vec{v}$",color=YELLOW).scale(0.7).shift(2.8*LEFT+0.5*DOWN)
+ f1 = TextMobject(r"$f_1$",color=YELLOW).scale(0.7).shift(2.8*RIGHT+0.5*UP)
+ f2 = TextMobject(r"$f_2$",color=YELLOW).scale(0.7).shift(2.8*RIGHT+0.5*DOWN)
+ text = TextMobject(r"The Linear Functional is a function that takes $\vec{u}, \vec{v} \in$ V as inputs and gives the output $f_1, f_2\in$ F.").scale(0.55).shift(2*DOWN)
+ self.play(ShowCreation(big_box))
+ self.play(ShowCreation(box))
+ self.play(ShowCreation(Linear),ShowCreation(Functional))
+ self.wait(2)
+ self.play(ShowCreation(arrow1),ShowCreation(u))
+ self.play(ShowCreation(arrow3),ShowCreation(f1))
+ self.wait(0.7)
+ self.play(ShowCreation(arrow2),ShowCreation(v))
+ self.play(ShowCreation(arrow4),ShowCreation(f2))
+ self.wait(1)
+ self.play(ShowCreation(text))
+ self.wait(4)
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Basis_of_a_dual_vector_space.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Basis_of_a_dual_vector_space.mp4
new file mode 100644
index 0000000..b96f541
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Basis_of_a_dual_vector_space.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Dual_Basis_Example.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Dual_Basis_Example.mp4
new file mode 100644
index 0000000..c93be25
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Dual_Basis_Example.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Dual_of_a_Cube.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Dual_of_a_Cube.mp4
new file mode 100644
index 0000000..ebfb564
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Dual_of_a_Cube.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Duality_in_Sets.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Duality_in_Sets.mp4
new file mode 100644
index 0000000..86cc693
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Duality_in_Sets.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Linear_functional.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Linear_functional.mp4
new file mode 100644
index 0000000..d41fada
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Dual-Spaces/gifs4/Linear_functional.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Function_Scalar_Multiplication.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Function_Scalar_Multiplication.py
new file mode 100644
index 0000000..ac74792
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Function_Scalar_Multiplication.py
@@ -0,0 +1,62 @@
+from manimlib.imports import *
+from scipy import exp
+class FunctionScalarMultiplication(GraphScene):
+ CONFIG = {
+ "x_min" : -5,
+ "x_max" : 5,
+ "y_min" : -5,
+ "y_max" : 5,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color":LIGHT_GRAY,
+ "graph_origin": ORIGIN,
+ }
+ def construct(self):
+ self.setup_axes(animate = True)
+ curve1 = self.get_graph(lambda x : 1/3*(x**2)+1, x_min=-2,x_max=2.5,color=ORANGE)
+ curve2 = self.get_graph(lambda x : 2*(1/3*(x**2)+1), x_min=-2,x_max=2.5,color=GOLD)
+ fx= TextMobject("$f(x)$").scale(0.6).shift(1.25*UP + 2.2*LEFT)
+ gx= TextMobject("$2 \cdot f(x)$").scale(0.6).shift(0.5*UP + 2.1*LEFT)
+ f1 = self.get_vertical_line_to_graph(-2,curve1,color=YELLOW)
+ f2 = self.get_vertical_line_to_graph(-1.5,curve1,color=YELLOW)
+ f3 = self.get_vertical_line_to_graph(-1,curve1,color=YELLOW)
+ f4 = self.get_vertical_line_to_graph(-0.5,curve1,color=YELLOW)
+ f5 = self.get_vertical_line_to_graph(0,curve1,color=YELLOW)
+ f6 = self.get_vertical_line_to_graph(0.5,curve1,color=YELLOW)
+ f7 = self.get_vertical_line_to_graph(1,curve1,color=YELLOW)
+ f8 = self.get_vertical_line_to_graph(1.5,curve1,color=YELLOW)
+ f9 = self.get_vertical_line_to_graph(2,curve1,color=YELLOW)
+ f10 = self.get_vertical_line_to_graph(2.5,curve1,color=YELLOW)
+ self.play(ShowCreation(curve1),ShowCreation(fx))
+ self.wait(1.5)
+ self.play(ShowCreation(f1),ShowCreation(f2),ShowCreation(f3),ShowCreation(f4),ShowCreation(f5),ShowCreation(f6),ShowCreation(f7),ShowCreation(f8),ShowCreation(f9),ShowCreation(f10))
+ self.wait(1.7)
+ line1=Line(color=YELLOW).shift(5*LEFT+1.8*UP).scale(0.5)
+ line1.rotate(np.pi/2)
+ scalar = TextMobject("2 x").scale(0.65).shift(5.5*LEFT+1.9*UP)
+ equal = TextMobject("=").scale(0.65).shift(4.5*LEFT+1.9*UP)
+ line2=Line(color=BLUE).shift(4*LEFT+2.3*UP)
+ line2.rotate(np.pi/2)
+ self.play(ShowCreation(line1),ShowCreation(scalar),ShowCreation(equal),ShowCreation(line2))
+ g1 = self.get_vertical_line_to_graph(-2,curve2,color=BLUE)
+ g2 = self.get_vertical_line_to_graph(-1.5,curve2,color=BLUE)
+ g3 = self.get_vertical_line_to_graph(-1,curve2,color=BLUE)
+ g4 = self.get_vertical_line_to_graph(-0.5,curve2,color=BLUE)
+ g5 = self.get_vertical_line_to_graph(0,curve2,color=BLUE)
+ g6 = self.get_vertical_line_to_graph(0.5,curve2,color=BLUE)
+ g7 = self.get_vertical_line_to_graph(1,curve2,color=BLUE)
+ g8 = self.get_vertical_line_to_graph(1.5,curve2,color=BLUE)
+ g9 = self.get_vertical_line_to_graph(2,curve2,color=BLUE)
+ g10 = self.get_vertical_line_to_graph(2.5,curve2,color=BLUE)
+ self.play(ShowCreation(g1),ShowCreation(g2),ShowCreation(g3),ShowCreation(g4),ShowCreation(g5),ShowCreation(g6),ShowCreation(g7),ShowCreation(g8),ShowCreation(g9),ShowCreation(g10))
+ self.wait(2)
+ fx2=TextMobject("2$\cdot f(x)$").scale(0.6).shift(2.6*UP+2.3*LEFT)
+ self.play(ShowCreation(curve2),ShowCreation(fx2))
+ self.wait(1.5)
+ self.play(FadeOut(curve1),FadeOut(fx))
+ sc_mult=TextMobject("$(2 f(x)) = 2f(x)$",color=GOLD).scale(0.65).shift(0.65*UP + 5*LEFT)
+ rect = Rectangle(height=0.5,width=2)
+ rect.surround(sc_mult)
+ self.play(ShowCreation(sc_mult),ShowCreation(rect))
+ self.wait(3)
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Function_Space_Addition.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Function_Space_Addition.py
new file mode 100644
index 0000000..5ce0e11
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Function_Space_Addition.py
@@ -0,0 +1,89 @@
+from manimlib.imports import *
+from scipy import sin,exp
+class FunctionalVectorSpace(GraphScene):
+ CONFIG = {
+ "x_min" : -5,
+ "x_max" : 5,
+ "y_min" : -5,
+ "y_max" : 5,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color":LIGHT_GRAY,
+ "graph_origin": ORIGIN,
+
+
+ }
+ def construct(self):
+ self.setup_axes(animate = True)
+ curve1 = self.get_graph(lambda x : exp(x) + 0.5, x_min=-2,x_max=2.5,color=ORANGE)
+ curve2 = self.get_graph(lambda x : 1/3*(x**2)+1, x_min=-2,x_max=2.5,color=DARK_BLUE)
+ curve3 = self.get_graph(lambda x : 1/3*(x**2)+1 + exp(x) + 0.5, x_min=-2,x_max=2.5,color=BLACK)
+ fx= TextMobject("$f(x)$").scale(0.6).shift(1.25*UP + 2.1*LEFT)
+ gx= TextMobject("$g(x)$").scale(0.6).shift(0.5*UP + 2.1*LEFT)
+ f1 = self.get_vertical_line_to_graph(-2,curve1,color=YELLOW)
+ f2 = self.get_vertical_line_to_graph(-1.5,curve1,color=YELLOW)
+ f3 = self.get_vertical_line_to_graph(-1,curve1,color=YELLOW)
+ f4 = self.get_vertical_line_to_graph(-0.5,curve1,color=YELLOW)
+ f5 = self.get_vertical_line_to_graph(0,curve1,color=YELLOW)
+ f6 = self.get_vertical_line_to_graph(0.5,curve1,color=YELLOW)
+ f7 = self.get_vertical_line_to_graph(1,curve1,color=YELLOW)
+ f8 = self.get_vertical_line_to_graph(1.5,curve1,color=YELLOW)
+ f9 = self.get_vertical_line_to_graph(2,curve1,color=YELLOW)
+ f10 = self.get_vertical_line_to_graph(2.5,curve1,color=YELLOW)
+
+ self.play(ShowCreation(curve1),ShowCreation(gx))
+ self.wait(1.2)
+ self.play(ShowCreation(curve2),ShowCreation(fx))
+ self.wait(1.2)
+ self.play(ShowCreation(f1),ShowCreation(f2),ShowCreation(f3),ShowCreation(f4),ShowCreation(f5),ShowCreation(f6),ShowCreation(f7),ShowCreation(f8),ShowCreation(f9),ShowCreation(f10))
+ self.wait(1.7)
+ g1 = self.get_vertical_line_to_graph(-2,curve2,color=BLUE)
+ g2 = self.get_vertical_line_to_graph(-1.5,curve2,color=BLUE)
+ g3 = self.get_vertical_line_to_graph(-1,curve2,color=BLUE)
+ g4 = self.get_vertical_line_to_graph(-0.5,curve2,color=BLUE)
+ g5 = self.get_vertical_line_to_graph(0,curve2,color=BLUE)
+ g6 = self.get_vertical_line_to_graph(0.5,curve2,color=BLUE)
+ g7 = self.get_vertical_line_to_graph(1,curve2,color=BLUE)
+ g8 = self.get_vertical_line_to_graph(1.5,curve2,color=BLUE)
+ g9 = self.get_vertical_line_to_graph(2,curve2,color=BLUE)
+ g10 = self.get_vertical_line_to_graph(2.5,curve2,color=BLUE)
+ self.play(ShowCreation(g1),ShowCreation(g2),ShowCreation(g3),ShowCreation(g4),ShowCreation(g5),ShowCreation(g6),ShowCreation(g7),ShowCreation(g8),ShowCreation(g9),ShowCreation(g10))
+ line1=Line(color=BLUE).shift(5*LEFT+2.3*UP).scale(0.25)
+ line1.rotate(np.pi/2)
+ line2=Line(color=YELLOW).shift(6*LEFT+2.5*UP).scale(0.5)
+ line2.rotate(np.pi/2)
+ line3=Line(color=PURPLE_B).shift(4*LEFT+2.7*UP).scale(0.75)
+ line3.rotate(np.pi/2)
+ add=TextMobject("+").shift(2.4*UP+5.5*LEFT).scale(0.7)
+ equal=TextMobject("=").shift(2.4*UP+4.5*LEFT).scale(0.7)
+ self.play(ShowCreation(line2),ShowCreation(line1),ShowCreation(add),ShowCreation(equal),ShowCreation(line3))
+ self.wait(2)
+ self.play(FadeOut(curve1),FadeOut(curve2))
+ self.wait(3)
+ h1 = self.get_vertical_line_to_graph(-2,curve3,color=PURPLE_B)
+ h2 = self.get_vertical_line_to_graph(-1.5,curve3,color=PURPLE_B)
+ h3 = self.get_vertical_line_to_graph(-1,curve3,color=PURPLE_B)
+ h4 = self.get_vertical_line_to_graph(-0.5,curve3,color=PURPLE_B)
+ h5 = self.get_vertical_line_to_graph(0,curve3,color=PURPLE_B)
+ h6 = self.get_vertical_line_to_graph(0.5,curve3,color=PURPLE_B)
+ h7 = self.get_vertical_line_to_graph(1,curve3,color=PURPLE_B)
+ h8 = self.get_vertical_line_to_graph(1.5,curve3,color=PURPLE_B)
+ h9 = self.get_vertical_line_to_graph(2,curve3,color=PURPLE_B)
+ h10 = self.get_vertical_line_to_graph(2.5,curve3,color=PURPLE_B)
+
+ line1.shift(1*LEFT+0.9*UP)
+ equal.shift(0.3*LEFT+0.2*UP)
+ f=TextMobject("$f(x)$").scale(0.5).shift(5.6*LEFT+3.2*UP)
+ g=TextMobject("$g(x)$").scale(0.5).shift(5.6*LEFT+2.4*UP)
+ fg=TextMobject("$(f + g)(x)$").scale(0.5).shift(2.85*UP+3.3*LEFT)
+ self.play(FadeOut(add),ShowCreation(equal),ShowCreation(line1),ShowCreation(f),ShowCreation(g),ShowCreation(fg),FadeOut(fx),FadeOut(gx))
+ self.wait(1.7)
+ self.play(ShowCreation(h1),ShowCreation(h2),ShowCreation(h3),ShowCreation(h4),ShowCreation(h5),ShowCreation(h6),ShowCreation(h7),ShowCreation(h8),ShowCreation(h9),ShowCreation(h10))
+ curve3 = self.get_graph(lambda x : 1/3*(x**2)+1 + exp(x) + 0.5, x_min=-2,x_max=2.5,color=RED_A)
+ fgx=TextMobject("$(f + g)(x)$").scale(0.5).shift(1.65*UP+2.4*LEFT)
+ self.play(ShowCreation(curve3),ShowCreation(fgx))
+ sum=TextMobject("$(f + g)(x) = f(x) + g(x)$",color=GOLD).scale(0.65).shift(0.8*UP + 5*LEFT)
+ rect = Rectangle(height=0.5,width=2)
+ rect.surround(sum)
+ self.play(ShowCreation(sum),ShowCreation(rect))
+ self.wait(3) \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Integral_Properties.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Integral_Properties.py
new file mode 100644
index 0000000..97c0e09
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/Integral_Properties.py
@@ -0,0 +1,77 @@
+from manimlib.imports import *
+from scipy import sin
+class Integral_Properties(GraphScene):
+ CONFIG = {
+ "x_min" : 0,
+ "x_max" : 5,
+ "y_min" : 0,
+ "y_max" : 6,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color":LIGHT_GRAY,
+ "x_labeled_nums" : list(range(6)),
+ "y_labeled_nums" : list(range(6))
+ }
+ def construct(self):
+ self.setup_axes(animate=False)
+ curve1 = self.get_graph(lambda x : sin(x), x_min=0,x_max=2.5,color=RED)
+ curve2 = self.get_graph(lambda x : x, x_min=0,x_max=2.5,color=DARK_BLUE)
+ curve3 = self.get_graph(lambda x : sin(x) + x, x_min=0,x_max=2.5,color=GREEN)
+ fx = TextMobject(r"$f(x)$").scale(0.5).shift(1*RIGHT+1.8*DOWN)
+ gx = TextMobject(r"$g(x)$").scale(0.5).shift(1*RIGHT)
+ sum = TextMobject(r"$f(x) + g(x)$").scale(0.5).shift(1.3*RIGHT+0.6*UP)
+ area1 = self.get_area(curve1,0,2.5)
+ area2 = self.get_area(curve2,0,2.5)
+ area3 = self.get_area(curve3,0,2.5)
+ area2.set_fill(color=PURPLE)
+ area3.set_fill(color=ORANGE)
+ text1=TextMobject(r"$\int_{0}^{2.5}$ f(x) dx = Area under the curve f(x)",color=BLUE_C).scale(0.7).shift(2.7*RIGHT+3*UP)
+ text2=TextMobject(r"$\int_{0}^{2.5}$ g(x) dx = Area under the curve g(x)",color=PURPLE_B).scale(0.7).shift(2.7*RIGHT+2.4*UP)
+ text3=TextMobject(r"Area under the curve f(x) + g(x) = $\int_{0}^{2.5} (f(x) + g(x)) dx$",color=ORANGE).scale(0.7).shift(2.7*RIGHT+1.8*UP)
+ text4=TextMobject(r"\text{$\int_{0}^{2.5}$ (f(x) + g(x)) dx}",r"\text{ = }",r"\text{ $\int_{0}^{2.5}$ f(x) dx }",r"\text{+}",r"\text{$\int_{0}^{2.5}$ g(x) dx}").scale(0.62).shift(2.7*RIGHT+2.7*UP)
+ text4[0].set_color(ORANGE)
+ text4[2].set_color(BLUE_C)
+ text4[4].set_color(PURPLE_B)
+ self.play(ShowCreation(curve1), ShowCreation(fx))
+ self.wait(1.2)
+ self.play(ShowCreation(curve2),ShowCreation(gx))
+ self.wait(1.2)
+ self.play(ShowCreation(area1))
+ self.play(ShowCreation(text1))
+ self.wait(1.5)
+ self.play(ShowCreation(area2))
+ self.play(ShowCreation(text2))
+ self.wait(1.5)
+ self.play(ShowCreation(curve3),ShowCreation(sum))
+ self.play(ShowCreation(area3))
+ self.play(ShowCreation(text3))
+ self.wait(2)
+ self.play(FadeOut(text1),FadeOut(text2),FadeOut(text3))
+ self.wait(1)
+ self.play(ShowCreation(text4))
+ self.wait(3)
+ self.play(FadeOut(curve1),FadeOut(curve2),FadeOut(area1),FadeOut(area2))
+ self.wait(1.5)
+ self.play(FadeOut(text4),FadeOut(area2),FadeOut(curve2),FadeOut(gx),FadeOut(curve3),FadeOut(sum),FadeOut(area3),ShowCreation(curve1),ShowCreation(fx))
+ self.wait(1.5)
+ self.play(ShowCreation(area1),ShowCreation(text1))
+ self.wait(1.5)
+ curve4 = self.get_graph(lambda x : 2*sin(x), x_min=0,x_max=2.5,color=RED)
+ area4 = self.get_area(curve4,0,2.5)
+ area4.set_fill(color=YELLOW)
+ fx2 = TextMobject(r"$2f(x)$").scale(0.7).shift(1*RIGHT+1.2*DOWN)
+ scalar_mul=TextMobject(r"$\int_{0}^{2.5} ( 2f(x) ) dx$ = 2 $\times$ Area under the curve f(x)",color=YELLOW).scale(0.7).shift(2.7*RIGHT+2.4*UP)
+ self.play(ShowCreation(curve4),ShowCreation(fx2))
+ self.wait(1)
+ self.play(ShowCreation(area4))
+ self.wait(2)
+ self.play(ShowCreation(scalar_mul))
+ self.wait(2)
+ text5=TextMobject(r"\text{$\int_{0}^{2.5}$ (2 f(x)) dx}",r"\text{ = }",r"\text{2 $\int_{0}^{2.5}$ f(x) dx }").scale(0.67).shift(2.7*RIGHT+2.7*UP)
+ text5[0].set_color(YELLOW)
+ text5[2].set_color(BLUE_C)
+ self.play(FadeOut(text1),FadeOut(scalar_mul))
+ self.wait(1)
+ self.play(ShowCreation(text5))
+ self.wait(3)
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Addition_of_Functions.gif b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Addition_of_Functions.gif
new file mode 100644
index 0000000..6c42b74
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Addition_of_Functions.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Function_Space_Example.gif b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Function_Space_Example.gif
new file mode 100644
index 0000000..996a9de
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Function_Space_Example.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Scalar_Multiplicaton_of_Functions.gif b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Scalar_Multiplicaton_of_Functions.gif
new file mode 100644
index 0000000..8fff2c8
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Function-and-Polynomial-Spaces/gifs3/Scalar_Multiplicaton_of_Functions.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Conjugate_Symmetry_and_Positivity_of_Inner_Product.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Conjugate_Symmetry_and_Positivity_of_Inner_Product.py
new file mode 100644
index 0000000..1d84842
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Conjugate_Symmetry_and_Positivity_of_Inner_Product.py
@@ -0,0 +1,141 @@
+from manimlib.imports import *
+VECTORS = [[0, 2],
+ [1, 1],
+ [0, -2],
+ [1, -1],
+ [2, -2],
+ [2, 2],
+ [2, 2],
+ [-2, -1],
+ [3, 4]]
+class Scene1(LinearTransformationScene):
+ CONFIG = {
+ "include_background_plane": True,
+ "include_foreground_plane": False,
+ "show_coordinates": True,
+ "show_basis_vectors": False,
+ "basis_vector_stroke_width": 3,
+ }
+ def construct(self):
+ text1 = TextMobject(r"\text{$u$}",r"\text{ = $0 + 2i$, }",r"\text{$v$}",r"\text{ = $1 + i$}").scale(0.6).shift(3.5*UP+4*LEFT)
+ text1[0].set_color(YELLOW)
+ text1[2].set_color(RED)
+ text1.add_background_rectangle()
+ self.play(ShowCreation(text1))
+ text2 = TextMobject(r"\text{$\overline{u}$}",r"\text{ = $0 - 2i$, }",r"\text{$\overline{v}$}",r"\text{ = $1 - i$}").scale(0.6).shift(3*UP+4*LEFT)
+ text2[0].set_color(YELLOW)
+ text2[2].set_color(RED)
+ text2.add_background_rectangle()
+ self.play(ShowCreation(text2))
+ self.wait(2)
+ v1 = self.add_vector(VECTORS[0],color = YELLOW, stroke_width = 3.5)
+ u = TextMobject(r"$u$",color=YELLOW).shift(0.3*LEFT+2*UP).scale(0.6)
+ self.play(ShowCreation(u))
+ v1b = self.add_vector(VECTORS[2],color = YELLOW, stroke_width = 3.5)
+ ub = TextMobject(r"$\overline{u}$",color=YELLOW).shift(2*DOWN+0.3*LEFT).scale(0.6)
+ self.play(ShowCreation(ub))
+ self.wait(2)
+ v2 = self.add_vector(VECTORS[1],color = RED, stroke_width = 3.5)
+ v = TextMobject(r"$v$",color=RED).shift(1.2*RIGHT+1*UP).scale(0.6)
+ self.play(ShowCreation(v))
+ v2b = self.add_vector(VECTORS[3],color = RED, stroke_width = 3.5)
+ vb = TextMobject(r"$\overline{v}$",color=RED).shift(1.2*RIGHT+1*DOWN).scale(0.6)
+ self.play(ShowCreation(vb))
+ text3 = TextMobject(r"\text{$<u, v>$}",r"\text{ = }",r"\text{$\overline{u}$",r"\text{$\cdot$}",r"\text{$v$}",r"\text{ = }",r"\text{$2 - 2i$}").shift(2.5*UP+3.7*LEFT).scale(0.6)
+ text3[0].set_color(BLUE)
+ text3[2].set_color(YELLOW)
+ text3[4].set_color(RED)
+ text3.add_background_rectangle()
+ self.play(ShowCreation(text3))
+ self.wait(2)
+ text4 = TextMobject(r"\text{$<\overline{u, v}>$",r"\text{ = }",r"\text{$\overline{u}$",r"\text{$\cdot$}",r"\text{$v$}",r"\text{ = }",r"\text{$2 + 2i$}").shift(2*UP+3.7*LEFT).scale(0.6)
+ text4[0].set_color(BLUE)
+ text4[2].set_color(YELLOW)
+ text4[4].set_color(RED)
+ text4.add_background_rectangle()
+ line = Line(stroke_width = 1.5).scale(0.33).shift(2.2*UP+3.54*LEFT)
+ self.play(ShowCreation(text4),ShowCreation(line))
+ self.wait(2)
+ self.play(FadeOut(v1),FadeOut(v1b),FadeOut(v2),FadeOut(v2b),FadeOut(u),FadeOut(ub),FadeOut(v),FadeOut(vb))
+ v3 = self.add_vector(VECTORS[4],color = BLUE, stroke_width = 3.5)
+ uv = TextMobject(r"$\overline{u}\cdot v$",color=BLUE).shift(2.4*RIGHT+2.1*DOWN).scale(0.6)
+ self.play(ShowCreation(uv))
+ v3b = self.add_vector(VECTORS[5],color = BLUE, stroke_width = 3.5)
+ uvb = TextMobject(r"$\overline{\overline{u}\cdot v}$",color=BLUE).shift(2.4*RIGHT+2.1*UP).scale(0.6)
+ self.play(ShowCreation(uvb))
+ self.wait(2)
+ text5 = TextMobject(r"\text{$<v, u>$}",r"\text{ = }",r"\text{$\overline{v}$",r"\text{$\cdot$}",r"\text{$u$}",r"\text{ = }",r"\text{$2 + 2i$}").shift(1.5*UP+3.7*LEFT).scale(0.6)
+ text5[0].set_color(MAROON_B)
+ text5[2].set_color(RED)
+ text5[4].set_color(YELLOW)
+ text5.add_background_rectangle()
+ self.play(ShowCreation(text5))
+ self.wait(2)
+ v4 = self.add_vector(VECTORS[5],color = MAROON_B, stroke_width = 3.5)
+ vu = TextMobject(r"$\overline{v}\cdot u$",color=MAROON_B).shift(1.3*RIGHT+2.1*UP).scale(0.6)
+ self.play(ShowCreation(vu))
+ self.play(FadeOut(uvb))
+ self.wait(2)
+ text6 = TextMobject(r"\text{$<\overline{u, v}>$",r"\text{ = }",r"\text{$<v, u>$").scale(0.6).shift(0.8*UP+4.2*LEFT)
+ text6[0].set_color(BLUE)
+ text6[2].set_color(MAROON_B)
+ text6.add_background_rectangle()
+ self.play(ShowCreation(text6))
+ rect = Rectangle(height = 0.7,width = 3.5)
+ rect.surround(text6)
+ self.play(ShowCreation(rect))
+ self.wait(3)
+ self.play(FadeOut(line),FadeOut(text1),FadeOut(text2),FadeOut(text3),FadeOut(text4),FadeOut(text5),FadeOut(text6),FadeOut(v4),FadeOut(vu),FadeOut(v3),FadeOut(uv),FadeOut(rect),FadeOut(v3b))
+
+ text7 = TextMobject(r"\text{$u$}",r"\text{ = $(1 + i) > 0$}").scale(0.6).shift(3.5*UP+4.5*LEFT)
+ text7[0].set_color(YELLOW)
+ text7.add_background_rectangle()
+ self.play(ShowCreation(text7))
+ v5 = self.add_vector(VECTORS[1],color = YELLOW, stroke_width = 3.5)
+ u = TextMobject(r"$u$",color=YELLOW).shift(1.2*RIGHT+1*UP).scale(0.6)
+ self.play(ShowCreation(u))
+ self.wait(1.5)
+ text8 = TextMobject(r"\text{$<u, u>$}",r"\text{ = $(0 + 2i) > 0$ }").scale(0.6).shift(2.7*UP+4*LEFT)
+ text8[0].set_color(GREEN)
+ text8.add_background_rectangle()
+ rect1 = Rectangle(height = 0.55, width = 3.3)
+ rect1.surround(text8)
+ self.play(ShowCreation(text8),ShowCreation(rect1))
+ self.wait(2)
+ v6 = self.add_vector(VECTORS[0],color = GREEN, stroke_width = 3.5)
+ uu = TextMobject(r"$<u, u>$",color=GREEN).shift(0.8*LEFT+1.9*UP).scale(0.6)
+ self.play(ShowCreation(uu))
+ text9 = TextMobject(r"\text{$v$}",r"\text{ = $(-2 - i) < 0$}").scale(0.6).shift(1.5*UP+4.4*LEFT)
+ text9[0].set_color(RED)
+ text9.add_background_rectangle()
+ self.play(ShowCreation(text9))
+ self.wait(1.5)
+ v7 = self.add_vector(VECTORS[7],color = RED, stroke_width = 3.5)
+ v = TextMobject(r"$v$",color=RED).shift(2.2*LEFT+1*DOWN).scale(0.6)
+ self.play(ShowCreation(v))
+ self.wait(1.5)
+ text10 = TextMobject(r"\text{$<v, v>$}",r"\text{ = $(3 + 4i) > 0$ }").scale(0.6).shift(0.7*UP+4*LEFT)
+ text10[0].set_color(BLUE)
+ text10.add_background_rectangle()
+ rect2 = Rectangle(height=0.55,width=3.3)
+ rect2.surround(text10)
+ self.play(ShowCreation(text10),ShowCreation(rect2))
+ self.wait(2)
+ v8 = self.add_vector(VECTORS[8],color = BLUE, stroke_width = 3.5)
+ vv = TextMobject(r"$<v, v>$",color=BLUE).shift(2.1*RIGHT+3.8*UP).scale(0.6)
+ self.play(ShowCreation(vv))
+ self.wait(4)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Inner_Product_Example.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Inner_Product_Example.py
new file mode 100644
index 0000000..97b9696
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Inner_Product_Example.py
@@ -0,0 +1,182 @@
+from manimlib.imports import *
+from scipy import sin,cos
+class Inner_Product_Space_Example(GraphScene):
+ CONFIG = {
+ "x_min" : 0,
+ "x_max" : 5,
+ "y_min" : 0,
+ "y_max" : 6,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color":LIGHT_GRAY,
+ "x_labeled_nums" : list(range(6)),
+ "y_labeled_nums" : list(range(6))
+ }
+ def construct(self):
+ self.setup_axes(animate=True)
+ text = TextMobject(r"$f(x), g(x), h(x) \in C[0, 2]$",color=GOLD).scale(0.5).shift(3.5*UP+5.5*LEFT)
+ fx = TextMobject(r"$f(x)$ = sin(x)",color=GOLD).scale(0.5).shift(3*UP+6*LEFT)
+ gx = TextMobject(r"$g(x)$ = x",color=GOLD).scale(0.5).shift(2.5*UP+6.25*LEFT)
+ hx = TextMobject(r"$h(x)$ = 1.4",color=GOLD).scale(0.5).shift(2*UP+6.2*LEFT)
+
+ curve1 = self.get_graph(lambda x : sin(x), x_min=0,x_max=2,color=RED)
+ curve2 = self.get_graph(lambda x : x, x_min=0,x_max=2,color=DARK_BLUE)
+ curve3 = self.get_graph(lambda x : 1.4, x_min=0,x_max=2,color=GREEN)
+ text1 = TextMobject(r"$f(x)$").scale(0.5).shift(1.7*DOWN)
+
+ text2 = TextMobject(r"$g(x)$").scale(0.5).shift(0.34*DOWN)
+ text3 = TextMobject(r"$h(x)$").scale(0.5).shift(1.1*DOWN)
+
+
+ self.play(ShowCreation(text))
+ self.play(ShowCreation(curve1),ShowCreation(text1),ShowCreation(fx))
+ self.wait(1)
+ self.play(ShowCreation(curve2),ShowCreation(text2),ShowCreation(gx))
+ self.wait(1)
+ self.play(ShowCreation(curve3),ShowCreation(text3),ShowCreation(hx))
+ self.wait(2)
+ curve4 = self.get_graph(lambda x : sin(x) + x, x_min=0,x_max=2,color=YELLOW)
+ text4 = TextMobject(r"$f(x) + g(x)$").scale(0.5).shift(0.5*UP+0.5*RIGHT)
+ self.wait(1.5)
+
+ self.play(ShowCreation(curve4),ShowCreation(text4),FadeOut(curve2),FadeOut(text2),FadeOut(curve1),FadeOut(text1))
+ self.wait(1.5)
+ text5 = TextMobject(r"\text{$<f(x) + g(x), h(x)>$ = ",r"\text{$\int_{0}^{2} (f(x) + g(x))h(x)$ $dx$}",r"\text{= 4.78}").scale(0.57).shift(3.3*RIGHT+3.5*UP)
+ text5[1].set_color(ORANGE)
+ self.play(ShowCreation(text5))
+
+ curve5 = self.get_graph(lambda x : (sin(x) + x)*1.6, x_min=0,x_max=2,color=ORANGE)
+ text6 = TextMobject(r"$(f(x) + g(x))\cdot h(x)$").scale(0.5).shift(2.2*UP+0.72*RIGHT)
+ area1 = self.get_area(curve5,0,2)
+ area1.set_color(ORANGE)
+ self.wait(1)
+ self.play(FadeOut(curve4),FadeOut(text4),FadeOut(curve3),FadeOut(text3),ShowCreation(curve5),ShowCreation(text6),ShowCreation(area1))
+ self.wait(2)
+ text7 = TextMobject(r"\text{$<f(x), h(x)>$ = ",r"\text{$\int_{0}^{2} (f(x)h(x)$ $dx$}",r"\text{= 1.98}").scale(0.57).shift(4.5*RIGHT+3*UP)
+ text7[1].set_color(BLUE)
+ self.play(ShowCreation(text7))
+ self.wait(1.5)
+ curve6 = self.get_graph(lambda x : (sin(x))*1.6, x_min=0,x_max=2,color=BLUE)
+ text8 = TextMobject(r"$f(x)\cdot h(x)$").scale(0.5).shift(0.9*DOWN+0.3*RIGHT)
+ area2 = self.get_area(curve6,0,2)
+ self.play(ShowCreation(curve6),ShowCreation(text8),ShowCreation(area2))
+ self.wait(1.5)
+ text9 = TextMobject(r"\text{$<g(x), h(x)>$ = ",r"\text{$\int_{0}^{2} (g(x)h(x)$ $dx$}",r"\text{= 2.8}").scale(0.57).shift(4.5*RIGHT+2.5*UP)
+ text9[1].set_color(MAROON_B)
+ self.play(ShowCreation(text9))
+ self.wait(1.5)
+ curve7 = self.get_graph(lambda x : x*1.6, x_min=0,x_max=2,color=MAROON_B)
+ text10 = TextMobject(r"$g(x)\cdot h(x)$").scale(0.5).shift(0.3*RIGHT+0.78*UP)
+ area3 = self.get_area(curve7,0,2)
+ area3.set_color(MAROON_B)
+ self.play(ShowCreation(curve7),ShowCreation(text10),ShowCreation(area3))
+ self.wait(2.6)
+ curve8 = self.get_graph(lambda x : (sin(x))*1.6 + x*1.6, x_min=0,x_max=2,color=RED_C)
+ area4 = self.get_area(curve8,0,2)
+ area4.set_color(RED_C)
+ text11 = TextMobject(r"$f(x)h(x) + g(x)h(x)$").scale(0.5).shift(2.2*UP + 0.76*RIGHT)
+ self.play(FadeOut(curve6),FadeOut(text8),FadeOut(curve7),FadeOut(text10),FadeOut(area2),FadeOut(area3),ShowCreation(curve8),ShowCreation(area4))
+ self.wait(1)
+ self.play(Transform(text6,text11))
+ self.wait(1.7)
+ text12 = TextMobject(r"$<f(x) + g(x), h(x)>$ = $<f(x), h(x)>$ + $<g(x), h(x)>$").scale(0.465).shift(0.7*UP+4*RIGHT)
+ rect1 = Rectangle(height=0.5)
+ rect1.surround(text12)
+ self.play(ShowCreation(text12),ShowCreation(rect1))
+ self.wait(3)
+ self.play(FadeOut(text6),FadeOut(text5),FadeOut(text7),FadeOut(text9),FadeOut(text12),FadeOut(rect1),FadeOut(curve8),FadeOut(area4),FadeOut(text11),FadeOut(curve5),FadeOut(area1))
+
+ curve2.set_color(ORANGE)
+ self.play(ShowCreation(curve1),ShowCreation(text1))
+ self.wait(1)
+ self.play(ShowCreation(curve2),ShowCreation(text2))
+ self.wait(2)
+ curve9 = self.get_graph(lambda x : 2*sin(x), x_min=0,x_max=2,color=GREEN)
+ text13 = TextMobject(r"$2f(x)$").scale(0.5).shift(0.75*DOWN)
+ self.play(Transform(curve1,curve9),Transform(text1,text13))
+ self.wait(1.5)
+
+ text14 = TextMobject(r"\text{$<2f(x), g(x)>$ = ",r"\text{$\int_{0}^{2} (2f(x))g(x)$ $dx$}",r"\text{= 3.48}").scale(0.57).shift(4*RIGHT+3.5*UP)
+ text14[1].set_color(YELLOW)
+ self.play(ShowCreation(text14))
+ self.wait(2.2)
+ curve10 = self.get_graph(lambda x : 2*sin(x)*x, x_min=0,x_max=2,color=YELLOW)
+ text15 = TextMobject(r"$2f(x)\cdot g(x)$").scale(0.5).shift(0.35*RIGHT+1.03*UP)
+ area5 = self.get_area(curve10,0,2)
+ area5.set_color(YELLOW)
+ self.play(ShowCreation(area5),ShowCreation(curve10),ShowCreation(text15),FadeOut(curve1),FadeOut(text1),FadeOut(curve2),FadeOut(text2))
+ self.wait(2)
+ text16 = TextMobject(r"\text{$<f(x), g(x)>$ = ",r"\text{$\int_{0}^{2} f(x)g(x)$ $dx$}",r"\text{= 1.74}").scale(0.57).shift(3.8*RIGHT+2.9*UP)
+ text16[1].set_color(TEAL)
+ self.play(ShowCreation(text16))
+ self.wait(1.7)
+ curve11 = self.get_graph(lambda x : sin(x)*x, x_min=0,x_max=2,color=TEAL)
+ area6 = self.get_area(curve11,0,2)
+ area6.set_color(TEAL)
+ text17 = TextMobject(r"$f(x)\cdot g(x)$").scale(0.5).shift(0.4*RIGHT+0.7*DOWN)
+ self.play(ShowCreation(curve11),ShowCreation(text17),ShowCreation(area6))
+ self.wait(2)
+
+ text18 = TextMobject(r"\text{$2 <f(x), g(x)>$ = ",r"\text{$2 \int_{0}^{2} f(x)g(x)$ $dx$}",r"\text{= 3.48}").scale(0.57).shift(4*RIGHT+2.3*UP)
+ text18[1].set_color(DARK_BLUE)
+ self.play(ShowCreation(text18))
+ self.wait(2)
+ curve12 = self.get_graph(lambda x : 2*sin(x)*x, x_min=0,x_max=2,color=DARK_BLUE)
+ area7 = self.get_area(curve12,0,2)
+ area7.set_color(DARK_BLUE)
+ text19 = TextMobject(r"= $2( f(x)\cdot g(x) )$").scale(0.5).shift(1.89*RIGHT+1.03*UP)
+ self.play(ShowCreation(curve12),ShowCreation(area7),ShowCreation(text19),FadeOut(text17),FadeOut(area6),FadeOut(curve11))
+
+ self.wait(2.5)
+ text20 = TextMobject(r"$<2f(x), g(x)>$ = $2<f(x), g(x)>$").scale(0.57).shift(0.6*DOWN+4*RIGHT)
+ rect2 = Rectangle(height=0.5)
+ rect2.surround(text20)
+ self.play(ShowCreation(text20),ShowCreation(rect2))
+ self.wait(3)
+
+ self.play(FadeOut(text14),FadeOut(text15),FadeOut(text19),FadeOut(text16),FadeOut(text18),FadeOut(rect2),FadeOut(curve10),FadeOut(area5),FadeOut(curve12),FadeOut(area7),FadeOut(text20))
+ curve1 = self.get_graph(lambda x : sin(x), x_min=0,x_max=2,color=YELLOW)
+ text1 = TextMobject(r"$f(x)$").scale(0.5).shift(1.77*DOWN)
+ self.play(ShowCreation(curve1),ShowCreation(text1))
+ self.wait(1.5)
+ self.play(ShowCreation(curve2),ShowCreation(text2))
+ self.wait(1.7)
+ text21 = TextMobject(r"\text{$<f(x), g(x)>$ = ",r"\text{$\int_{0}^{2} f(x)g(x)$ $dx$}",r"\text{= 1.74}").scale(0.57).shift(3.5*RIGHT+3*UP)
+ text21[1].set_color(GREEN)
+ self.play(ShowCreation(text21))
+ self.wait(2)
+ curve13 = self.get_graph(lambda x : sin(x)*x, x_min=0,x_max=2,color=GREEN)
+ area8 = self.get_area(curve13,0,2)
+ area8.set_color(GREEN)
+ text22 = TextMobject(r"$f(x)\cdot g(x)$").scale(0.5).shift(0.32*RIGHT+0.7*DOWN)
+ self.play(ShowCreation(curve13),ShowCreation(area8),ShowCreation(text22),FadeOut(curve1),FadeOut(text1),FadeOut(curve2),FadeOut(text2))
+ self.wait(2.2)
+ curve14 = self.get_graph(lambda x : sin(x)*x, x_min=0,x_max=2,color=RED)
+ area9 = self.get_area(curve14,0,2)
+ area9.set_color(RED)
+ self.play(ShowCreation(curve14),ShowCreation(area9))
+ text23 = TextMobject(r"= $\overline{f(x)\cdot g(x)}$").scale(0.5).shift(0.7*DOWN+1.7*RIGHT)
+ self.play(ShowCreation(text23))
+ self.wait(2)
+ text24 = TextMobject(r"For all the real functions").scale(0.5).shift(2*RIGHT+2*UP)
+ text25 = TextMobject(r"$<\overline{f(x), g(x)}>$ = $<f(x), g(x)>$").scale(0.5).shift(2*RIGHT+1.4*UP)
+ rect3 = Rectangle(height=0.7)
+ rect3.surround(text25)
+ self.play(ShowCreation(text24),ShowCreation(text25),ShowCreation(rect3))
+ self.wait(3)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Inner_product.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Inner_product.py
new file mode 100644
index 0000000..e1344f7
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Inner_product.py
@@ -0,0 +1,28 @@
+from manimlib.imports import *
+import numpy as np
+class InnerProduct(Scene):
+ def construct(self):
+ big_box=Rectangle().scale(2.7)
+ box = Rectangle(height=2,width=2,color=DARK_GREY).set_fill(color=BLUE_B,opacity=350)
+ arrow1 = Arrow(color=RED).shift(1.8*LEFT+0.5*UP)
+ arrow2 = Arrow(color=RED).shift(1.8*LEFT+0.5*DOWN)
+ arrow3 = Arrow(color=GREEN).shift(1.8*RIGHT)
+ Inner = TextMobject("INNER",color=BLACK).scale(0.65).shift(0.2*UP)
+ Product = TextMobject("PRODUCT",color=BLACK).scale(0.65).shift(0.2*DOWN)
+ u = TextMobject(r"$\vec{u}$",color=YELLOW).scale(0.7).shift(2.8*LEFT+0.5*UP)
+ v = TextMobject(r"$\vec{v}$",color=YELLOW).scale(0.7).shift(2.8*LEFT+0.5*DOWN)
+ scalar = TextMobject("(Scalar)").scale(0.55).shift(3.3*RIGHT+0.4*DOWN)
+ u.v = TextMobject(r"$<\vec{u}, \vec{v}>$",color=YELLOW).scale(0.7).shift(3.3*RIGHT)
+ V = TextMobject("V").scale(0.7).shift(2*UP+3.8*RIGHT)
+ text = TextMobject(r"The Inner Product is an operation that takes $\vec{u}, \vec{v} \in$ V as inputs and gives a scalar as an output.").scale(0.55).shift(2*DOWN)
+ self.play(ShowCreation(big_box),ShowCreation(V))
+ self.play(ShowCreation(box))
+ self.play(ShowCreation(Product),ShowCreation(Inner))
+ self.wait(2)
+ self.play(ShowCreation(arrow1),ShowCreation(u))
+ self.play(ShowCreation(arrow2),ShowCreation(v))
+ self.wait(1.5)
+ self.play(ShowCreation(arrow3),ShowCreation(scalar),ShowCreation(u.v))
+ self.wait(1)
+ self.play(ShowCreation(text))
+ self.wait(10)
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Instances_of_Topological_Spaces.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Instances_of_Topological_Spaces.py
new file mode 100644
index 0000000..2b3cf14
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Instances_of_Topological_Spaces.py
@@ -0,0 +1,36 @@
+from manimlib.imports import *
+class InnerProduct(Scene):
+ def construct(self):
+
+ circle1 = Circle(color=DARK_GREY).scale(3.7)
+ circle1.set_fill(color=GOLD,opacity=350)
+ square1 = Square(color=DARK_GREY).scale(2.5)
+ square1.set_fill(color=DARK_BLUE,opacity=350)
+ square2=Square(color=DARK_GREY).scale(1.6).shift(0.2*DOWN)
+ square2.rotate(np.pi/4).set_fill(color=YELLOW,opacity=350)
+ square3 = Square(color=DARK_GREY).scale(1).shift(0.3*DOWN)
+ square3.set_fill(color=BLACK,opacity=350)
+ circle2 = Circle(color=DARK_GREY).scale(0.5).shift(0.45*DOWN)
+ circle2.set_fill(color=MAROON_A,opacity=350)
+ text1 = TextMobject("Topological Spaces",color=BLACK).scale(0.5).shift(3*UP)
+ text2 = TextMobject("Metric Spaces",color=BLACK).scale(0.5).shift(2.2*UP)
+ text3 = TextMobject("Normed",color=BLACK).scale(0.44).shift(1.4*UP)
+ text4 = TextMobject("Vector Spaces",color=BLACK).scale(0.44).shift(1.17*UP)
+ text5 = TextMobject("Inner Product",color=WHITE).scale(0.37).shift(0.5*UP)
+ text6 = TextMobject("Spaces",color=WHITE).scale(0.37).shift(0.27*UP)
+ text7 = TextMobject("Dot",color=BLACK).scale(0.37).shift(0.3*DOWN)
+ text8 = TextMobject("Product",color=BLACK).scale(0.32).shift(0.5*DOWN)
+
+
+
+
+ self.play(ShowCreation(circle1),ShowCreation(text1))
+ self.wait(1.5)
+ self.play(ShowCreation(square1),ShowCreation(text2))
+ self.wait(1.5)
+ self.play(ShowCreation(square2),ShowCreation(text3),ShowCreation(text4))
+ self.wait(1.5)
+ self.play(ShowCreation(square3),ShowCreation(text5),ShowCreation(text6))
+ self.wait(1.5)
+ self.play(ShowCreation(circle2),ShowCreation(text7),ShowCreation(text8))
+ self.wait(4)
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Interpretation_of_Norm_as_Length.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Interpretation_of_Norm_as_Length.py
new file mode 100644
index 0000000..23c568d
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Interpretation_of_Norm_as_Length.py
@@ -0,0 +1,42 @@
+from manimlib.imports import *
+import numpy as np
+class Interpretation_of_norm_as_length(GraphScene):
+ CONFIG = {
+ "x_min" : 0,
+ "x_max" : 5,
+ "y_min" : 0,
+ "y_max" : 5,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "axes_color":LIGHT_GRAY,
+ "x_axis_width": 5,
+ "y_axis_height":5,
+ "graph_origin" : ORIGIN + 2*DOWN + 2*LEFT,
+ "enclude_zero_label": False
+
+ }
+ def construct(self):
+ self.setup_axes(animate=False)
+ dot = Dot().scale(0.5)
+ self.play(ShowCreation(dot))
+ origin = TextMobject(r"(0, 0)").scale(0.5).shift(2.5*LEFT+2.2*DOWN)
+ line1 = self.get_graph(lambda x : x, x_min=0,x_max=2,color=WHITE)
+ line2 = Line().rotate(np.pi/2).shift(1*DOWN)
+ text1 = TextMobject(r"$(v_1, 0)$").scale(0.5).shift(2.2*DOWN+0.2*RIGHT)
+ text2 = TextMobject(r"$(0, v_2)$").scale(0.5).shift(2.5*LEFT)
+ text3 = TextMobject(r"$(v_1, v_2)$").scale(0.5).shift(0.5*RIGHT)
+ text4 = TextMobject(r"$| v_1 |$",color=RED_B).scale(0.5).shift(1*LEFT+2.3*DOWN)
+ text5 = TextMobject(r"$| v_2 |$",color=RED_B).scale(0.5).shift(0.3*RIGHT+1*DOWN)
+ text6 = TextMobject(r"$\sqrt{{v_1}^2 + {v_2}^2}$",color=RED_B).scale(0.5).rotate(np.pi/4).shift(1.3*LEFT+1*DOWN)
+ line3 = Line(color=YELLOW).shift(1*LEFT+2*DOWN)
+ self.play(ShowCreation(line1),ShowCreation(line2),ShowCreation(text1),ShowCreation(text2),ShowCreation(text3),ShowCreation(origin))
+ self.wait(1.5)
+ self.play(ShowCreation(line3),ShowCreation(text4))
+ self.wait(1.5)
+ line2 = Line(color=YELLOW).rotate(np.pi/2).shift(1*DOWN)
+ self.play(ShowCreation(line2),ShowCreation(text5))
+ self.wait(1.5)
+ line1 = self.get_graph(lambda x : x, x_min=0,x_max=2,color=YELLOW)
+ self.play(ShowCreation(text6),ShowCreation(line1))
+ self.wait(4)
+ \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Linearity_of_Inner_Product.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Linearity_of_Inner_Product.py
new file mode 100644
index 0000000..e1344f7
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Linearity_of_Inner_Product.py
@@ -0,0 +1,28 @@
+from manimlib.imports import *
+import numpy as np
+class InnerProduct(Scene):
+ def construct(self):
+ big_box=Rectangle().scale(2.7)
+ box = Rectangle(height=2,width=2,color=DARK_GREY).set_fill(color=BLUE_B,opacity=350)
+ arrow1 = Arrow(color=RED).shift(1.8*LEFT+0.5*UP)
+ arrow2 = Arrow(color=RED).shift(1.8*LEFT+0.5*DOWN)
+ arrow3 = Arrow(color=GREEN).shift(1.8*RIGHT)
+ Inner = TextMobject("INNER",color=BLACK).scale(0.65).shift(0.2*UP)
+ Product = TextMobject("PRODUCT",color=BLACK).scale(0.65).shift(0.2*DOWN)
+ u = TextMobject(r"$\vec{u}$",color=YELLOW).scale(0.7).shift(2.8*LEFT+0.5*UP)
+ v = TextMobject(r"$\vec{v}$",color=YELLOW).scale(0.7).shift(2.8*LEFT+0.5*DOWN)
+ scalar = TextMobject("(Scalar)").scale(0.55).shift(3.3*RIGHT+0.4*DOWN)
+ u.v = TextMobject(r"$<\vec{u}, \vec{v}>$",color=YELLOW).scale(0.7).shift(3.3*RIGHT)
+ V = TextMobject("V").scale(0.7).shift(2*UP+3.8*RIGHT)
+ text = TextMobject(r"The Inner Product is an operation that takes $\vec{u}, \vec{v} \in$ V as inputs and gives a scalar as an output.").scale(0.55).shift(2*DOWN)
+ self.play(ShowCreation(big_box),ShowCreation(V))
+ self.play(ShowCreation(box))
+ self.play(ShowCreation(Product),ShowCreation(Inner))
+ self.wait(2)
+ self.play(ShowCreation(arrow1),ShowCreation(u))
+ self.play(ShowCreation(arrow2),ShowCreation(v))
+ self.wait(1.5)
+ self.play(ShowCreation(arrow3),ShowCreation(scalar),ShowCreation(u.v))
+ self.wait(1)
+ self.play(ShowCreation(text))
+ self.wait(10)
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Projection-in-3D-space.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Projection-in-3D-space.py
new file mode 100644
index 0000000..e99202f
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Projection-in-3D-space.py
@@ -0,0 +1,31 @@
+from manimlib.imports import *
+class ThreeDSpace(ThreeDScene):
+
+ def construct(self):
+ axes = ThreeDAxes()
+ axes.set_stroke(width=1,color=GOLD)
+ self.add(axes)
+ self.set_camera_orientation(phi = 70*DEGREES,theta =110*DEGREES)
+ line1 = Line(color = YELLOW,opacity=350,start = ORIGIN,end = [0.5,2,2])
+ self.play(ShowCreation(line1))
+ self.wait(1)
+ line2 = Line(color = BLUE,opacity=350,start = ORIGIN,end = [2,2,-1])
+ self.play(ShowCreation(line2))
+ self.wait(1)
+ line3 = Line(opacity=350,start=axes.c2p(0.5,2,2) ,end=axes.c2p(0.5,1.14,-0.17))
+ self.play(ShowCreation(line3))
+ self.wait(1)
+ line4 = Line(color=RED,opacity=350,start = ORIGIN,end=[0.5,1.14,-0.145])
+ self.play(ShowCreation(line4))
+ self.wait(2)
+ text1 = TextMobject(r"\text{Projection on }",r"\text{$\vec{v}$}",r"\text{ onto }",r"\text{$\vec{u}$}",r"\text{ = }",r"\text{$ |\vec{v}|cos\theta$,}").scale(0.6).shift(4*LEFT+3.5*UP)
+ text1[1].set_color(YELLOW)
+ text1[3].set_color(BLUE)
+ text1[5].set_color(RED)
+ text2 = TextMobject(r"\text{where $\theta$ is the angle between the vectors.}").scale(0.6).shift(4*LEFT+3*UP)
+ self.add_fixed_in_frame_mobjects(text1)
+ self.add_fixed_in_frame_mobjects(text2)
+ self.play(ShowCreation(text1),ShowCreation(text2))
+ self.wait(3)
+
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Vector_Projection.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Vector_Projection.py
new file mode 100644
index 0000000..b1724c1
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/Vector_Projection.py
@@ -0,0 +1,43 @@
+from manimlib.imports import *
+VECTORS = [[3,1],
+ [1,3],
+ [1.96,0.65]]
+class Projection(LinearTransformationScene):
+ CONFIG = {
+ "include_background_plane": True,
+ "include_foreground_plane": False,
+ "show_coordinates": False,
+ "show_basis_vectors": False,
+ "basis_vector_stroke_width": 3,
+ }
+ def construct(self):
+ v1 = self.add_vector(VECTORS[0],color = YELLOW, stroke_width = 3.5)
+ u = TextMobject(r"$\vec{u}$",color=YELLOW).scale(0.65).shift(3.2*RIGHT,1*UP)
+ self.play(ShowCreation(u))
+ self.wait(0.7)
+ v2 = self.add_vector(VECTORS[1],color = RED, stroke_width = 3.5)
+ v = TextMobject(r"$\vec{v}$",color=RED).scale(0.65).shift(1.2*RIGHT,3*UP)
+ self.play(ShowCreation(v))
+ self.wait(0.7)
+ angle = Arc(radius=0.6).scale(0.5)
+ theta = TextMobject(r"$\theta$").scale(0.65).shift(0.5*UP+0.5*RIGHT).rotate(np.pi/6)
+ self.play(ShowCreation(angle),ShowCreation(theta))
+ self.wait(1)
+ line1 = Line().scale(1.25).rotate(np.pi/(2)).shift(1.8*UP+1.47*RIGHT)
+ line1.rotate(np.pi/8)
+ self.play(ShowCreation(line1))
+ self.wait(1.3)
+ v3 = self.add_vector(VECTORS[2],color = BLUE, stroke_width = 3.5)
+ text1 = TextMobject(r"$\vec{v}$cos$\theta$",color=BLUE).scale(0.55).shift(1.25*RIGHT+0.26*UP).rotate(np.pi/9)
+ self.play(ShowCreation(text1))
+ self.wait(2)
+ text2 = TextMobject(r"\text{Projection on }",r"\text{$\vec{v}$}",r"\text{ onto }",r"\text{$\vec{u}$}",r"\text{ = }",r"\text{$ |\vec{v}|cos\theta$}").scale(0.6).shift(4*RIGHT+3*UP)
+ text2[1].set_color(RED)
+ text2[3].set_color(YELLOW)
+ text2[5].set_color(BLUE)
+ text2.add_background_rectangle()
+ self.play(ShowCreation(text2))
+ self.wait(4)
+
+
+ \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Conjugate_Symmetry_and_Positivity_of_Inner_Product.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Conjugate_Symmetry_and_Positivity_of_Inner_Product.mp4
new file mode 100644
index 0000000..6b44c55
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Conjugate_Symmetry_and_Positivity_of_Inner_Product.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/InnerProduct.gif b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/InnerProduct.gif
new file mode 100644
index 0000000..55b6546
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/InnerProduct.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Inner_Product_Space_Example.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Inner_Product_Space_Example.mp4
new file mode 100644
index 0000000..edecd88
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Inner_Product_Space_Example.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Instances_of_Topological_Spaces.gif b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Instances_of_Topological_Spaces.gif
new file mode 100644
index 0000000..82d5c75
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Instances_of_Topological_Spaces.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Interpretation_of_norm_as_length.gif b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Interpretation_of_norm_as_length.gif
new file mode 100644
index 0000000..9eda7c5
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Interpretation_of_norm_as_length.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Linerity_of_Inner_Product.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Linerity_of_Inner_Product.mp4
new file mode 100644
index 0000000..a1e7b29
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Linerity_of_Inner_Product.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Projection.gif b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Projection.gif
new file mode 100644
index 0000000..c32fd6b
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Projection.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Projection_of_vectors_in-3D_plane.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Projection_of_vectors_in-3D_plane.mp4
new file mode 100644
index 0000000..bdca5f9
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Inner-Product_Spaces/gifs2/Projection_of_vectors_in-3D_plane.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Basis of a Vector Space and its Subspace.docx b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Basis of a Vector Space and its Subspace.docx
new file mode 100644
index 0000000..0dbfc4f
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Basis of a Vector Space and its Subspace.docx
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Dual of a Space MCQ Questions.docx b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Dual of a Space MCQ Questions.docx
new file mode 100644
index 0000000..1731a8f
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Dual of a Space MCQ Questions.docx
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Inner Product Space MCQ Questions.docx b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Inner Product Space MCQ Questions.docx
new file mode 100644
index 0000000..80ee81c
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Inner Product Space MCQ Questions.docx
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Polynomial and Function Spaces MCQ Questions.docx b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Polynomial and Function Spaces MCQ Questions.docx
new file mode 100644
index 0000000..7904fd1
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Polynomial and Function Spaces MCQ Questions.docx
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Vector Spaces MCQ Questions.docx b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Vector Spaces MCQ Questions.docx
new file mode 100644
index 0000000..338b6f3
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/MCQ/Vector Spaces MCQ Questions.docx
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Basis.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Basis.py
new file mode 100644
index 0000000..6d2edc8
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Basis.py
@@ -0,0 +1,174 @@
+from manimlib.imports import *
+
+
+VECTORS = [[1, 2],
+ [-4, 2],
+ [-3, -3],
+ [3,-2],
+ [3,3],
+ [-2,1],
+ [-1,-3]]
+
+class Scene1(LinearTransformationScene):
+
+ CONFIG = {
+ "include_background_plane": True,
+ "include_foreground_plane": False,
+ "show_coordinates": False,
+ "show_basis_vectors": True,
+ "basis_vector_stroke_width": 3,
+
+ }
+ def construct(self):
+ self.setup()
+ ihat, jhat = self.get_basis_vectors()
+ labels = self.get_basis_vector_labels()
+ self.add(ihat, jhat)
+ self.add(*labels)
+
+ self.show_vector_as_basis_sum()
+ self.wait(2)
+
+ def show_vector_as_basis_sum(self):
+ text1 = TextMobject(r"Vector Space $\mathbb{R}^2$}").scale(0.8).shift(3*UP)
+ text1.add_background_rectangle()
+ self.play(ShowCreation(text1))
+ text2 = TextMobject(r"$\mathbb{R}^2$",color=BLUE_E).scale(0.8).shift(6.5*LEFT+3.5*UP)
+ text3 = TextMobject(r"\text{Basis Vectors:}",r"\text{$\hat{i}$}",r"\text{,}",r"\text{$\hat{j}$}").scale(0.7).shift(2*UP+2.5*RIGHT)
+ text3[1].set_color(GREEN_C)
+ text3[3].set_color(RED_C)
+
+ self.wait(2)
+ self.play(Transform(text1,text2))
+ self.wait(1)
+ self.play(ShowCreation(text3))
+ self.wait(1.7)
+ self.play(FadeOut(text3))
+
+ for i in range(len(VECTORS)):
+ v = self.add_vector(VECTORS[i], stroke_width = 3,color=YELLOW_D)
+
+ linei = Line(start = ORIGIN, end = VECTORS[i][0]*RIGHT)
+ linei.set_color(GREEN_C)
+ linej = Line(start = linei.get_end(),
+ end = linei.get_end() + VECTORS[i][1]*UP)
+ linej.set_color(RED_C)
+ self.play(ShowCreation(linei))
+ self.play(ShowCreation(linej))
+ vlabel = self.get_vector_label(v, str(VECTORS[i][0]) +
+ r"\imath" + "+" +
+ str(VECTORS[i][1]) +
+ r"\jmath", at_tip = True)
+ self.play(ShowCreation(vlabel))
+
+ self.play(FadeOut(linei),FadeOut(linej))
+ self.wait(1)
+ dot = Dot(v.get_end(), fill_color = v.get_stroke_color())
+ self.play(ShowCreation(dot),FadeOut(v),FadeOut(vlabel))
+ self.wait(0.3)
+
+class Scene2(LinearTransformationScene):
+ CONFIG = {
+ "num_vectors" : 16,
+ "start_color" : GREY,
+ "end_color" : YELLOW_D,
+ "include_background_plane": True,
+ "include_foreground_plane": False,
+ }
+
+ def get_vectors(self):
+ return [
+ Vector([x, y], stroke_width = 3.5)
+ for x in np.arange(-int(FRAME_X_RADIUS), int(FRAME_X_RADIUS)+0.5, 0.5)
+ for y in np.arange(-int(FRAME_Y_RADIUS), int(FRAME_Y_RADIUS)+0.5, 0.5)
+ ]
+
+ def lock_in_faded_grid(self, dimness=0.7, axes_dimness=0.5):
+ plane = self.add_plane()
+ axes = plane.get_axes()
+ plane.fade(dimness)
+ axes.set_color(WHITE)
+ axes.fade(axes_dimness)
+ self.add(axes)
+
+ def construct(self):
+ self.lock_in_faded_grid()
+
+ vectors = self.get_vectors()
+ colors = Color(self.start_color).range_to(
+ self.end_color, len(vectors)
+ )
+ for vect, color in zip(vectors, colors):
+ vect.set_color(color)
+
+ vector_group = VGroup(*vectors)
+ self.play(
+ ShowCreation(
+ vector_group,
+ run_time = 3
+ )
+ )
+
+ self.wait(1)
+
+ vectors.sort(key=lambda v: v.get_length())
+ def v_to_dot(vector):
+ return Dot(vector.get_end(), fill_color = vector.get_stroke_color())
+ self.wait()
+ rate_functions = [
+ squish_rate_func(smooth, float(x)/(len(vectors)+2), 1)
+ for x in range(len(vectors))
+ ]
+ self.play(*[
+ Transform(v, v_to_dot(v), rate_func = rf, run_time = 3)
+ for v, rf in zip(vectors, rate_functions)
+ ])
+ self.wait(2)
+ self.play_final_animation(vectors, rate_functions)
+ self.wait(2)
+
+ text1 = TextMobject(" Basis is the minimum information required to ").shift(3.1*UP).scale(0.8)
+ text2 = TextMobject("generate the whole space.").scale(0.8).shift(2.6*UP)
+
+ text1.add_background_rectangle()
+ text2.add_background_rectangle()
+
+
+
+ self.play(ShowCreation(text1),ShowCreation(text2))
+
+ self.play(ShowCreation(self.get_basis_vectors()))
+ self.wait(3)
+
+ def play_final_animation(self, vectors, rate_functions):
+
+ h_line = Line(
+ FRAME_X_RADIUS*RIGHT, FRAME_X_RADIUS*LEFT,
+ stroke_width = 0.5,
+ color = BLUE_E
+ )
+ v_line = Line(
+ FRAME_Y_RADIUS*UP, FRAME_Y_RADIUS*DOWN,
+ stroke_width = 0.5,
+ color = BLUE_E
+ )
+ line_pairs = [
+ VGroup(h_line.copy().shift(y), v_line.copy().shift(x))
+ for v in vectors
+ for x, y, z in [v.get_center()]
+ ]
+ plane = NumberPlane()
+
+ self.play(
+ ShowCreation(plane),
+ *[
+ Transform(v, p, rate_func = rf)
+ for v, p, rf in zip(vectors, line_pairs, rate_functions)
+ ]
+ )
+ self.remove(*vectors)
+
+
+
+
+ \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Intersection_of_Subspaces.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Intersection_of_Subspaces.py
new file mode 100644
index 0000000..ec82daa
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Intersection_of_Subspaces.py
@@ -0,0 +1,52 @@
+from manimlib.imports import *
+class ThreeDSpace(ThreeDScene):
+
+
+ def construct(self):
+ axes = ThreeDAxes()
+ self.set_camera_orientation(phi = 80*DEGREES,theta =110*DEGREES)
+ self.begin_ambient_camera_rotation(rate=0.09)
+
+
+
+
+ cube = Cube(stroke_width=5,color=WHITE).shift([1.5,1.5,1.5]).scale(1.5)
+ cube.set_fill(TEAL)
+
+ cube.set_opacity(0.4)
+
+
+ plane1 = Polygon([0,0,3],[3,0,3],[3,3,0],[0,3,0])
+ plane1.set_opacity(0.65)
+ plane1.set_fill(PURPLE)
+ plane1.set_color(PURPLE)
+
+
+ plane2 = Polygon([0,3,3],[3,3,3],[3,0,0],[0,0,0])
+ plane2.set_opacity(0.7)
+ plane2.set_fill(RED)
+ plane2.set_color(RED)
+ line = Line(color=YELLOW,set_opacity=100).shift([1.5,1.5,1.5]).scale(1.5)
+
+ vgroup = VGroup(plane1,plane2,line,cube)
+ vgroup.shift([-1,-1,-1])
+
+ dot = Dot(color=BLACK).shift([0.5,0.5,0.5]).scale(1)
+ text = TextMobject(r"\text{The}",r"\text{line}",r"\text{representing the intersection of the two planes is a Subspace.}",opacity = 0.6).scale(0.7).shift(3*UP)
+ text[1].set_color(YELLOW)
+ self.add_fixed_in_frame_mobjects(text)
+ self.play(ShowCreation(text))
+
+
+ self.play(ShowCreation(cube))
+ self.play(ShowCreation(plane1))
+ self.play(ShowCreation(plane2))
+
+ self.play(ShowCreation(line),ShowCreation(dot))
+
+
+ self.wait(15)
+
+
+
+ \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Straight_Line_through_Origin.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Straight_Line_through_Origin.py
new file mode 100644
index 0000000..5790d2e
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Straight_Line_through_Origin.py
@@ -0,0 +1,48 @@
+from manimlib.imports import *
+from scipy import exp, sin, log,tan,cos
+class Straight_Line(GraphScene):
+ CONFIG = {
+ "x_min" : -4,
+ "x_max" : 4,
+ "y_min" : -4,
+ "y_max" : 4,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "x_labeled_nums" : list(np.arange(-4,5,1)),
+ "y_labeled_nums" : list(np.arange(-4,5,1)),
+ "graph_origin" : ORIGIN+0.7*DOWN,
+ "axes_color" : GREY,
+ "x_axis_width": 6,
+ "y_axis_height":6,
+ }
+ def construct(self):
+ self.setup_axes(animate=True)
+ line_1 = self.get_graph(lambda x : x, x_min=-3,x_max=3,color=YELLOW)
+ self.play(ShowCreation(line_1))
+ text1 = TextMobject("ax + by = 0",color=BLUE_B)
+ text1.shift(3*RIGHT+2*UP)
+ text1.scale(0.65)
+ dot = Dot(color=BLUE_B).shift(0.7*DOWN)
+ dot.scale(1.3)
+ self.play(ShowCreation(dot))
+ text2 = TextMobject("Line passing through the origin")
+ text2.scale(0.7)
+ text2.shift(3.5*UP)
+ self.play(ShowCreation(text1),ShowCreation(text2))
+ self.wait(1)
+ self.play(FadeOut(line_1),FadeOut(text2),FadeOut(text1))
+ text4=TextMobject("Line not passing through the origin")
+ text4.scale(0.7)
+ text4.shift(3.5*UP)
+ self.play(ShowCreation(text4))
+
+ line_2 = self.get_graph(lambda x : 2.5*x +1, x_min = -2, x_max=1, color = RED)
+ text3 = TextMobject(r"ax + by $\neq 0$",color=BLUE_B)
+ text3.scale(0.65)
+ self.play(ShowCreation(line_2))
+ text3.shift(1.5*RIGHT+2.2*UP)
+ self.play(ShowCreation(text3))
+ self.wait(1)
+
+
+ \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Subspace_Non_Example.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Subspace_Non_Example.py
new file mode 100644
index 0000000..115a722
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Subspace_Non_Example.py
@@ -0,0 +1,25 @@
+from manimlib.imports import *
+class ThreeDSpace(ThreeDScene):
+
+
+ def construct(self):
+ axes = ThreeDAxes()
+ self.add(axes)
+ self.set_camera_orientation(phi = 80*DEGREES,theta =110*DEGREES)
+ self.begin_ambient_camera_rotation(rate=0.09)
+ plane1 = Polygon([-1.5,1.5,-1.5],[1.5,1.5,-1.5],[1.5,-1.5,1.5],[-1.5,-1.5,1.5])
+ plane1.set_opacity(0.65)
+ plane1.set_fill(GREEN)
+ plane1.set_color(GREEN)
+
+
+ plane2 = Polygon([-1.5,1.5,1.5],[1.5,1.5,1.5],[1.5,-1.5,-1.5],[-1.5,-1.5,-1.5])
+ plane2.set_opacity(0.7)
+ plane2.set_fill(MAROON_A)
+ plane2.set_color(MAROON_A)
+ line = Line(color=YELLOW,set_opacity=100,start=[1.5,1.2,1.2],end=[-1.5,1.2,1.2])
+
+
+ self.play(ShowCreation(plane1),ShowCreation(plane2),ShowCreation(line))
+ self.wait(10)
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Unit_Circle.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Unit_Circle.py
new file mode 100644
index 0000000..2973f08
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/Unit_Circle.py
@@ -0,0 +1,68 @@
+from manimlib.imports import *
+import numpy as np
+import math
+
+class Unit_Circle(GraphScene):
+ CONFIG = {
+ "x_min" : -3,
+ "x_max" : 3,
+ "y_min" : -3,
+ "y_max" : 3,
+ "y_tick_frequency" : 1,
+ "x_tick_frequency" : 1,
+ "x_labeled_nums" : list(np.arange(-3,4,1)),
+ "y_labeled_nums" : list(np.arange(-3,4,1)),
+ "graph_origin" : ORIGIN,
+ "axes_color" : GREY,
+ "x_axis_width": 6,
+ "y_axis_height":6,
+ }
+
+ def construct(self):
+ self.setup_axes(animate = True)
+ circle = Circle(radius=1,color=BLUE)
+ self.play(ShowCreation(circle))
+ dot1 = Dot(color=RED).scale(0.7)
+ dot1.shift(1*UP)
+ dot2 = Dot(color=RED).scale(0.7)
+ dot2.shift(1*LEFT)
+ dot3 = Dot(color=RED).scale(0.7)
+ dot3.shift(1*DOWN)
+ dot4 = Dot(color=RED).scale(0.7)
+ dot4.shift(1*RIGHT)
+ dot5= Dot(color=RED).scale(0.7)
+ dot6 = Dot(color=RED).scale(0.7)
+ dot5.shift(0.5*RIGHT+(math.sqrt(3)/2)*UP)
+ dot6.shift(0.5*LEFT+(math.sqrt(3)/2)*DOWN)
+ dot7 = Dot(color=RED).scale(0.7)
+ dot7.shift(math.sqrt(2)/2*RIGHT+math.sqrt(2)/2*UP)
+ dot8 = Dot(color=RED).scale(0.7)
+ dot8.shift(math.sqrt(2)/2*LEFT+math.sqrt(2)/2*UP)
+ dot9 = Dot(color=RED).scale(0.7)
+ dot9.shift(0.5*LEFT+(math.sqrt(3)/2)*UP)
+ dot10 = Dot(color=RED).scale(0.7)
+ dot10.shift(math.sqrt(3)/2*LEFT+0.5*UP)
+ dot11=Dot(color=RED).scale(0.7)
+ dot11.shift(math.sqrt(3)/2*RIGHT+0.5*UP)
+ dot12= Dot(color=RED).scale(0.7)
+ dot12.shift(math.sqrt(3)/2*LEFT+0.5*DOWN)
+ dot13=Dot(color=RED).scale(0.7)
+ dot13.shift(math.sqrt(2)/2*RIGHT+math.sqrt(2)/2*DOWN)
+ dot14=Dot(color=RED).scale(0.7)
+ dot14.shift(math.sqrt(2)/2*LEFT+math.sqrt(2)/2*DOWN)
+ dot15=Dot(color=RED).scale(0.7)
+ dot15.shift(math.sqrt(3)/2*RIGHT+0.5*DOWN)
+ dot16=Dot(color=RED).scale(0.7)
+ dot16.shift(0.5*RIGHT+(math.sqrt(3)/2)*DOWN)
+ self.play(ShowCreation(dot1),ShowCreation(dot2))
+ self.play(ShowCreation(dot3),ShowCreation(dot4))
+ self.play(ShowCreation(dot5),ShowCreation(dot6))
+ self.play(ShowCreation(dot7),ShowCreation(dot8))
+ self.play(ShowCreation(dot9),ShowCreation(dot10))
+ self.play(ShowCreation(dot11),ShowCreation(dot12))
+ self.play(ShowCreation(dot13),ShowCreation(dot14))
+ self.play(ShowCreation(dot15),ShowCreation(dot16))
+ self.wait(4)
+
+
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Basis_generating_the_whole_2D_space.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Basis_generating_the_whole_2D_space.mp4
new file mode 100644
index 0000000..9a43846
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Basis_generating_the_whole_2D_space.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Intersection_of_Subspaces.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Intersection_of_Subspaces.mp4
new file mode 100644
index 0000000..d43bfbe
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Intersection_of_Subspaces.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Linear-Dependence-and-Independence.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Linear-Dependence-and-Independence.mp4
new file mode 100644
index 0000000..c44801f
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Linear-Dependence-and-Independence.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Straight_Line_Through_Origin.gif b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Straight_Line_Through_Origin.gif
new file mode 100644
index 0000000..b7695a4
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Straight_Line_Through_Origin.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Subspace_Non_Example.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Subspace_Non_Example.mp4
new file mode 100644
index 0000000..390f4cf
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Subspace_Non_Example.mp4
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Unit_Circle.gif b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Unit_Circle.gif
new file mode 100644
index 0000000..165d040
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/gifs/Unit_Circle.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/linear_dependence_and_independence.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/linear_dependence_and_independence.py
new file mode 100644
index 0000000..b092777
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Subspaces/linear_dependence_and_independence.py
@@ -0,0 +1,293 @@
+from manimlib.imports import *
+class Linear_Dependence(ThreeDScene):
+
+ def construct(self):
+
+ axes = ThreeDAxes()
+ axes.set_stroke(width=1,color=GOLD)
+ self.add(axes)
+ self.set_camera_orientation(phi = 70*DEGREES,theta =110*DEGREES)
+ self.begin_ambient_camera_rotation(rate=0.05)
+ self.wait(0.5)
+ text1 = TextMobject(r"Consider 3 linearly dependent vectors in $\mathbb{R}^3$").scale(0.5).shift(2.5*UP+4*LEFT)
+ line1 = Line(color = YELLOW,opacity=350,start = ORIGIN,end = [-1,1,1])
+ self.add_fixed_in_frame_mobjects(text1)
+ self.play(ShowCreation(text1))
+ self.play(ShowCreation(line1))
+ self.wait(1)
+ line2 = Line(color = RED,opacity=350,start = ORIGIN,end = [1,0.5,0.5])
+ self.play(ShowCreation(line2))
+ self.wait(1)
+ line3 = Line(color = BLUE,opacity=350,start = ORIGIN,end = [0.5,1,1])
+ self.play(ShowCreation(line3))
+ self.wait(1)
+ text2 = TextMobject("Scaling the Vectors").scale(0.5).shift(2.5*UP+4.5*LEFT)
+ text3 = TextMobject(r"\text{and}",r"\text{Adding}",r"\text{them}").scale(0.5).shift(2*UP+4.5*LEFT)
+ text3[1].set_color(GREEN)
+
+
+ line4 = Line(color = YELLOW,opacity=350,start = ORIGIN,end = [-2,2,2])
+ line5 = Line(color = RED,opacity = 350,start = ORIGIN,end = [3,1.5,1.5])
+ line6 = Line(color = BLUE,opacity = 350,start = ORIGIN,end = [-0.5,-1,-1])
+ self.wait(1.1)
+ self.play(FadeOut(text1))
+ self.add_fixed_in_frame_mobjects(text2)
+ self.play(ShowCreation(text2))
+ self.wait(0.7)
+ self.play(Transform(line1,line4))
+ self.wait(0.5)
+ self.play(Transform(line2,line5))
+ self.wait(0.5)
+ self.play(Transform(line3,line6))
+
+ self.wait(1.5)
+
+ line7 = Line(color = RED,opacity = 350,start = [-2,2,2],end = [1,3.5,3.5])
+ line8 = Line(color = BLUE,opacity = 350,start = [1,3.5,3.5],end = [0.5,2.5,2.5])
+ line9 = Line(color = GREEN,opacity = 350,start = ORIGIN,end = [0.5,2.5,2.5])
+
+ self.add_fixed_in_frame_mobjects(text3)
+ self.play(ShowCreation(text3))
+ self.wait(0.7)
+ self.play(FadeOut(line2),ShowCreation(line7))
+ self.play(FadeOut(line3),ShowCreation(line8))
+ self.wait(0.7)
+ self.play(ShowCreation(line9))
+ self.wait(1.2)
+
+
+ plane = Polygon([-4,4,4],[4,4,4],[4,-4,-4],[-4,-4,-4])
+ plane.set_opacity(0.4)
+ plane.set_fill(DARK_BLUE)
+ plane.set_color(DARK_BLUE)
+ self.play(ShowCreation(plane))
+ self.wait(1.2)
+ text4 = TextMobject("Linearly Combinations").scale(0.65).shift(3.5*UP+4*RIGHT)
+
+ text5 = TextMobject(r"\text{$\vec{z_1}$}",r"\text{=}",r"\text{2}",r"\text{$\vec{u}$}",r"\text{+}",r"\text{3}",r"\text{$\vec{v}$}",r"\text{+}",r"\text{(-1)}",r"\text{$\vec{w}$}",).scale(0.55).shift(2.5*UP+3.9*RIGHT)
+ text5[0].set_color(GREEN)
+ text5[3].set_color(YELLOW)
+ text5[6].set_color(RED)
+ text5[9].set_color(BLUE)
+ self.add_fixed_in_frame_mobjects(text5)
+ self.add_fixed_in_frame_mobjects(text4)
+ self.play(ShowCreation(text4),ShowCreation(text5))
+ self.wait(3.8)
+ bunch1 = VGroup(line7,line8,line9)
+ line10 = Line(color=YELLOW,opacity=350,start=ORIGIN,end=[-0.5,0.5,0.5])
+ line11 = Line(color=RED,opacity=350,start=ORIGIN,end=[2,1,1])
+ line12 = Line(color = BLUE,opacity = 350,start = ORIGIN,end = [-1.5,-3,-3])
+ line13 = Line(color = RED,opacity = 350,start = [-0.5,0.5,0.5],end = [1.5,1.5,1.5])
+ line14 = Line(color = BLUE,opacity = 350,start = [1.5,1.5,1.5],end = [0,-1.5,-1.5])
+ line15 = Line(color = GREEN,opacity = 350,start = ORIGIN,end = [0,-1.5,-1.5])
+ bunch2 = VGroup(line13,line14,line15,line10)
+ self.play(FadeOut(line1),Transform(bunch1,bunch2))
+ self.wait(1.2)
+ text6 = TextMobject(r"\text{$\vec{z_2}$}",r"\text{=}",r"\text{0.5}",r"\text{$\vec{u}$}",r"\text{+}",r"\text{2}",r"\text{$\vec{v}$}",r"\text{+}",r"\text{(-3)}",r"\text{$\vec{w}$}",).scale(0.55).shift(2*UP+4*RIGHT)
+ text6[0].set_color(GREEN)
+ text6[3].set_color(YELLOW)
+ text6[6].set_color(RED)
+ text6[9].set_color(BLUE)
+
+ self.add_fixed_in_frame_mobjects(text6)
+ self.play(ShowCreation(text6))
+ self.wait(2.8)
+ bunch3 = VGroup(line10,bunch1)
+
+ line16 = Line(color=YELLOW,opacity=350,start=ORIGIN,end=[-2,2,2])
+ line17 = Line(color=RED,opacity=350,start=ORIGIN,end=[1,0.5,0.5])
+
+ line18 = Line(color = RED,opacity = 350,start = [-2,2,2],end = [-1,2.5,2.5])
+
+ line19 = Line(color = GREEN,opacity = 350,start = ORIGIN,end = [-1,2.5,2.5])
+ bunch4 = VGroup(line16,line18,line19)
+ self.play(Transform(bunch3,bunch4))
+ self.wait(1.2)
+ text7 = TextMobject(r"\text{$\vec{z_3}$}",r"\text{=}",r"\text{(-2)}",r"\text{$\vec{u}$}",r"\text{+}",r"\text{2}",r"\text{$\vec{v}$}",r"\text{+}",r"\text{(0)}",r"\text{$\vec{w}$}",).scale(0.55).shift(1.5*UP+4*RIGHT)
+ text7[0].set_color(GREEN)
+ text7[3].set_color(YELLOW)
+ text7[6].set_color(RED)
+ text7[9].set_color(BLUE)
+ self.add_fixed_in_frame_mobjects(text7)
+ self.play(ShowCreation(text7))
+
+ self.wait(5)
+ self.play(FadeOut(text2),FadeOut(text3))
+ text8 = TextMobject(r"\text{$\vec{z}$}",r"\text{=}",r"\text{a}",r"\text{$\vec{u}$}",r"\text{+}",r"\text{b}",r"\text{$\vec{v}$}",r"\text{+}",r"\text{c}",r"\text{$\vec{w}$}",).scale(0.55).shift(0.8*UP+4*RIGHT)
+ text8[0].set_color(GREEN)
+ text8[3].set_color(YELLOW)
+ text8[6].set_color(RED)
+ text8[9].set_color(BLUE)
+ rect1 = Rectangle(height=0.7,stroke_width=1.2)
+ rect1.surround(text8)
+ self.add_fixed_in_frame_mobjects(rect1)
+ self.add_fixed_in_frame_mobjects(text8)
+ self.play(ShowCreation(text8))
+ text9 = TextMobject(r"\text{All the}",r"\text{linear combinations}",r"\text{of linearly dependent vectors}",r"\text{$\vec{u},$}",r"\text{$\vec{v},$}",r"\text{and}",r"\text{$\vec{w}$}",r"\text{spans}").scale(0.5).shift(2.5*DOWN)
+ text9[1].set_color(GREEN)
+ text9[3].set_color(YELLOW)
+ text9[4].set_color(RED)
+ text9[6].set_color(BLUE)
+ text9.add_background_rectangle()
+ text10 = TextMobject(r"this entire plane (and not the entire $\mathbb{R}^3 )$.").scale(0.5).shift(3*DOWN)
+ text10.add_background_rectangle()
+ self.wait(2)
+ self.add_fixed_in_frame_mobjects(text10)
+
+ self.add_fixed_in_frame_mobjects(text9)
+ self.play(ShowCreation(text9),ShowCreation(text10))
+ self.wait(7)
+
+class Linear_Independence(ThreeDScene):
+
+ def construct(self):
+
+ axes = ThreeDAxes()
+ axes.set_stroke(width=1,color=GOLD)
+ self.add(axes)
+ self.set_camera_orientation(phi = 70*DEGREES,theta =110*DEGREES)
+ self.begin_ambient_camera_rotation(rate=0.1)
+ self.wait(0.5)
+ text1 = TextMobject(r"Consider 3 linearly independent vectors in $\mathbb{R}^3$").scale(0.5).shift(2.5*UP+4*LEFT)
+ self.add_fixed_in_frame_mobjects(text1)
+ self.play(ShowCreation(text1))
+ line1 = Line(color = YELLOW,opacity=350,start = ORIGIN,end = [-1,1,1])
+ self.play(ShowCreation(line1))
+ self.wait(0.7)
+ line2 = Line(color = RED,opacity=350,start = ORIGIN,end = [1,0.5,0.5])
+ self.play(ShowCreation(line2))
+ self.wait(0.7)
+ line3 = Line(color = BLUE,opacity=350,start = ORIGIN,end = [0,-1,-2])
+ self.play(ShowCreation(line3))
+ self.wait(0.7)
+
+ self.wait(1)
+ self.play(FadeOut(text1))
+ text2 = TextMobject("Scaling the Vectors").scale(0.5).shift(2.5*UP+5*LEFT)
+ self.add_fixed_in_frame_mobjects(text2)
+ self.play(ShowCreation(text2))
+ self.wait(0.7)
+ line4 = Line(color = YELLOW,opacity=350,start = ORIGIN,end = [-0.5,0.5,0.5])
+ self.play(Transform(line1,line4))
+ self.wait(0.7)
+ line5 = Line(color = RED,opacity=350,start = ORIGIN,end = [2,1,1])
+ self.play(Transform(line2,line5))
+ self.wait(0.7)
+ line6 = Line(color = BLUE,opacity=350,start = ORIGIN,end = [0,-1.5,-3])
+ self.play(Transform(line3,line6))
+ self.wait(1.7)
+ text3 = TextMobject(r"\text{and}",r"\text{Adding}",r"\text{them}").scale(0.5).shift(2*UP+5*LEFT)
+ text3[1].set_color(GREEN)
+
+ line7 = Line(color = RED,opacity = 350,start = [-0.5,0.5,0.5],end = [1.5,1.5,1.5])
+ line8 = Line(color = BLUE,opacity = 350,start = [1.5,1.5,1.5],end = [1.5,0,-1.5])
+ line9 = Line(color = GREEN,opacity = 350,start = ORIGIN,end = [1.5,0,-1.5])
+ self.add_fixed_in_frame_mobjects(text3)
+ self.play(ShowCreation(text3))
+ self.wait(0.7)
+ self.play(FadeOut(line2),ShowCreation(line7))
+ self.play(FadeOut(line3),ShowCreation(line8))
+ self.wait(0.7)
+ self.play(ShowCreation(line9))
+ self.wait(1.5)
+ plane = Polygon([-4,4,4],[4,4,4],[4,-4,-4],[-4,-4,-4])
+ plane.set_opacity(0.3)
+ plane.set_fill(DARK_BLUE)
+ plane.set_color(DARK_BLUE)
+ self.play(ShowCreation(plane))
+ self.wait(1.2)
+ text4 = TextMobject("Linearly Combinations").scale(0.65).shift(3.5*UP+4*RIGHT)
+ self.add_fixed_in_frame_mobjects(text4)
+ self.play(ShowCreation(text4))
+ self.wait(0.7)
+ text5 = TextMobject(r"\text{$\vec{z_1}$}",r"\text{=}",r"\text{0.5}",r"\text{$\vec{u}$}",r"\text{+}",r"\text{2}",r"\text{$\vec{v}$}",r"\text{+}",r"\text{1.5}",r"\text{$\vec{w}$}").scale(0.55).shift(2.5*UP+3.8*RIGHT)
+ text5[0].set_color(GREEN)
+ text5[3].set_color(YELLOW)
+ text5[6].set_color(RED)
+ text5[9].set_color(BLUE)
+ self.add_fixed_in_frame_mobjects(text5)
+
+ self.play(ShowCreation(text5))
+ self.wait(3.8)
+ bunch1 = VGroup(line7,line8,line9)
+ line10 = Line(color=YELLOW,opacity=350,start=ORIGIN,end=[-3,3,3])
+
+ line11 = Line(color = BLUE,opacity = 350,start = [-3,3,3],end = [-2,3.5,3.5])
+
+
+ line12 = Line(color = GREEN,opacity = 350,start = ORIGIN,end = [-2,3.5,3.5])
+ bunch2 = VGroup(line10,line11,line12)
+ self.play(FadeOut(line1),Transform(bunch1,bunch2))
+ self.wait(1.2)
+
+ text6 = TextMobject(r"\text{$\vec{z_2}$}",r"\text{=}",r"\text{3}",r"\text{$\vec{u}$}",r"\text{+}",r"\text{1}",r"\text{$\vec{v}$}",r"\text{+}",r"\text{0}",r"\text{$\vec{w}$}").scale(0.55).shift(2*UP+3.6*RIGHT)
+ text6[0].set_color(GREEN)
+ text6[3].set_color(YELLOW)
+ text6[6].set_color(RED)
+ text6[9].set_color(BLUE)
+
+ self.add_fixed_in_frame_mobjects(text6)
+ self.play(ShowCreation(text6))
+ self.wait(2.8)
+ bunch3 = VGroup(line10,bunch1)
+
+ line13 = Line(color=YELLOW,opacity=350,start=ORIGIN,end=[2.5,-2.5,-2.5])
+ line14 = Line(color=RED,opacity=350,start=[2.5,-2.5,-2.5],end=[0.5,-3.5,-3.5])
+
+ line15 = Line(color = BLUE,opacity = 350,start = [0.5,-3.5,-3.5],end = [0.5,-0.5,2.5])
+
+ line16 = Line(color = GREEN,opacity = 350,start = ORIGIN,end = [0.5,-0.5,2.5])
+ bunch4 = VGroup(line13,line14,line15,line16)
+ self.play(Transform(bunch3,bunch4))
+ self.wait(1.2)
+ text7 = TextMobject(r"\text{$\vec{z_3}$}",r"\text{=}",r"\text{(-2.5)}",r"\text{$\vec{u}$}",r"\text{+}",r"\text{(-2)}",r"\text{$\vec{v}$}",r"\text{+}",r"\text{(-3)}",r"\text{$\vec{w}$}").scale(0.55).shift(1.5*UP+4.2*RIGHT)
+ text7[0].set_color(GREEN)
+ text7[3].set_color(YELLOW)
+ text7[6].set_color(RED)
+ text7[9].set_color(BLUE)
+ self.add_fixed_in_frame_mobjects(text7)
+ self.play(ShowCreation(text7))
+ self.play(FadeOut(text3),FadeOut(text2))
+ self.wait(1.2)
+ text8 = TextMobject(r"\text{$\vec{z}$}",r"\text{=}",r"\text{a}",r"\text{$\vec{u}$}",r"\text{+}",r"\text{b}",r"\text{$\vec{v}$}",r"\text{+}",r"\text{c}",r"\text{$\vec{w}$}").scale(0.55).shift(0.8*UP+3.6*RIGHT)
+ text8[0].set_color(GREEN)
+ text8[3].set_color(YELLOW)
+ text8[6].set_color(RED)
+ text8[9].set_color(BLUE)
+ rect1 = Rectangle(height=0.7,stroke_width=1.2)
+ rect1.surround(text8)
+ self.add_fixed_in_frame_mobjects(rect1)
+ self.add_fixed_in_frame_mobjects(text8)
+ self.play(ShowCreation(text8))
+ self.wait(1.7)
+ self.play(FadeOut(plane))
+ self.wait(1.5)
+ text9 = TextMobject(r"\text{All the}",r"\text{linear combinations}",r"\text{of linearly independent vectors}",r"\text{$\vec{u},$}",r"\text{$\vec{v},$}",r"\text{and}",r"\text{$\vec{w}$}",r"\text{spans}").scale(0.5).shift(2.5*DOWN)
+ text9[1].set_color(GREEN)
+ text9[3].set_color(YELLOW)
+ text9[4].set_color(RED)
+ text9[6].set_color(BLUE)
+ text9.add_background_rectangle()
+ text10 = TextMobject("not only the plane but the entire 3-D space.").scale(0.5).shift(3*DOWN)
+ text10.add_background_rectangle()
+ self.add_fixed_in_frame_mobjects(text9)
+
+ self.add_fixed_in_frame_mobjects(text10)
+ self.play(ShowCreation(text9),ShowCreation(text10))
+ self.wait(2.3)
+
+ self.play(FadeOut(text5),FadeOut(text6),FadeOut(text7))
+ self.wait(0.6)
+ text9 = TextMobject(r"\text{$\vec{z}$}",r"\text{=}",r"\text{a}",r"\text{$\vec{u}$}",r"\text{+}",r"\text{b}",r"\text{$\vec{v}$}",r"\text{+}",r"\text{c}",r"\text{$\vec{w}$}",r"\text{= 0}").scale(0.55).shift(2.6*UP+3.9*RIGHT)
+ text9[0].set_color(GREEN)
+ text9[3].set_color(YELLOW)
+ text9[6].set_color(RED)
+ text9[9].set_color(BLUE)
+ text10 = TextMobject("only when a = b = c = 0.").scale(0.55).shift(2.2*UP+3.9*RIGHT)
+ self.play(FadeOut(text8),FadeOut(rect1))
+ self.wait(0.7)
+ self.add_fixed_in_frame_mobjects(text9)
+ self.add_fixed_in_frame_mobjects(text10)
+
+ self.play(ShowCreation(text9),ShowCreation(text10))
+ self.wait(5)
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/3D_Vector_Space.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/3D_Vector_Space.py
new file mode 100644
index 0000000..70913eb
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/3D_Vector_Space.py
@@ -0,0 +1,14 @@
+from manimlib.imports import *
+class ThreeDSpace(ThreeDScene):
+ def construct(self):
+ curve = ParametricFunction(
+ lambda x: np.array([
+ 0, -x , x]), color = YELLOW, t_min = -2, t_max = 2)
+ axes = ThreeDAxes()
+ axes.set_stroke(width=1,color=GOLD)
+ self.add(axes)
+ self.set_camera_orientation(phi = 70*DEGREES,theta =60*DEGREES)
+ self.begin_ambient_camera_rotation(rate=0.3)
+ self.play(ShowCreation(curve))
+ self.wait(6)
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/Vector_Addition_and_Scalar_Multiplication.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/Vector_Addition_and_Scalar_Multiplication.py
new file mode 100644
index 0000000..12c9bce
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/Vector_Addition_and_Scalar_Multiplication.py
@@ -0,0 +1,177 @@
+from manimlib.imports import *
+VECTORS = [[1, 2],
+ [1, 1],
+ [2, 2],
+ [3, 4]]
+class Scene1(LinearTransformationScene):
+ CONFIG = {
+ "include_background_plane": True,
+ "include_foreground_plane": False,
+ "show_coordinates": True,
+ "show_basis_vectors": False,
+ "basis_vector_stroke_width": 3,
+ }
+ def construct(self):
+ self.write_stuff()
+ v1 = self.add_vector(VECTORS[0],color = YELLOW, stroke_width = 3.5)
+ line1 = Line(start = ORIGIN, end = VECTORS[0][0]*RIGHT)
+ line1.set_color(RED_B)
+ line2 = Line(start = line1.get_end(), end = line1.get_end() + VECTORS[0][1]*UP)
+ line2.set_color(GREEN_D)
+ self.play(ShowCreation(line1))
+ self.play(ShowCreation(line2))
+ self.wait(0.5)
+ text1 = TextMobject("(1, 2)",color=YELLOW).scale(0.6).shift(2*UP + 1.5*RIGHT)
+ self.play(ShowCreation(text1))
+ text2 = TextMobject(r"$\vec{a}$",color = YELLOW).scale(0.8).shift(2*UP + 1.2*RIGHT)
+ text3 = TextMobject(r"\text{$\vec{a}$}",r"\text{=}",r"\text{(1, 2)}").scale(0.7).shift(5.1*LEFT + 2.5*UP)
+ text3[0].set_color(YELLOW)
+ text3[2].set_color(YELLOW)
+ self.wait(1)
+ self.play(Transform(text1,text2),FadeOut(line1),FadeOut(line2))
+ self.wait(0.5)
+ self.play(ShowCreation(text3))
+ self.wait(1)
+
+
+ v2 = self.add_vector(VECTORS[1],color = BLUE, stroke_width = 3.5)
+ line3 = Line(start = ORIGIN, end = VECTORS[1][0]*RIGHT)
+ line3.set_color(RED_B)
+ line4 = Line(start = line3.get_end(), end = line3.get_end() + VECTORS[1][1]*UP)
+ line4.set_color(GREEN_D)
+ self.play(ShowCreation(line3))
+ self.play(ShowCreation(line4))
+ self.wait(0.5)
+ text4 = TextMobject("(2, 2)",color=BLUE).scale(0.6).shift(1*UP + 1.5*RIGHT)
+ self.play(ShowCreation(text4))
+ text5 = TextMobject(r"$\vec{b}$",color = BLUE).scale(0.8).shift(1*UP + 1.2*RIGHT)
+ text6 = TextMobject(r"\text{$\vec{b}$}",r"\text{=}",r"\text{(1, 1)}").scale(0.7).shift(5.1*LEFT + 1.8*UP)
+ text6[0].set_color(BLUE)
+ text6[2].set_color(BLUE)
+ self.wait(1)
+ self.play(Transform(text4,text5),FadeOut(line3),FadeOut(line4))
+ self.wait(0.5)
+ self.play(ShowCreation(text6))
+ self.wait(2)
+
+
+
+ text7 = TextMobject(r"\text{Scaling}",r"\text{ $\vec{b}$ }",r"\text{by 2 units}",color = GOLD).scale(0.7).shift(2.8*UP+4*RIGHT)
+ text7[1].set_color(BLUE)
+ self.play(ShowCreation(text7))
+ self.play(FadeOut(text4))
+ v3 = self.add_vector(VECTORS[2],color = BLUE, stroke_width = 3.5)
+ line7 = Line(start = ORIGIN, end = VECTORS[2][0]*RIGHT)
+ line7.set_color(RED_B)
+ line8 = Line(start = line7.get_end(), end = line7.get_end() + VECTORS[2][1]*UP)
+ line8.set_color(GREEN_D)
+ self.play(FadeOut(v2))
+ self.play(ShowCreation(line7))
+ self.play(ShowCreation(line8))
+
+
+ self.wait(0.5)
+
+ text8 = TextMobject("(2, 2)",color=BLUE).scale(0.6).shift(2.5*RIGHT + 2*UP)
+ text9 = TextMobject(r"$2\vec{b}$",color = BLUE).scale(0.8).shift(2*UP + 2.3*RIGHT)
+ self.play(ShowCreation(text8))
+ self.wait(1)
+ self.play(Transform(text8,text9),FadeOut(line7),FadeOut(line8))
+ self.wait(1)
+ text10 = TextMobject(r"\text{$2\vec{b}$}",r"\text{=}",r"\text{(2, 2)}").scale(0.7).shift(5.1*LEFT + 1.8*UP)
+ text10[0].set_color(BLUE)
+ text10[2].set_color(BLUE)
+ self.play(Transform(text6,text10))
+ self.wait(1)
+ self.play(FadeOut(text7))
+ self.wait(1.5)
+
+
+
+ text11 = TextMobject(r"Addition of vectors",color = GOLD).scale(0.7).shift(2.8*UP+5*RIGHT)
+ self.play(ShowCreation(text11))
+ v1.move_to(3*UP+2.5*RIGHT)
+ self.play(ShowCreation(v1),FadeOut(text8),FadeOut(text1))
+ v4 = self.add_vector(VECTORS[3],color = ORANGE, stroke_width = 3.5)
+ line7 = Line(start = ORIGIN, end = VECTORS[3][0]*RIGHT)
+ line7.set_color(RED_B)
+ line8 = Line(start = line7.get_end(), end = line7.get_end() + VECTORS[3][1]*UP)
+ line8.set_color(GREEN_D)
+ self.play(ShowCreation(line7))
+ self.play(ShowCreation(line8))
+ text12 = TextMobject("(3, 4)",color=ORANGE).scale(0.6).shift(3.5*RIGHT + 3.8*UP)
+ text13 = TextMobject(r"$\vec{c}$",color = ORANGE).scale(0.8).shift(3.7*UP + 3.3*RIGHT)
+ self.play(ShowCreation(text12))
+ self.wait(1)
+ self.play(Transform(text12,text13),FadeOut(line7),FadeOut(line8))
+ self.wait(1)
+ add = TextMobject("+").scale(0.8).shift(6.2*LEFT + 1.8*UP)
+ line_1= Line().shift(1.5*UP+5.1*LEFT).scale(1.5)
+ line_2= Line().shift(0.8*UP+5.1*LEFT).scale(1.5)
+
+ text14=TextMobject(r"\text{$\vec{c}$}",r"\text{=}",r"\text{$\vec{a}$}",r"\text{+}",r"\text{$2\vec{b}$}",r"\text{=}",r"\text{(3, 4)}").scale(0.7).shift(1.2*UP+5.1*LEFT)
+ text14[0].set_color(ORANGE)
+ text14[2].set_color(YELLOW)
+ text14[4].set_color(BLUE)
+ text14[6].set_color(ORANGE)
+
+
+ self.play(ShowCreation(add),ShowCreation(line_1))
+ self.play(ShowCreation(text14),ShowCreation(line_2))
+ self.wait(3)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def write_stuff(self):
+ self.text = []
+ text = self.text
+
+ text.append(TexMobject(r"\text{Consider the Vector Space }",
+ r"{\mathbb{R}^2}"))
+ self.add_title(text[0], 0.7, animate = True)
+ text.append(TexMobject(r"{\mathbb{R}^2}",
+ tex_to_color_map = {r"{\mathbb{R}^2}": BLUE_E}))
+ text[1].shift(6.5*LEFT+3.5*UP)
+ self.wait(0.5)
+ self.play(Transform(text[0], text[1]))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/Vector_Space_As_Functions.py b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/Vector_Space_As_Functions.py
new file mode 100644
index 0000000..4f5614d
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/Vector_Space_As_Functions.py
@@ -0,0 +1,62 @@
+from manimlib.imports import *
+from scipy import sin,cos
+class FunctionalVectorSpace(GraphScene):
+ CONFIG = {
+ "x_min": -5,
+ "x_max": 5,
+ "y_min": -5,
+ "y_max": 5,
+ "graph_origin": ORIGIN,
+ }
+ def construct(self):
+ self.setup_axes(animate = True)
+ curve1 = self.get_graph(lambda x : sin(x), x_min=-5,x_max=5,color=YELLOW_E)
+ curve2 = self.get_graph(lambda x : cos(x), x_min=-5,x_max=5,color=RED)
+ self.play(ShowCreation(curve1))
+ fx=TextMobject(r"$f(x)$",color=YELLOW_E).scale(0.7)
+ fx.shift(5*LEFT+0.7*UP)
+ self.play(ShowCreation(fx))
+ self.play(ShowCreation(curve2))
+ gx=TextMobject(r"$g(x)$",color=RED).scale(0.7)
+ gx.shift(5*LEFT+0.2*UP)
+ self.play(ShowCreation(gx))
+ self.wait(2)
+ scaling=TextMobject("Scaling f(x) by 2 units",color=GOLD).scale(0.65)
+ scaling.shift(3*LEFT+2.4*UP)
+ curve3 = self.get_graph(lambda x : 2*sin(x), x_min=-5,x_max=5,color=BLUE)
+ fx2=TextMobject(r"$2f(x)$",color=BLUE).scale(0.7)
+ fx2.shift(5*LEFT+1*UP)
+ self.play(Transform(curve1,curve3),FadeOut(fx),ShowCreation(fx2),ShowCreation(scaling))
+ self.wait(3)
+ hx = TextMobject(r"$h(x)$",color=PURPLE).scale(0.7)
+ hx.shift(4.9*LEFT+1.5*UP)
+ curve4 = self.get_graph(lambda x : 2*sin(x) + cos(x), x_min=-5,x_max=5,color=PURPLE)
+ self.play(ShowCreation(curve4),ShowCreation(hx))
+ self.play(FadeOut(curve2),FadeOut(curve1),FadeOut(fx2),FadeOut(gx),FadeOut(scaling))
+ hxn=TextMobject(r"$h(x)$",color=PURPLE).scale(0.7)
+ hxn.shift(3*RIGHT+2.4*UP)
+ equal = TextMobject("=").scale(0.7)
+ equal.shift(3.5*RIGHT+2.4*UP)
+ fx2n=TextMobject(r"$2f(x)$",color=BLUE).scale(0.7)
+ fx2n.shift(4.2*RIGHT+2.4*UP)
+ add=TextMobject("+").scale(0.7)
+ add.shift(4.8*RIGHT+2.4*UP)
+ gxn=TextMobject(r"$g(x)$",color=RED).scale(0.7)
+ gxn.shift(5.3*RIGHT+2.4*UP)
+ vector_add=TextMobject("Vector Addition",color=GOLD).scale(0.65)
+ vector_add.shift(3*UP+3*RIGHT)
+ self.play(ShowCreation(hxn),ShowCreation(equal),ShowCreation(fx2n),ShowCreation(add),ShowCreation(gxn),ShowCreation(vector_add))
+ self.wait(2)
+
+
+
+
+
+
+
+
+
+
+
+
+ \ No newline at end of file
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/3D_Vector_Space.gif b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/3D_Vector_Space.gif
new file mode 100644
index 0000000..137546a
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/3D_Vector_Space.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/Function_Vector_Space_Example.gif b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/Function_Vector_Space_Example.gif
new file mode 100644
index 0000000..d9edf46
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/Function_Vector_Space_Example.gif
Binary files differ
diff --git a/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/Vector_Addition_and_Scalar_Multiplication.mp4 b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/Vector_Addition_and_Scalar_Multiplication.mp4
new file mode 100644
index 0000000..8acbb81
--- /dev/null
+++ b/FSF-2020/linear-algebra/vector-spaces/Vector-Spaces/Vector-Spaces/gifs/Vector_Addition_and_Scalar_Multiplication.mp4
Binary files differ