{ "cells": [ { "cell_type": "markdown", "id": "00e7e6ec", "metadata": {}, "source": [ "# The Method of Euler" ] }, { "cell_type": "markdown", "id": "7a82a697", "metadata": {}, "source": [ "Euler's method is illustrated on the test equation:\n", "\n", "$$\n", " \\frac{d y}{d x} = y, \\quad y(0) = 1.\n", "$$\n", "\n", "The exact solution to the test equation is $y(x) = \\exp(x)$." ] }, { "cell_type": "code", "execution_count": 1, "id": "3b32e7f5", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\n", "(process:61556): GLib-GIO-WARNING **: 14:50:21.192: Unexpectedly, UWP app `Clipchamp.Clipchamp_2.5.1.0_neutral__yxz26nhyzhsrt' (AUMId `Clipchamp.Clipchamp_yxz26nhyzhsrt!App') supports 41 extensions but has no verbs\n", "\n", "(process:61556): GLib-GIO-WARNING **: 14:50:21.239: Unexpectedly, UWP app `Evernote.Evernote_10.47.7.0_x64__q4d96b2w5wcc2' (AUMId `Evernote.Evernote_q4d96b2w5wcc2!Evernote') supports 1 extensions but has no verbs\n" ] } ], "source": [ "using Plots" ] }, { "cell_type": "code", "execution_count": 2, "id": "06b096f3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9, 1.0]\n", "[1.0, 1.1, 1.2100000000000002, 1.3310000000000004, 1.4641000000000004, 1.6105100000000006, 1.7715610000000008, 1.9487171000000012, 2.1435888100000016, 2.357947691000002, 2.5937424601000023]\n" ] } ], "source": [ "h = 0.1\n", "r = 0:1:10\n", "x = [i*h for i in r]\n", "y = [(1.0+h)^i for i in r]\n", "println(x)\n", "println(y)" ] }, { "cell_type": "code", "execution_count": 3, "id": "9bd3e28b", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "xr = 0.0:0.01:1.0\n", "ye = [exp(x) for x in xr]\n", "plot(xr,ye,label=\"exp(x)\",legend=:topleft)\n", "scatter!(x,y,label=\"Euler\")" ] }, { "cell_type": "code", "execution_count": 4, "id": "7cda4f8c", "metadata": {}, "outputs": [], "source": [ "# savefig(\"figeulerexp.png\")" ] }, { "cell_type": "markdown", "id": "8eca59be", "metadata": {}, "source": [ "## Accuracy of Euler's Method" ] }, { "cell_type": "markdown", "id": "b176b4cc", "metadata": {}, "source": [ "How many function evaluations are needed to obtain a desired accuracy?" ] }, { "cell_type": "code", "execution_count": 5, "id": "c7a99342", "metadata": {}, "outputs": [], "source": [ "using Printf" ] }, { "cell_type": "code", "execution_count": 6, "id": "0ea83fc1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "eulerexp" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\"\"\"\n", " eulerexp(n::Int64,verbose::Bool=true)\n", "\n", "Euler's method with n evaluations\n", "on the interval [0,1] on the test\n", "equation y' = y, y(0) = 1.\n", "\"\"\"\n", "function eulerexp(n::Int64,verbose::Bool=true)\n", " h = 1.0/n\n", " if verbose\n", " println(\" i x approx exact error\")\n", " end\n", " y = 0.0\n", " for i=0:n\n", " x = i*h\n", " y = (1.0+h)^i\n", " exact = exp(x)\n", " if verbose\n", " stri = @sprintf(\"%3d\", i)\n", " strx = @sprintf(\"%.2f\", x)\n", " stry = @sprintf(\"%.6e\", y)\n", " strexp = @sprintf(\"%.6e\", exact)\n", " strerr = @sprintf(\"%.2e\", abs(y-exact))\n", " println(\"$stri $strx $stry $strexp $strerr\")\n", " end\n", " end\n", " return y\n", "end" ] }, { "cell_type": "markdown", "id": "aeeca97e", "metadata": {}, "source": [ "Let us check the function ``eulerexp`` for a step size of 0.1, with 10 function evaluations." ] }, { "cell_type": "code", "execution_count": 7, "id": "1e214482", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " i x approx exact error\n", " 0 0.00 1.000000e+00 1.000000e+00 0.00e+00\n", " 1 0.10 1.100000e+00 1.105171e+00 5.17e-03\n", " 2 0.20 1.210000e+00 1.221403e+00 1.14e-02\n", " 3 0.30 1.331000e+00 1.349859e+00 1.89e-02\n", " 4 0.40 1.464100e+00 1.491825e+00 2.77e-02\n", " 5 0.50 1.610510e+00 1.648721e+00 3.82e-02\n", " 6 0.60 1.771561e+00 1.822119e+00 5.06e-02\n", " 7 0.70 1.948717e+00 2.013753e+00 6.50e-02\n", " 8 0.80 2.143589e+00 2.225541e+00 8.20e-02\n", " 9 0.90 2.357948e+00 2.459603e+00 1.02e-01\n", " 10 1.00 2.593742e+00 2.718282e+00 1.25e-01\n" ] }, { "data": { "text/plain": [ "2.5937424601000023" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eulerexp(10)" ] }, { "cell_type": "markdown", "id": "258618d4", "metadata": {}, "source": [ "Now we will run ``eulerexp`` for increasing values of $n$, for $n = 10^i$, for $i$ from 1 to 6. After each run, we compare with the exact value at the end. This comparison gives *the global error*. Running ``eulerexp`` with the verbose mode on shows *the local error* of each step. The verbose is set to ``false`` in the run below, as we are mainly interested in the global error." ] }, { "cell_type": "code", "execution_count": 8, "id": "3926db6a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 10 2.593742e+00 1.25e-01\n", " 100 2.704814e+00 1.35e-02\n", " 1000 2.716924e+00 1.36e-03\n", " 10000 2.718146e+00 1.36e-04\n", " 100000 2.718268e+00 1.36e-05\n", " 1000000 2.718280e+00 1.36e-06\n" ] } ], "source": [ "exact = exp(1.0)\n", "for i=1:6\n", " y = eulerexp(10^i, false)\n", " stri = @sprintf(\"%8d\", 10^i)\n", " stry = @sprintf(\"%.6e\", y)\n", " strerr = @sprintf(\"%.2e\", abs(y-exact))\n", " println(\"$stri $stry $strerr\")\n", "end" ] }, { "cell_type": "markdown", "id": "6a38921b", "metadata": {}, "source": [ "We see that we need one million steps for six decimal places of accuracy." ] }, { "cell_type": "markdown", "id": "ca7a47f9", "metadata": {}, "source": [ "## Accuracy of the Modified Euler Method" ] }, { "cell_type": "markdown", "id": "7c435b4d", "metadata": {}, "source": [ "The modified Euler method improves on the Euler method with the application of the trapezoidal rule." ] }, { "cell_type": "code", "execution_count": 9, "id": "a941525f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "modeulerexp" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\n", "\"\"\"\n", " modeulerexp(n::Int64,verbose::Bool=true)\n", "\n", "The Modified Euler's method with\n", "n evaluations on the interval [0,1] on\n", "the test equation y' = y, y(0) = 1.\n", "\"\"\"\n", "function modeulerexp(n::Int64,verbose::Bool=true)\n", " h = 1.0/n\n", " if verbose\n", " println(\" i x predict correct exact error\")\n", " end\n", " y0 = 1.0\n", " y1 = 1.0\n", " for i=1:n\n", " x = i*h\n", " y = (1.0+h)*y0\n", " y1 = y0 + h*(y0 + y)/2.0\n", " exact = exp(x)\n", " if verbose\n", " stri = @sprintf(\"%3d\", i)\n", " strx = @sprintf(\"%.2f\", x)\n", " stry = @sprintf(\"%.6e\", y)\n", " stry1 = @sprintf(\"%.6e\", y1)\n", " strexp = @sprintf(\"%.6e\", exact)\n", " strerr = @sprintf(\"%.2e\", abs(y1-exact))\n", " println(\"$stri $strx $stry $stry1 $strexp $strerr\")\n", " end\n", " y0 = y1\n", " end\n", " return y1\n", "end" ] }, { "cell_type": "markdown", "id": "863e9107", "metadata": {}, "source": [ "First a sanity check, we do a run with 10 steps." ] }, { "cell_type": "code", "execution_count": 10, "id": "f10f527c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " i x predict correct exact error\n", " 1 0.10 1.100000e+00 1.105000e+00 1.105171e+00 1.71e-04\n", " 2 0.20 1.215500e+00 1.221025e+00 1.221403e+00 3.78e-04\n", " 3 0.30 1.343128e+00 1.349233e+00 1.349859e+00 6.26e-04\n", " 4 0.40 1.484156e+00 1.490902e+00 1.491825e+00 9.23e-04\n", " 5 0.50 1.639992e+00 1.647447e+00 1.648721e+00 1.27e-03\n", " 6 0.60 1.812191e+00 1.820429e+00 1.822119e+00 1.69e-03\n", " 7 0.70 2.002472e+00 2.011574e+00 2.013753e+00 2.18e-03\n", " 8 0.80 2.212731e+00 2.222789e+00 2.225541e+00 2.75e-03\n", " 9 0.90 2.445068e+00 2.456182e+00 2.459603e+00 3.42e-03\n", " 10 1.00 2.701800e+00 2.714081e+00 2.718282e+00 4.20e-03\n" ] }, { "data": { "text/plain": [ "2.714080846608224" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "modeulerexp(10)" ] }, { "cell_type": "markdown", "id": "902ee5ab", "metadata": {}, "source": [ "Comparing the output of ``modeulerexp(10)`` to the output of ``eulerexp(10)`` we see that the local error (the error in the first step) is much smaller. Also the global error (the error in the last step) is much smaller." ] }, { "cell_type": "code", "execution_count": 11, "id": "34731aa1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 10 2.7140808466082e+00 4.20e-03\n", " 100 2.7182368625600e+00 4.50e-05\n", " 1000 2.7182813757518e+00 4.53e-07\n", " 10000 2.7182818239289e+00 4.53e-09\n", " 100000 2.7182818284137e+00 4.53e-11\n", " 1000000 2.7182818284586e+00 4.08e-13\n" ] } ], "source": [ "exact = exp(1.0)\n", "for i=1:6\n", " y = modeulerexp(10^i, false)\n", " stri = @sprintf(\"%8d\", 10^i)\n", " stry = @sprintf(\"%.13e\", y)\n", " strerr = @sprintf(\"%.2e\", abs(y-exact))\n", " println(\"$stri $stry $strerr\")\n", "end" ] }, { "cell_type": "markdown", "id": "23ab3e8e", "metadata": {}, "source": [ "With one million steps, we obtain an accuracy of 13 decimal places. On the test equation, the modified Euler method is twice as accurate as Euler's method." ] } ], "metadata": { "kernelspec": { "display_name": "Julia 1.8.0", "language": "julia", "name": "julia-1.8" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.8.0" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false } }, "nbformat": 4, "nbformat_minor": 5 }