{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Numerov's Algorithm & Shooting Method: Finite Square Well\n", "\n", "### Time indepedent Schrodinger Equation\n", "\n", "In units where $\\hbar = 1$, the 1D TISE can be expressed in the form:\n", "\n", "\\begin{equation}\n", " \\frac{d^2 \\psi}{dx^2} = -2m\\left(E - V(x) \\right) \\psi = -g(x) \\psi\n", "\\end{equation}\n", "\n", "This differential equation can be solved numerically via Numerov's method ([see page 10 - 11](http://www.fisica.uniud.it/~giannozz/Corsi/MQ/LectureNotes/mq-cap1.pdf)). For a 1D spatial grid, the wavefunction at the $n+1$th point along can be approximated by:\n", "\n", "\\begin{equation}\n", " \\psi_{n+1} = \\frac{(12-10f_n) \\ \\psi_n-f_{n-1}\\psi_{n-1}}{f_{n+1}}\n", "\\end{equation}\n", "\n", "where:\n", "\\begin{equation}\n", " f_n \\equiv \\left( 1 + \\frac{\\delta x^2}{12}g_n \\right), \\ \\ \\ \\ \\ \\ \\ g_n = 2m(E-V(x_n))\n", "\\end{equation}\n", "\n", "Hence to start Numerov's method we require $\\psi_0$ and $\\psi_1$, in other words $\\psi(x = x_{min})$ and $\\psi(x = x_{min} + \\delta x)$, where $\\delta x$ is the step size." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Shooting Method:\n", "\n", "When investigating bound states we require $\\psi( x \\to \\pm \\infty) = 0$. However we cannot consider a infinite domain, instead we must choose a big enough domain that setting $\\psi( x = x_{min}) = 0$ is a good approximation (and similarly for $x_{max}$).\n", "\n", "With Numerov's Method in place, the shooting method can be used to find the energy eigenstates. It goes as follows:\n", "\n", "1. Setting $\\psi_0 = 0$ \"satisfies\" the boundary condition that the wavefunctions must vanish at the boundary\n", "2. Since the Schrodinger Equation is linear and homogeneous we are free to set $\\psi_1$ to any non-zero constant as multiplying by a constant does not affect the solution. In this case we shall set $\\psi_1 = \\delta x$.\n", "3. Using the Numerov algorithm, $\\psi(x)$ can be found. Exponential growth near $x_{max}$ can be observed if the input energy is not near a energy eigenvalue\n", "4. A bisection search can be performed to calculate the energy eigenvalue and eigenstate" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Bisection Search:\n", "\n", "We wish to find a function $f(E) = 0$. First we must find values of $E$ which bracket the solution, that is:\n", "
$f(E_1) > 0 \\ $ and $\\ f(E_2) > 0$
\n", "Evaluating $f$ at the midpoint $E_3 = \\frac{1}{2}(E_1+E_2)$, depending on the result we can rebracket our solution. Hence the solution will be converged about with many iterations. Solutions can converge from both above and below $0$ so your search algorithm should account for this.\n", "\n", "The search should be stopped when $\\left| \\ f(E)\\right| < \\epsilon$ where $\\epsilon$ is a suitably small number.\n", "\n", "\n", "\n", "Dotted lines show the bracket solutions and the solid lines show the progression of the search to obtain the ground state of the infinite square well" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercises:\n", "\n", "1. Write a Numerov routine for a finite square well potential of the form: $V = -V_0$ for $\\left| \\ x \\ \\right| < a$ elsewhere $V = 0$\n", "2. Include a bisection search which calls the Numerov function until a solution is found. Choose large initial energy brackets to ensure a result is within range\n", "3. Search for bound states and travelling wave states, by plotting them note their structure.\n", "4. For $V_0 = 300$, $m = 1$ and $a = 0.15$, find and plot the normalised wavefunctions and energy eigenvalues" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support.' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " this.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('
');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width);\n", " canvas.attr('height', height);\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
')\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('