{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["# Exercise 9.2: Numerically solving differential equations\n", "\n", "
"]}, {"cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [{"data": {"text/html": ["\n", "
\n", " \n", " Loading BokehJS ...\n", "
"]}, "metadata": {}, "output_type": "display_data"}, {"data": {"application/javascript": ["\n", "(function(root) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " var force = true;\n", "\n", " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n", " root._bokeh_onload_callbacks = [];\n", " root._bokeh_is_loading = undefined;\n", " }\n", "\n", " var JS_MIME_TYPE = 'application/javascript';\n", " var HTML_MIME_TYPE = 'text/html';\n", " var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n", " var CLASS_NAME = 'output_bokeh rendered_html';\n", "\n", " /**\n", " * Render data to the DOM node\n", " */\n", " function render(props, node) {\n", " var script = document.createElement(\"script\");\n", " node.appendChild(script);\n", " }\n", "\n", " /**\n", " * Handle when an output is cleared or removed\n", " */\n", " function handleClearOutput(event, handle) {\n", " var cell = handle.cell;\n", "\n", " var id = cell.output_area._bokeh_element_id;\n", " var server_id = cell.output_area._bokeh_server_id;\n", " // Clean up Bokeh references\n", " if (id != null && id in Bokeh.index) {\n", " Bokeh.index[id].model.document.clear();\n", " delete Bokeh.index[id];\n", " }\n", "\n", " if (server_id !== undefined) {\n", " // Clean up Bokeh references\n", " var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n", " cell.notebook.kernel.execute(cmd, {\n", " iopub: {\n", " output: function(msg) {\n", " var id = msg.content.text.trim();\n", " if (id in Bokeh.index) {\n", " Bokeh.index[id].model.document.clear();\n", " delete Bokeh.index[id];\n", " }\n", " }\n", " }\n", " });\n", " // Destroy server and session\n", " var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n", " cell.notebook.kernel.execute(cmd);\n", " }\n", " }\n", "\n", " /**\n", " * Handle when a new output is added\n", " */\n", " function handleAddOutput(event, handle) {\n", " var output_area = handle.output_area;\n", " var output = handle.output;\n", "\n", " // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n", " if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", " return\n", " }\n", "\n", " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", "\n", " if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n", " toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n", " // store reference to embed id on output_area\n", " output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", " }\n", " if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", " var bk_div = document.createElement(\"div\");\n", " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", " var script_attrs = bk_div.children[0].attributes;\n", " for (var i = 0; i < script_attrs.length; i++) {\n", " toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n", " }\n", " // store reference to server id on output_area\n", " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", " }\n", " }\n", "\n", " function register_renderer(events, OutputArea) {\n", "\n", " function append_mime(data, metadata, element) {\n", " // create a DOM node to render to\n", " var toinsert = this.create_output_subarea(\n", " metadata,\n", " CLASS_NAME,\n", " EXEC_MIME_TYPE\n", " );\n", " this.keyboard_manager.register_events(toinsert);\n", " // Render to node\n", " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", " render(props, toinsert[toinsert.length - 1]);\n", " element.append(toinsert);\n", " return toinsert\n", " }\n", "\n", " /* Handle when an output is cleared or removed */\n", " events.on('clear_output.CodeCell', handleClearOutput);\n", " events.on('delete.Cell', handleClearOutput);\n", "\n", " /* Handle when a new output is added */\n", " events.on('output_added.OutputArea', handleAddOutput);\n", "\n", " /**\n", " * Register the mime type and append_mime function with output_area\n", " */\n", " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", " /* Is output safe? */\n", " safe: true,\n", " /* Index of renderer in `output_area.display_order` */\n", " index: 0\n", " });\n", " }\n", "\n", " // register the mime type if in Jupyter Notebook environment and previously unregistered\n", " if (root.Jupyter !== undefined) {\n", " var events = require('base/js/events');\n", " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", "\n", " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", " register_renderer(events, OutputArea);\n", " }\n", " }\n", "\n", " \n", " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_failed_load = false;\n", " }\n", "\n", " var NB_LOAD_WARNING = {'data': {'text/html':\n", " \"
\\n\"+\n", " \"

\\n\"+\n", " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", " \"

\\n\"+\n", " \"\\n\"+\n", " \"\\n\"+\n", " \"from bokeh.resources import INLINE\\n\"+\n", " \"output_notebook(resources=INLINE)\\n\"+\n", " \"\\n\"+\n", " \"
\"}};\n", "\n", " function display_loaded() {\n", " var el = document.getElementById(\"1001\");\n", " if (el != null) {\n", " el.textContent = \"BokehJS is loading...\";\n", " }\n", " if (root.Bokeh !== undefined) {\n", " if (el != null) {\n", " el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n", " }\n", " } else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(display_loaded, 100)\n", " }\n", " }\n", "\n", "\n", " function run_callbacks() {\n", " try {\n", " root._bokeh_onload_callbacks.forEach(function(callback) {\n", " if (callback != null)\n", " callback();\n", " });\n", " } finally {\n", " delete root._bokeh_onload_callbacks\n", " }\n", " console.debug(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(css_urls, js_urls, callback) {\n", " if (css_urls == null) css_urls = [];\n", " if (js_urls == null) js_urls = [];\n", "\n", " root._bokeh_onload_callbacks.push(callback);\n", " if (root._bokeh_is_loading > 0) {\n", " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " }\n", " if (js_urls == null || js_urls.length === 0) {\n", " run_callbacks();\n", " return null;\n", " }\n", " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " root._bokeh_is_loading = css_urls.length + js_urls.length;\n", "\n", " function on_load() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", " run_callbacks()\n", " }\n", " }\n", "\n", " function on_error() {\n", " console.error(\"failed to load \" + url);\n", " }\n", "\n", " for (var i = 0; i < css_urls.length; i++) {\n", " var url = css_urls[i];\n", " const element = document.createElement(\"link\");\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.rel = \"stylesheet\";\n", " element.type = \"text/css\";\n", " element.href = url;\n", " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", " document.body.appendChild(element);\n", " }\n", "\n", " const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js\": \"kLr4fYcqcSpbuI95brIH3vnnYCquzzSxHPU6XGQCIkQRGJwhg0StNbj1eegrHs12\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.1.1.min.js\": \"xIGPmVtaOm+z0BqfSOMn4lOR6ciex448GIKG4eE61LsAvmGj48XcMQZtKcE/UXZe\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.1.1.min.js\": \"Dc9u1wF/0zApGIWoBbH77iWEHtdmkuYWG839Uzmv8y8yBLXebjO9ZnERsde5Ln/P\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.1.1.min.js\": \"cT9JaBz7GiRXdENrJLZNSC6eMNF3nh3fa5fTF51Svp+ukxPdwcU5kGXGPBgDCa2j\"};\n", "\n", " for (var i = 0; i < js_urls.length; i++) {\n", " var url = js_urls[i];\n", " var element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " if (url in hashes) {\n", " element.crossOrigin = \"anonymous\";\n", " element.integrity = \"sha384-\" + hashes[url];\n", " }\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " };\n", "\n", " function inject_raw_css(css) {\n", " const element = document.createElement(\"style\");\n", " element.appendChild(document.createTextNode(css));\n", " document.body.appendChild(element);\n", " }\n", "\n", " \n", " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.1.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.1.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.1.1.min.js\"];\n", " var css_urls = [];\n", " \n", "\n", " var inline_js = [\n", " function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", " function(Bokeh) {\n", " \n", " \n", " }\n", " ];\n", "\n", " function run_inline_js() {\n", " \n", " if (root.Bokeh !== undefined || force === true) {\n", " \n", " for (var i = 0; i < inline_js.length; i++) {\n", " inline_js[i].call(root, root.Bokeh);\n", " }\n", " if (force === true) {\n", " display_loaded();\n", " }} else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!root._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " root._bokeh_failed_load = true;\n", " } else if (force !== true) {\n", " var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n", " cell.output_area.append_execute_result(NB_LOAD_WARNING)\n", " }\n", "\n", " }\n", "\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", " run_inline_js();\n", " } else {\n", " load_libs(css_urls, js_urls, function() {\n", " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", "}(window));"], "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n \n\n \n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n var NB_LOAD_WARNING = {'data': {'text/html':\n \"
\\n\"+\n \"

\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"

\\n\"+\n \"\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"\\n\"+\n \"
\"}};\n\n function display_loaded() {\n var el = document.getElementById(\"1001\");\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\n\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js\": \"kLr4fYcqcSpbuI95brIH3vnnYCquzzSxHPU6XGQCIkQRGJwhg0StNbj1eegrHs12\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.1.1.min.js\": \"xIGPmVtaOm+z0BqfSOMn4lOR6ciex448GIKG4eE61LsAvmGj48XcMQZtKcE/UXZe\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.1.1.min.js\": \"Dc9u1wF/0zApGIWoBbH77iWEHtdmkuYWG839Uzmv8y8yBLXebjO9ZnERsde5Ln/P\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.1.1.min.js\": \"cT9JaBz7GiRXdENrJLZNSC6eMNF3nh3fa5fTF51Svp+ukxPdwcU5kGXGPBgDCa2j\"};\n\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n if (url in hashes) {\n element.crossOrigin = \"anonymous\";\n element.integrity = \"sha384-\" + hashes[url];\n }\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n \n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.1.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.1.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.1.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.1.1.min.js\"];\n var css_urls = [];\n \n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {\n \n \n }\n ];\n\n function run_inline_js() {\n \n if (root.Bokeh !== undefined || force === true) {\n \n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\n if (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));"}, "metadata": {}, "output_type": "display_data"}], "source": ["import numpy as np\n", "\n", "import bokeh.io\n", "import bokeh.plotting\n", "\n", "bokeh.io.output_notebook()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["For this exercise, we will use Euler's method to simulate a classic set of differential equations that can exhibit chaotic solutions known as the Lorenz attractor. As a warm-up example, we will simulate bacterial growth.\n", "\n", "Bacterial growth can be modeled by the differential equation\n", "\n", "\\begin{align}\n", "\\frac{\\mathrm{d}n}{\\mathrm{d}t} = k n,\n", "\\end{align}\n", "\n", "where $n$ is the number of bacteria and $k$ is the growth rate. The idea here is that the number of bacteria will grow faster the more bacteria we have, because there are more to divide. Analytically, we know the solution to this differential equation is\n", "\n", "\\begin{align}\n", "n(t) = n_0 \\mathrm{e}^{kt},\n", "\\end{align}\n", "\n", "i.e., exponential growth. But suppose we did not know how to derive that. We could *simulate* the differential equation. We do this by discretizing time. Instead of a derivative, we have a change in $n$ over a change in time $t$.\n", "\n", "\\begin{align}\n", "\\frac{\\mathrm{d}n}{\\mathrm{d}t} \\approx \\frac{\\Delta n}{\\Delta t} = k n.\n", "\\end{align}\n", "\n", "Let's say we know $n$ and time zero, $n(0)$. Then $n$ at time $t = \\Delta t$ is\n", "\n", "\\begin{align}\n", "n(\\Delta t) \\approx n(0) + \\Delta n = n(0) + \\Delta t\\, k n(0).\n", "\\end{align}\n", "\n", "More generally, we can write\n", "\n", "\\begin{align}\n", "\\frac{\\mathrm{d}n}{\\mathrm{d}t} = f(n),\n", "\\end{align}\n", "\n", "and\n", "\n", "\\begin{align}\n", "n(t+\\Delta t) \\approx n(t) + \\Delta t\\,f(n).\n", "\\end{align}\n", "\n", "So, we can instruct Python to take our current value of $n$, and then add $\\Delta t$ times $f(n)$ to get our new $n$ at a time just a bit later on, at $t + \\Delta t$. We repeat this over and over again to move forward in time. Let's code that up!"]}, {"cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": ["# Specify parameter\n", "k = 1\n", "\n", "# Specify my little time step\n", "delta_t = 0.01\n", "\n", "# Make an array of time points, evenly spaced up to 10\n", "t = np.arange(0, 10, delta_t)\n", "\n", "# Make an array to store the number of bacteria\n", "n = np.empty_like(t)\n", "\n", "# Set the initial number of bacteria\n", "n[0] = 100\n", "\n", "# Write a for loop to keep updating n as time goes on\n", "for i in range(1, len(t)):\n", " n[i] = n[i - 1] + delta_t * k * n[i - 1]"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Ok! We just computed the time points and the number of bacteria, so we can just plot the result!"]}, {"cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [{"data": {"text/html": ["\n", "\n", "\n", "\n", "\n", "\n", "
\n"]}, "metadata": {}, "output_type": "display_data"}, {"data": {"application/javascript": ["(function(root) {\n", " function embed_document(root) {\n", " \n", " var docs_json = {\"5f308faf-4fcf-4cf7-9a31-e9f949bb1859\":{\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1011\"}],\"center\":[{\"id\":\"1014\"},{\"id\":\"1018\"}],\"left\":[{\"id\":\"1015\"}],\"plot_height\":300,\"plot_width\":450,\"renderers\":[{\"id\":\"1036\"}],\"title\":{\"id\":\"1038\"},\"toolbar\":{\"id\":\"1026\"},\"x_range\":{\"id\":\"1003\"},\"x_scale\":{\"id\":\"1007\"},\"y_range\":{\"id\":\"1005\"},\"y_scale\":{\"id\":\"1009\"}},\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"axis_label\":\"time (units of 1/k)\",\"formatter\":{\"id\":\"1040\"},\"ticker\":{\"id\":\"1012\"}},\"id\":\"1011\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"1024\",\"type\":\"HelpTool\"},{\"attributes\":{\"text\":\"\"},\"id\":\"1038\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"1040\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"1044\",\"type\":\"Selection\"},{\"attributes\":{\"bottom_units\":\"screen\",\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"top_units\":\"screen\"},\"id\":\"1025\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"axis\":{\"id\":\"1015\"},\"dimension\":1,\"ticker\":null},\"id\":\"1018\",\"type\":\"Grid\"},{\"attributes\":{\"axis\":{\"id\":\"1011\"},\"ticker\":null},\"id\":\"1014\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"1003\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1042\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"1016\",\"type\":\"BasicTicker\"},{\"attributes\":{\"axis_label\":\"number of bacteria\",\"formatter\":{\"id\":\"1042\"},\"ticker\":{\"id\":\"1016\"}},\"id\":\"1015\",\"type\":\"LinearAxis\"},{\"attributes\":{\"source\":{\"id\":\"1033\"}},\"id\":\"1037\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"1045\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"line_color\":\"#1f77b4\",\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1034\",\"type\":\"Line\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"1019\"},{\"id\":\"1020\"},{\"id\":\"1021\"},{\"id\":\"1022\"},{\"id\":\"1023\"},{\"id\":\"1024\"}]},\"id\":\"1026\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"1009\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"1019\",\"type\":\"PanTool\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#1f77b4\",\"line_width\":2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1035\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1020\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"data\":{\"x\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[1000]},\"y\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[1000]}},\"selected\":{\"id\":\"1044\"},\"selection_policy\":{\"id\":\"1045\"}},\"id\":\"1033\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"overlay\":{\"id\":\"1025\"}},\"id\":\"1021\",\"type\":\"BoxZoomTool\"},{\"attributes\":{},\"id\":\"1007\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"1022\",\"type\":\"SaveTool\"},{\"attributes\":{\"data_source\":{\"id\":\"1033\"},\"glyph\":{\"id\":\"1034\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1035\"},\"selection_glyph\":null,\"view\":{\"id\":\"1037\"}},\"id\":\"1036\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"1023\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"1005\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1012\",\"type\":\"BasicTicker\"}],\"root_ids\":[\"1002\"]},\"title\":\"Bokeh Application\",\"version\":\"2.1.1\"}};\n", " var render_items = [{\"docid\":\"5f308faf-4fcf-4cf7-9a31-e9f949bb1859\",\"root_ids\":[\"1002\"],\"roots\":{\"1002\":\"6b3825a3-fa66-4641-a46a-c07e3a8f1495\"}}];\n", " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", "\n", " }\n", " if (root.Bokeh !== undefined) {\n", " embed_document(root);\n", " } else {\n", " var attempts = 0;\n", " var timer = setInterval(function(root) {\n", " if (root.Bokeh !== undefined) {\n", " clearInterval(timer);\n", " embed_document(root);\n", " } else {\n", " attempts++;\n", " if (attempts > 100) {\n", " clearInterval(timer);\n", " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", " }\n", " }\n", " }, 10, root)\n", " }\n", "})(window);"], "application/vnd.bokehjs_exec.v0+json": ""}, "metadata": {"application/vnd.bokehjs_exec.v0+json": {"id": "1002"}}, "output_type": "display_data"}], "source": ["p = bokeh.plotting.figure(\n", " height=300,\n", " width=450,\n", " x_axis_label=\"time (units of 1/k)\",\n", " y_axis_label=\"number of bacteria\",\n", ")\n", "\n", "p.line(x=t, y=n, line_width=2)\n", "\n", "bokeh.io.show(p)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["And there is the famous exponential growth!\n", "\n", "This time stepping method is called [Euler's method](https://en.wikipedia.org/wiki/Euler_method), and what we're doing is called *numerical solution of a differential equation*.\n", "\n", "**a)** Now it's time to solve the Lorenz attractor. In this case, there are three differential equations.\n", "\n", "\\begin{align}\n", "&\\frac{\\mathrm{d}x}{\\mathrm{d}t} = \\sigma(y - x),\\\\[1em]\n", "&\\frac{\\mathrm{d}y}{\\mathrm{d}t} = x(\\rho - z) - y,\\\\[1em]\n", "&\\frac{\\mathrm{d}z}{\\mathrm{d}t} = xy - \\beta z.\n", "\\end{align}\n", "\n", "Your task in this exercise is to numerically solve these two differential equations together and then plot the result. Use the following parameter values, which were the ones originally used by Lorenz.\n", "\n", "```python\n", "sigma = 10\n", "beta = 8/3\n", "rho = 28\n", "```\n", "\n", "Start at time $t = 0$ with $x = y = z= 1$.\n", "\n", "Even though there are now three differential equations, the procedure is the same, you update each by adding $\\Delta t$ times the respective derivative. You should integrate these equations until time $t = 60$. I would recommend a step size of 0.001.\n", "\n", "**b)** Plot your solution showing $x$ versus time.\n", "\n", "**c)** Solve again, this time with $x(0) = 1.0001$, just 0.01\\% different from your previous starting point. Plot this solution on the same plot as your did in part (b) so you can compare the trajectories for just slightly different initial conditions.\n", "\n", "\n", "**d)** Now make three plots. Plot $x$ vs $y$, $x$ vs $x$, and $y$ vs $z$. Look at the result. Cool, right?\n", "\n", "**e)** [Bonus] Euler's method is probably the simplest way to solve differential equations, and is by no means the best. SciPy has an ODE solver, `scipy.integrate.odeint()` that uses the more sophisticated and robust methods for solving systems of ODEs. Read the documentation about how `scipy.integrate.odeint()` works and use it to solve the Lorenz attractor system of ODEs.\n", "\n", "This last part is tough; I'm not giving you directions, and you are kind of on your own to read the documentation and figure it out."]}, {"cell_type": "markdown", "metadata": {}, "source": ["
"]}], "metadata": {"anaconda-cloud": {}, "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.7.7"}}, "nbformat": 4, "nbformat_minor": 4}