1958 lines
164 KiB
Text
1958 lines
164 KiB
Text
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Batch Reactor Example\n",
|
|
"## Ignition delay computation\n",
|
|
"\n",
|
|
"In this example we will illustrate how to setup and use a constant volume batch reactor. This reactor will then be used to compute the ignition delay of a gas at any temperature and pressure\n",
|
|
"\n",
|
|
"The reactor (system) is simply an insulated box."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Runnning Cantera version: 2.3.0a3\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from __future__ import division\n",
|
|
"from __future__ import print_function\n",
|
|
"\n",
|
|
"import pandas as pd\n",
|
|
"import numpy as np\n",
|
|
"\n",
|
|
"import time\n",
|
|
"\n",
|
|
"import cantera as ct\n",
|
|
"print('Runnning Cantera version: ' + ct.__version__)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Define the gas\n",
|
|
"In this example we will choose n-heptane as the gas. For a representative kinetic model, we use the 160 species [mechanism](https://combustion.llnl.gov/archived-mechanisms/alkanes/heptane-reduced-mechanism) by [Seier et al. 2000, Proc. Comb. Inst](http://dx.doi.org/10.1016/S0082-0784(00)80610-4). "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"\n",
|
|
"\n",
|
|
"**** WARNING ****\n",
|
|
"For species c7h15o-1, discontinuity in cp/R detected at Tmid = 1391\n",
|
|
"\tValue computed using low-temperature polynomial: 53.0168\n",
|
|
"\tValue computed using high-temperature polynomial: 52.748\n",
|
|
"\n",
|
|
"\n",
|
|
"**** WARNING ****\n",
|
|
"For species c7h15o-1, discontinuity in h/RT detected at Tmid = 1391\n",
|
|
"\tValue computed using low-temperature polynomial: 21.8343\n",
|
|
"\tValue computed using high-temperature polynomial: 21.767\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"gas = ct.Solution('data/seiser.cti')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Define reactor conditions : temperature, pressure, fuel, stoichiometry"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Define the reactor temperature and pressure\n",
|
|
"reactorTemperature = 1000 #Kelvin\n",
|
|
"reactorPressure = 101325.0 #Pascals\n",
|
|
"\n",
|
|
"gas.TP = reactorTemperature, reactorPressure\n",
|
|
"\n",
|
|
"# Define the fuel, oxidizer and set the stoichiometry\n",
|
|
"gas.set_equivalence_ratio(phi=1.0, fuel='nc7h16', oxidizer={'o2':1.0, 'n2':3.76})\n",
|
|
"\n",
|
|
"# Create a batch reactor object and add it to a reactor network\n",
|
|
"# In this example, the batch reactor will be the only reactor\n",
|
|
"# in the network\n",
|
|
"r = ct.IdealGasReactor(contents=gas, name='Batch Reactor')\n",
|
|
"reactorNetwork = ct.ReactorNet([r])\n",
|
|
"\n",
|
|
"# now compile a list of all variables for which we will store data\n",
|
|
"stateVariableNames = [r.component_name(item) for item in range(r.n_vars)]\n",
|
|
"\n",
|
|
"# use the above list to create a DataFrame\n",
|
|
"timeHistory = pd.DataFrame(columns=stateVariableNames)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Define useful functions"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def ignitionDelay(df, species):\n",
|
|
" \"\"\"\n",
|
|
" This function computes the ignition delay from the occurence of the\n",
|
|
" peak in species' concentration.\n",
|
|
" \"\"\"\n",
|
|
" return df[species].argmax()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Computed Ignition Delay: 3.248e-02 seconds. Took 2.30s to compute\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"#Tic\n",
|
|
"t0 = time.time()\n",
|
|
"\n",
|
|
"# This is a starting estimate. If you do not get an ignition within this time, increase it\n",
|
|
"estimatedIgnitionDelayTime = 0.1\n",
|
|
"t = 0\n",
|
|
"\n",
|
|
"counter = 1;\n",
|
|
"while(t < estimatedIgnitionDelayTime):\n",
|
|
" t = reactorNetwork.step()\n",
|
|
" if (counter%10 == 0):\n",
|
|
" # We will save only every 10th value. Otherwise, this takes too long\n",
|
|
" # Note that the species concentrations are mass fractions\n",
|
|
" timeHistory.loc[t] = reactorNetwork.get_state()\n",
|
|
" counter+=1\n",
|
|
"\n",
|
|
"# We will use the 'oh' species to compute the ignition delay\n",
|
|
"tau = ignitionDelay(timeHistory, 'oh')\n",
|
|
"\n",
|
|
"#Toc\n",
|
|
"t1 = time.time()\n",
|
|
"\n",
|
|
"print('Computed Ignition Delay: {:.3e} seconds. Took {:3.2f}s to compute'.format(tau, t1-t0))\n",
|
|
"\n",
|
|
"# If you want to save all the data - molefractions, temperature, pressure, etc\n",
|
|
"# uncomment the next line\n",
|
|
"# timeHistory.to_csv(\"time_history.csv\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Plot the result"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Import modules and set plotting defaults"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import matplotlib.pyplot as plt\n",
|
|
"import matplotlib as mpl\n",
|
|
"%matplotlib notebook\n",
|
|
"\n",
|
|
"plt.rcParams['axes.labelsize'] = 18\n",
|
|
"plt.rcParams['xtick.labelsize'] = 12\n",
|
|
"plt.rcParams['ytick.labelsize'] = 12\n",
|
|
"plt.rcParams['figure.autolayout'] = True\n",
|
|
"\n",
|
|
"plt.style.use('ggplot')\n",
|
|
"plt.style.use('seaborn-pastel')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Figure illustrating the definition of ignition delay"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"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 = $('<div/>');\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",
|
|
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
|
|
" 'ui-helper-clearfix\"/>');\n",
|
|
" var titletext = $(\n",
|
|
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
|
|
" 'text-align: center; padding: 3px;\"/>');\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 = $('<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 = $('<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 = $('<canvas/>');\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 = $('<div/>')\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 = $('<button/>');\n",
|
|
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
|
|
" 'ui-button-icon-only');\n",
|
|
" button.attr('role', 'button');\n",
|
|
" button.attr('aria-disabled', 'false');\n",
|
|
" button.click(method_name, toolbar_event);\n",
|
|
" button.mouseover(tooltip, toolbar_mouse_event);\n",
|
|
"\n",
|
|
" var icon_img = $('<span/>');\n",
|
|
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
|
|
" icon_img.addClass(image);\n",
|
|
" icon_img.addClass('ui-corner-all');\n",
|
|
"\n",
|
|
" var tooltip_span = $('<span/>');\n",
|
|
" tooltip_span.addClass('ui-button-text');\n",
|
|
" tooltip_span.html(tooltip);\n",
|
|
"\n",
|
|
" button.append(icon_img);\n",
|
|
" button.append(tooltip_span);\n",
|
|
"\n",
|
|
" nav_element.append(button);\n",
|
|
" }\n",
|
|
"\n",
|
|
" var fmt_picker_span = $('<span/>');\n",
|
|
"\n",
|
|
" var fmt_picker = $('<select/>');\n",
|
|
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
|
|
" fmt_picker_span.append(fmt_picker);\n",
|
|
" nav_element.append(fmt_picker_span);\n",
|
|
" this.format_dropdown = fmt_picker[0];\n",
|
|
"\n",
|
|
" for (var ind in mpl.extensions) {\n",
|
|
" var fmt = mpl.extensions[ind];\n",
|
|
" var option = $(\n",
|
|
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
|
|
" fmt_picker.append(option)\n",
|
|
" }\n",
|
|
"\n",
|
|
" // Add hover states to the ui-buttons\n",
|
|
" $( \".ui-button\" ).hover(\n",
|
|
" function() { $(this).addClass(\"ui-state-hover\");},\n",
|
|
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
|
|
" );\n",
|
|
"\n",
|
|
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
|
|
" nav_element.append(status_bar);\n",
|
|
" this.message = status_bar[0];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
|
|
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
|
|
" // which will in turn request a refresh of the image.\n",
|
|
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.send_message = function(type, properties) {\n",
|
|
" properties['type'] = type;\n",
|
|
" properties['figure_id'] = this.id;\n",
|
|
" this.ws.send(JSON.stringify(properties));\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.send_draw_message = function() {\n",
|
|
" if (!this.waiting) {\n",
|
|
" this.waiting = true;\n",
|
|
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
|
|
" var format_dropdown = fig.format_dropdown;\n",
|
|
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
|
|
" fig.ondownload(fig, format);\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
|
|
" var size = msg['size'];\n",
|
|
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
|
|
" fig._resize_canvas(size[0], size[1]);\n",
|
|
" fig.send_message(\"refresh\", {});\n",
|
|
" };\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
|
|
" var x0 = msg['x0'];\n",
|
|
" var y0 = fig.canvas.height - msg['y0'];\n",
|
|
" var x1 = msg['x1'];\n",
|
|
" var y1 = fig.canvas.height - msg['y1'];\n",
|
|
" x0 = Math.floor(x0) + 0.5;\n",
|
|
" y0 = Math.floor(y0) + 0.5;\n",
|
|
" x1 = Math.floor(x1) + 0.5;\n",
|
|
" y1 = Math.floor(y1) + 0.5;\n",
|
|
" var min_x = Math.min(x0, x1);\n",
|
|
" var min_y = Math.min(y0, y1);\n",
|
|
" var width = Math.abs(x1 - x0);\n",
|
|
" var height = Math.abs(y1 - y0);\n",
|
|
"\n",
|
|
" fig.rubberband_context.clearRect(\n",
|
|
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
|
|
"\n",
|
|
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
|
|
" // Updates the figure title.\n",
|
|
" fig.header.textContent = msg['label'];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
|
|
" var cursor = msg['cursor'];\n",
|
|
" switch(cursor)\n",
|
|
" {\n",
|
|
" case 0:\n",
|
|
" cursor = 'pointer';\n",
|
|
" break;\n",
|
|
" case 1:\n",
|
|
" cursor = 'default';\n",
|
|
" break;\n",
|
|
" case 2:\n",
|
|
" cursor = 'crosshair';\n",
|
|
" break;\n",
|
|
" case 3:\n",
|
|
" cursor = 'move';\n",
|
|
" break;\n",
|
|
" }\n",
|
|
" fig.rubberband_canvas.style.cursor = cursor;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
|
|
" fig.message.textContent = msg['message'];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
|
|
" // Request the server to send over a new figure.\n",
|
|
" fig.send_draw_message();\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
|
|
" fig.image_mode = msg['mode'];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.updated_canvas_event = function() {\n",
|
|
" // Called whenever the canvas gets updated.\n",
|
|
" this.send_message(\"ack\", {});\n",
|
|
"}\n",
|
|
"\n",
|
|
"// A function to construct a web socket function for onmessage handling.\n",
|
|
"// Called in the figure constructor.\n",
|
|
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
|
|
" return function socket_on_message(evt) {\n",
|
|
" if (evt.data instanceof Blob) {\n",
|
|
" /* FIXME: We get \"Resource interpreted as Image but\n",
|
|
" * transferred with MIME type text/plain:\" errors on\n",
|
|
" * Chrome. But how to set the MIME type? It doesn't seem\n",
|
|
" * to be part of the websocket stream */\n",
|
|
" evt.data.type = \"image/png\";\n",
|
|
"\n",
|
|
" /* Free the memory for the previous frames */\n",
|
|
" if (fig.imageObj.src) {\n",
|
|
" (window.URL || window.webkitURL).revokeObjectURL(\n",
|
|
" fig.imageObj.src);\n",
|
|
" }\n",
|
|
"\n",
|
|
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
|
|
" evt.data);\n",
|
|
" fig.updated_canvas_event();\n",
|
|
" fig.waiting = false;\n",
|
|
" return;\n",
|
|
" }\n",
|
|
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
|
|
" fig.imageObj.src = evt.data;\n",
|
|
" fig.updated_canvas_event();\n",
|
|
" fig.waiting = false;\n",
|
|
" return;\n",
|
|
" }\n",
|
|
"\n",
|
|
" var msg = JSON.parse(evt.data);\n",
|
|
" var msg_type = msg['type'];\n",
|
|
"\n",
|
|
" // Call the \"handle_{type}\" callback, which takes\n",
|
|
" // the figure and JSON message as its only arguments.\n",
|
|
" try {\n",
|
|
" var callback = fig[\"handle_\" + msg_type];\n",
|
|
" } catch (e) {\n",
|
|
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
|
|
" return;\n",
|
|
" }\n",
|
|
"\n",
|
|
" if (callback) {\n",
|
|
" try {\n",
|
|
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
|
|
" callback(fig, msg);\n",
|
|
" } catch (e) {\n",
|
|
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
|
|
" }\n",
|
|
" }\n",
|
|
" };\n",
|
|
"}\n",
|
|
"\n",
|
|
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
|
|
"mpl.findpos = function(e) {\n",
|
|
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
|
|
" var targ;\n",
|
|
" if (!e)\n",
|
|
" e = window.event;\n",
|
|
" if (e.target)\n",
|
|
" targ = e.target;\n",
|
|
" else if (e.srcElement)\n",
|
|
" targ = e.srcElement;\n",
|
|
" if (targ.nodeType == 3) // defeat Safari bug\n",
|
|
" targ = targ.parentNode;\n",
|
|
"\n",
|
|
" // jQuery normalizes the pageX and pageY\n",
|
|
" // pageX,Y are the mouse positions relative to the document\n",
|
|
" // offset() returns the position of the element relative to the document\n",
|
|
" var x = e.pageX - $(targ).offset().left;\n",
|
|
" var y = e.pageY - $(targ).offset().top;\n",
|
|
"\n",
|
|
" return {\"x\": x, \"y\": y};\n",
|
|
"};\n",
|
|
"\n",
|
|
"/*\n",
|
|
" * return a copy of an object with only non-object keys\n",
|
|
" * we need this to avoid circular references\n",
|
|
" * http://stackoverflow.com/a/24161582/3208463\n",
|
|
" */\n",
|
|
"function simpleKeys (original) {\n",
|
|
" return Object.keys(original).reduce(function (obj, key) {\n",
|
|
" if (typeof original[key] !== 'object')\n",
|
|
" obj[key] = original[key]\n",
|
|
" return obj;\n",
|
|
" }, {});\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
|
|
" var canvas_pos = mpl.findpos(event)\n",
|
|
"\n",
|
|
" if (name === 'button_press')\n",
|
|
" {\n",
|
|
" this.canvas.focus();\n",
|
|
" this.canvas_div.focus();\n",
|
|
" }\n",
|
|
"\n",
|
|
" var x = canvas_pos.x;\n",
|
|
" var y = canvas_pos.y;\n",
|
|
"\n",
|
|
" this.send_message(name, {x: x, y: y, button: event.button,\n",
|
|
" step: event.step,\n",
|
|
" guiEvent: simpleKeys(event)});\n",
|
|
"\n",
|
|
" /* This prevents the web browser from automatically changing to\n",
|
|
" * the text insertion cursor when the button is pressed. We want\n",
|
|
" * to control all of the cursor setting manually through the\n",
|
|
" * 'cursor' event from matplotlib */\n",
|
|
" event.preventDefault();\n",
|
|
" return false;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
|
|
" // Handle any extra behaviour associated with a key event\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.key_event = function(event, name) {\n",
|
|
"\n",
|
|
" // Prevent repeat events\n",
|
|
" if (name == 'key_press')\n",
|
|
" {\n",
|
|
" if (event.which === this._key)\n",
|
|
" return;\n",
|
|
" else\n",
|
|
" this._key = event.which;\n",
|
|
" }\n",
|
|
" if (name == 'key_release')\n",
|
|
" this._key = null;\n",
|
|
"\n",
|
|
" var value = '';\n",
|
|
" if (event.ctrlKey && event.which != 17)\n",
|
|
" value += \"ctrl+\";\n",
|
|
" if (event.altKey && event.which != 18)\n",
|
|
" value += \"alt+\";\n",
|
|
" if (event.shiftKey && event.which != 16)\n",
|
|
" value += \"shift+\";\n",
|
|
"\n",
|
|
" value += 'k';\n",
|
|
" value += event.which.toString();\n",
|
|
"\n",
|
|
" this._key_event_extra(event, name);\n",
|
|
"\n",
|
|
" this.send_message(name, {key: value,\n",
|
|
" guiEvent: simpleKeys(event)});\n",
|
|
" return false;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
|
|
" if (name == 'download') {\n",
|
|
" this.handle_save(this, null);\n",
|
|
" } else {\n",
|
|
" this.send_message(\"toolbar_button\", {name: name});\n",
|
|
" }\n",
|
|
"};\n",
|
|
"\n",
|
|
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
|
|
" this.message.textContent = tooltip;\n",
|
|
"};\n",
|
|
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
|
|
"\n",
|
|
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
|
|
"\n",
|
|
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
|
|
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
|
|
" // object with the appropriate methods. Currently this is a non binary\n",
|
|
" // socket, so there is still some room for performance tuning.\n",
|
|
" var ws = {};\n",
|
|
"\n",
|
|
" ws.close = function() {\n",
|
|
" comm.close()\n",
|
|
" };\n",
|
|
" ws.send = function(m) {\n",
|
|
" //console.log('sending', m);\n",
|
|
" comm.send(m);\n",
|
|
" };\n",
|
|
" // Register the callback with on_msg.\n",
|
|
" comm.on_msg(function(msg) {\n",
|
|
" //console.log('receiving', msg['content']['data'], msg);\n",
|
|
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
|
|
" ws.onmessage(msg['content']['data'])\n",
|
|
" });\n",
|
|
" return ws;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.mpl_figure_comm = function(comm, msg) {\n",
|
|
" // This is the function which gets called when the mpl process\n",
|
|
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
|
|
"\n",
|
|
" var id = msg.content.data.id;\n",
|
|
" // Get hold of the div created by the display call when the Comm\n",
|
|
" // socket was opened in Python.\n",
|
|
" var element = $(\"#\" + id);\n",
|
|
" var ws_proxy = comm_websocket_adapter(comm)\n",
|
|
"\n",
|
|
" function ondownload(figure, format) {\n",
|
|
" window.open(figure.imageObj.src);\n",
|
|
" }\n",
|
|
"\n",
|
|
" var fig = new mpl.figure(id, ws_proxy,\n",
|
|
" ondownload,\n",
|
|
" element.get(0));\n",
|
|
"\n",
|
|
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
|
|
" // web socket which is closed, not our websocket->open comm proxy.\n",
|
|
" ws_proxy.onopen();\n",
|
|
"\n",
|
|
" fig.parent_element = element.get(0);\n",
|
|
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
|
|
" if (!fig.cell_info) {\n",
|
|
" console.error(\"Failed to find cell for figure\", id, fig);\n",
|
|
" return;\n",
|
|
" }\n",
|
|
"\n",
|
|
" var output_index = fig.cell_info[2]\n",
|
|
" var cell = fig.cell_info[0];\n",
|
|
"\n",
|
|
"};\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
|
|
" fig.root.unbind('remove')\n",
|
|
"\n",
|
|
" // Update the output cell to use the data from the current canvas.\n",
|
|
" fig.push_to_output();\n",
|
|
" var dataURL = fig.canvas.toDataURL();\n",
|
|
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
|
|
" // the notebook keyboard shortcuts fail.\n",
|
|
" IPython.keyboard_manager.enable()\n",
|
|
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n",
|
|
" fig.close_ws(fig, msg);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
|
|
" fig.send_message('closing', msg);\n",
|
|
" // fig.ws.close()\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
|
|
" // Turn the data on the canvas into data in the output cell.\n",
|
|
" var dataURL = this.canvas.toDataURL();\n",
|
|
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.updated_canvas_event = function() {\n",
|
|
" // Tell IPython that the notebook contents must change.\n",
|
|
" IPython.notebook.set_dirty(true);\n",
|
|
" this.send_message(\"ack\", {});\n",
|
|
" var fig = this;\n",
|
|
" // Wait a second, then push the new image to the DOM so\n",
|
|
" // that it is saved nicely (might be nice to debounce this).\n",
|
|
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._init_toolbar = function() {\n",
|
|
" var fig = this;\n",
|
|
"\n",
|
|
" var nav_element = $('<div/>')\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) { continue; };\n",
|
|
"\n",
|
|
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
|
|
" button.click(method_name, toolbar_event);\n",
|
|
" button.mouseover(tooltip, toolbar_mouse_event);\n",
|
|
" nav_element.append(button);\n",
|
|
" }\n",
|
|
"\n",
|
|
" // Add the status bar.\n",
|
|
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
|
|
" nav_element.append(status_bar);\n",
|
|
" this.message = status_bar[0];\n",
|
|
"\n",
|
|
" // Add the close button to the window.\n",
|
|
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
|
|
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
|
|
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
|
|
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
|
|
" buttongrp.append(button);\n",
|
|
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
|
|
" titlebar.prepend(buttongrp);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._root_extra_style = function(el){\n",
|
|
" var fig = this\n",
|
|
" el.on(\"remove\", function(){\n",
|
|
"\tfig.close_ws(fig, {});\n",
|
|
" });\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
|
|
" // this is important to make the div 'focusable\n",
|
|
" el.attr('tabindex', 0)\n",
|
|
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
|
|
" // off when our div gets focus\n",
|
|
"\n",
|
|
" // location in version 3\n",
|
|
" if (IPython.notebook.keyboard_manager) {\n",
|
|
" IPython.notebook.keyboard_manager.register_events(el);\n",
|
|
" }\n",
|
|
" else {\n",
|
|
" // location in version 2\n",
|
|
" IPython.keyboard_manager.register_events(el);\n",
|
|
" }\n",
|
|
"\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
|
|
" var manager = IPython.notebook.keyboard_manager;\n",
|
|
" if (!manager)\n",
|
|
" manager = IPython.keyboard_manager;\n",
|
|
"\n",
|
|
" // Check for shift+enter\n",
|
|
" if (event.shiftKey && event.which == 13) {\n",
|
|
" this.canvas_div.blur();\n",
|
|
" event.shiftKey = false;\n",
|
|
" // Send a \"J\" for go to next cell\n",
|
|
" event.which = 74;\n",
|
|
" event.keyCode = 74;\n",
|
|
" manager.command_mode();\n",
|
|
" manager.handle_keydown(event);\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
|
|
" fig.ondownload(fig, null);\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.find_output_cell = function(html_output) {\n",
|
|
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
|
|
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
|
|
" // IPython event is triggered only after the cells have been serialised, which for\n",
|
|
" // our purposes (turning an active figure into a static one), is too late.\n",
|
|
" var cells = IPython.notebook.get_cells();\n",
|
|
" var ncells = cells.length;\n",
|
|
" for (var i=0; i<ncells; i++) {\n",
|
|
" var cell = cells[i];\n",
|
|
" if (cell.cell_type === 'code'){\n",
|
|
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
|
|
" var data = cell.output_area.outputs[j];\n",
|
|
" if (data.data) {\n",
|
|
" // IPython >= 3 moved mimebundle to data attribute of output\n",
|
|
" data = data.data;\n",
|
|
" }\n",
|
|
" if (data['text/html'] == html_output) {\n",
|
|
" return [cell, data, j];\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"// Register the function which deals with the matplotlib target/channel.\n",
|
|
"// The kernel may be null if the page has been refreshed.\n",
|
|
"if (IPython.notebook.kernel != null) {\n",
|
|
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
|
|
"}\n"
|
|
],
|
|
"text/plain": [
|
|
"<IPython.core.display.Javascript object>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<img src=\"data:image/png;base64,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\">"
|
|
],
|
|
"text/plain": [
|
|
"<IPython.core.display.HTML object>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"plt.figure()\n",
|
|
"plt.plot(timeHistory.index, timeHistory['oh'],'-o')\n",
|
|
"plt.xlabel('Time (s)')\n",
|
|
"plt.ylabel('$Y_{OH}$')\n",
|
|
"\n",
|
|
"plt.xlim([0,0.05])\n",
|
|
"plt.arrow(0, 0.008, tau, 0, width=0.0001, head_width=0.0005,\n",
|
|
" head_length=0.001, length_includes_head=True, color='r', shape='full')\n",
|
|
"plt.annotate(r'$Ignition Delay: \\tau_{ign}$', xy=(0,0), xytext=(0.01, 0.0082), fontsize=16);"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Illustration : NTC behavior\n",
|
|
"A common benchmark for a reaction mechanism is its ability to reproduce the **N**egative **T**emperature **C**oefficient behavior. Intuitively, as the temperature of an explosive mixture increases, it should ignite faster. But, under certain conditions, we observe the opposite. This is referred to as NTC behavior. Reproducing experimentally observed NTC behavior is thus an important test for any mechanism. We will do this now by computing and visualizing the ignition delay for a wide range of temperatures"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Define the temperatures for which we will run the simulations"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Make a list of all the temperatures we would like to run simulations at\n",
|
|
"T = [1800, 1600, 1400, 1200, 1000, 950, 925, 900, 850, 825, 800,\n",
|
|
" 750, 700, 675, 650, 625, 600, 550, 500]\n",
|
|
"\n",
|
|
"estimatedIgnitionDelayTimes = np.ones(len(T))\n",
|
|
"\n",
|
|
"# Make time adjustments for the highest and lowest temperatures. This we do empirically\n",
|
|
"estimatedIgnitionDelayTimes[:6] = 6*[0.1]\n",
|
|
"estimatedIgnitionDelayTimes[-2:] = 10\n",
|
|
"estimatedIgnitionDelayTimes[-1] = 100\n",
|
|
"\n",
|
|
"# Now create a dataFrame out of these\n",
|
|
"ignitionDelays = pd.DataFrame(data={'T':T})\n",
|
|
"ignitionDelays['ignDelay'] = np.nan"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Now, what we will do is simply run the code above the plots for each temperature."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"metadata": {
|
|
"scrolled": false
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Computed Ignition Delay: 1.765e-05 seconds for T=1800K. Took 1.07s to compute\n",
|
|
"Computed Ignition Delay: 3.454e-05 seconds for T=1600K. Took 0.99s to compute\n",
|
|
"Computed Ignition Delay: 1.614e-04 seconds for T=1400K. Took 0.99s to compute\n",
|
|
"Computed Ignition Delay: 1.629e-03 seconds for T=1200K. Took 1.10s to compute\n",
|
|
"Computed Ignition Delay: 3.248e-02 seconds for T=1000K. Took 1.23s to compute\n",
|
|
"Computed Ignition Delay: 7.909e-02 seconds for T=950K. Took 1.32s to compute\n",
|
|
"Computed Ignition Delay: 1.252e-01 seconds for T=925K. Took 1.37s to compute\n",
|
|
"Computed Ignition Delay: 1.983e-01 seconds for T=900K. Took 1.34s to compute\n",
|
|
"Computed Ignition Delay: 4.266e-01 seconds for T=850K. Took 1.43s to compute\n",
|
|
"Computed Ignition Delay: 4.726e-01 seconds for T=825K. Took 1.47s to compute\n",
|
|
"Computed Ignition Delay: 3.795e-01 seconds for T=800K. Took 1.42s to compute\n",
|
|
"Computed Ignition Delay: 1.462e-01 seconds for T=750K. Took 1.66s to compute\n",
|
|
"Computed Ignition Delay: 6.427e-02 seconds for T=700K. Took 1.80s to compute\n",
|
|
"Computed Ignition Delay: 5.791e-02 seconds for T=675K. Took 1.81s to compute\n",
|
|
"Computed Ignition Delay: 7.723e-02 seconds for T=650K. Took 1.83s to compute\n",
|
|
"Computed Ignition Delay: 1.503e-01 seconds for T=625K. Took 2.01s to compute\n",
|
|
"Computed Ignition Delay: 3.754e-01 seconds for T=600K. Took 2.03s to compute\n",
|
|
"Computed Ignition Delay: 3.749e+00 seconds for T=550K. Took 2.13s to compute\n",
|
|
"Computed Ignition Delay: 6.945e+01 seconds for T=500K. Took 2.15s to compute\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"for i, temperature in enumerate(T):\n",
|
|
" # Setup the gas and reactor\n",
|
|
" reactorTemperature = temperature\n",
|
|
" reactorPressure = 101325.0\n",
|
|
" gas.TP = reactorTemperature, reactorPressure\n",
|
|
" gas.set_equivalence_ratio(phi=1.0, fuel='nc7h16', oxidizer={'o2':1.0, 'n2':3.76})\n",
|
|
" r = ct.IdealGasReactor(contents=gas, name='Batch Reactor')\n",
|
|
" reactorNetwork = ct.ReactorNet([r])\n",
|
|
"\n",
|
|
" # Create and empty data frame\n",
|
|
" timeHistory = pd.DataFrame(columns=timeHistory.columns)\n",
|
|
"\n",
|
|
" t0 = time.time()\n",
|
|
"\n",
|
|
" t = 0\n",
|
|
" counter = 0\n",
|
|
" while t < estimatedIgnitionDelayTimes[i]:\n",
|
|
" t = reactorNetwork.step()\n",
|
|
" if not counter % 20:\n",
|
|
" timeHistory.loc[t] = r.get_state()\n",
|
|
" counter += 1\n",
|
|
"\n",
|
|
" tau = ignitionDelay(timeHistory, 'oh')\n",
|
|
" t1 = time.time()\n",
|
|
"\n",
|
|
" print('Computed Ignition Delay: {:.3e} seconds for T={}K. Took {:3.2f}s to compute'.format(tau, temperature, t1-t0))\n",
|
|
"\n",
|
|
" ignitionDelays.set_value(index=i, col='ignDelay', value=tau)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Figure: ignition delay ($\\tau$) vs. the inverse of temperature ($\\frac{1000}{T}$). "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"metadata": {
|
|
"scrolled": 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 = $('<div/>');\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",
|
|
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
|
|
" 'ui-helper-clearfix\"/>');\n",
|
|
" var titletext = $(\n",
|
|
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
|
|
" 'text-align: center; padding: 3px;\"/>');\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 = $('<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 = $('<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 = $('<canvas/>');\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 = $('<div/>')\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 = $('<button/>');\n",
|
|
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
|
|
" 'ui-button-icon-only');\n",
|
|
" button.attr('role', 'button');\n",
|
|
" button.attr('aria-disabled', 'false');\n",
|
|
" button.click(method_name, toolbar_event);\n",
|
|
" button.mouseover(tooltip, toolbar_mouse_event);\n",
|
|
"\n",
|
|
" var icon_img = $('<span/>');\n",
|
|
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
|
|
" icon_img.addClass(image);\n",
|
|
" icon_img.addClass('ui-corner-all');\n",
|
|
"\n",
|
|
" var tooltip_span = $('<span/>');\n",
|
|
" tooltip_span.addClass('ui-button-text');\n",
|
|
" tooltip_span.html(tooltip);\n",
|
|
"\n",
|
|
" button.append(icon_img);\n",
|
|
" button.append(tooltip_span);\n",
|
|
"\n",
|
|
" nav_element.append(button);\n",
|
|
" }\n",
|
|
"\n",
|
|
" var fmt_picker_span = $('<span/>');\n",
|
|
"\n",
|
|
" var fmt_picker = $('<select/>');\n",
|
|
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
|
|
" fmt_picker_span.append(fmt_picker);\n",
|
|
" nav_element.append(fmt_picker_span);\n",
|
|
" this.format_dropdown = fmt_picker[0];\n",
|
|
"\n",
|
|
" for (var ind in mpl.extensions) {\n",
|
|
" var fmt = mpl.extensions[ind];\n",
|
|
" var option = $(\n",
|
|
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
|
|
" fmt_picker.append(option)\n",
|
|
" }\n",
|
|
"\n",
|
|
" // Add hover states to the ui-buttons\n",
|
|
" $( \".ui-button\" ).hover(\n",
|
|
" function() { $(this).addClass(\"ui-state-hover\");},\n",
|
|
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
|
|
" );\n",
|
|
"\n",
|
|
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
|
|
" nav_element.append(status_bar);\n",
|
|
" this.message = status_bar[0];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
|
|
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
|
|
" // which will in turn request a refresh of the image.\n",
|
|
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.send_message = function(type, properties) {\n",
|
|
" properties['type'] = type;\n",
|
|
" properties['figure_id'] = this.id;\n",
|
|
" this.ws.send(JSON.stringify(properties));\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.send_draw_message = function() {\n",
|
|
" if (!this.waiting) {\n",
|
|
" this.waiting = true;\n",
|
|
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
|
|
" var format_dropdown = fig.format_dropdown;\n",
|
|
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
|
|
" fig.ondownload(fig, format);\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
|
|
" var size = msg['size'];\n",
|
|
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
|
|
" fig._resize_canvas(size[0], size[1]);\n",
|
|
" fig.send_message(\"refresh\", {});\n",
|
|
" };\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
|
|
" var x0 = msg['x0'];\n",
|
|
" var y0 = fig.canvas.height - msg['y0'];\n",
|
|
" var x1 = msg['x1'];\n",
|
|
" var y1 = fig.canvas.height - msg['y1'];\n",
|
|
" x0 = Math.floor(x0) + 0.5;\n",
|
|
" y0 = Math.floor(y0) + 0.5;\n",
|
|
" x1 = Math.floor(x1) + 0.5;\n",
|
|
" y1 = Math.floor(y1) + 0.5;\n",
|
|
" var min_x = Math.min(x0, x1);\n",
|
|
" var min_y = Math.min(y0, y1);\n",
|
|
" var width = Math.abs(x1 - x0);\n",
|
|
" var height = Math.abs(y1 - y0);\n",
|
|
"\n",
|
|
" fig.rubberband_context.clearRect(\n",
|
|
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
|
|
"\n",
|
|
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
|
|
" // Updates the figure title.\n",
|
|
" fig.header.textContent = msg['label'];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
|
|
" var cursor = msg['cursor'];\n",
|
|
" switch(cursor)\n",
|
|
" {\n",
|
|
" case 0:\n",
|
|
" cursor = 'pointer';\n",
|
|
" break;\n",
|
|
" case 1:\n",
|
|
" cursor = 'default';\n",
|
|
" break;\n",
|
|
" case 2:\n",
|
|
" cursor = 'crosshair';\n",
|
|
" break;\n",
|
|
" case 3:\n",
|
|
" cursor = 'move';\n",
|
|
" break;\n",
|
|
" }\n",
|
|
" fig.rubberband_canvas.style.cursor = cursor;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
|
|
" fig.message.textContent = msg['message'];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
|
|
" // Request the server to send over a new figure.\n",
|
|
" fig.send_draw_message();\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
|
|
" fig.image_mode = msg['mode'];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.updated_canvas_event = function() {\n",
|
|
" // Called whenever the canvas gets updated.\n",
|
|
" this.send_message(\"ack\", {});\n",
|
|
"}\n",
|
|
"\n",
|
|
"// A function to construct a web socket function for onmessage handling.\n",
|
|
"// Called in the figure constructor.\n",
|
|
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
|
|
" return function socket_on_message(evt) {\n",
|
|
" if (evt.data instanceof Blob) {\n",
|
|
" /* FIXME: We get \"Resource interpreted as Image but\n",
|
|
" * transferred with MIME type text/plain:\" errors on\n",
|
|
" * Chrome. But how to set the MIME type? It doesn't seem\n",
|
|
" * to be part of the websocket stream */\n",
|
|
" evt.data.type = \"image/png\";\n",
|
|
"\n",
|
|
" /* Free the memory for the previous frames */\n",
|
|
" if (fig.imageObj.src) {\n",
|
|
" (window.URL || window.webkitURL).revokeObjectURL(\n",
|
|
" fig.imageObj.src);\n",
|
|
" }\n",
|
|
"\n",
|
|
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
|
|
" evt.data);\n",
|
|
" fig.updated_canvas_event();\n",
|
|
" fig.waiting = false;\n",
|
|
" return;\n",
|
|
" }\n",
|
|
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
|
|
" fig.imageObj.src = evt.data;\n",
|
|
" fig.updated_canvas_event();\n",
|
|
" fig.waiting = false;\n",
|
|
" return;\n",
|
|
" }\n",
|
|
"\n",
|
|
" var msg = JSON.parse(evt.data);\n",
|
|
" var msg_type = msg['type'];\n",
|
|
"\n",
|
|
" // Call the \"handle_{type}\" callback, which takes\n",
|
|
" // the figure and JSON message as its only arguments.\n",
|
|
" try {\n",
|
|
" var callback = fig[\"handle_\" + msg_type];\n",
|
|
" } catch (e) {\n",
|
|
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
|
|
" return;\n",
|
|
" }\n",
|
|
"\n",
|
|
" if (callback) {\n",
|
|
" try {\n",
|
|
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
|
|
" callback(fig, msg);\n",
|
|
" } catch (e) {\n",
|
|
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
|
|
" }\n",
|
|
" }\n",
|
|
" };\n",
|
|
"}\n",
|
|
"\n",
|
|
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
|
|
"mpl.findpos = function(e) {\n",
|
|
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
|
|
" var targ;\n",
|
|
" if (!e)\n",
|
|
" e = window.event;\n",
|
|
" if (e.target)\n",
|
|
" targ = e.target;\n",
|
|
" else if (e.srcElement)\n",
|
|
" targ = e.srcElement;\n",
|
|
" if (targ.nodeType == 3) // defeat Safari bug\n",
|
|
" targ = targ.parentNode;\n",
|
|
"\n",
|
|
" // jQuery normalizes the pageX and pageY\n",
|
|
" // pageX,Y are the mouse positions relative to the document\n",
|
|
" // offset() returns the position of the element relative to the document\n",
|
|
" var x = e.pageX - $(targ).offset().left;\n",
|
|
" var y = e.pageY - $(targ).offset().top;\n",
|
|
"\n",
|
|
" return {\"x\": x, \"y\": y};\n",
|
|
"};\n",
|
|
"\n",
|
|
"/*\n",
|
|
" * return a copy of an object with only non-object keys\n",
|
|
" * we need this to avoid circular references\n",
|
|
" * http://stackoverflow.com/a/24161582/3208463\n",
|
|
" */\n",
|
|
"function simpleKeys (original) {\n",
|
|
" return Object.keys(original).reduce(function (obj, key) {\n",
|
|
" if (typeof original[key] !== 'object')\n",
|
|
" obj[key] = original[key]\n",
|
|
" return obj;\n",
|
|
" }, {});\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
|
|
" var canvas_pos = mpl.findpos(event)\n",
|
|
"\n",
|
|
" if (name === 'button_press')\n",
|
|
" {\n",
|
|
" this.canvas.focus();\n",
|
|
" this.canvas_div.focus();\n",
|
|
" }\n",
|
|
"\n",
|
|
" var x = canvas_pos.x;\n",
|
|
" var y = canvas_pos.y;\n",
|
|
"\n",
|
|
" this.send_message(name, {x: x, y: y, button: event.button,\n",
|
|
" step: event.step,\n",
|
|
" guiEvent: simpleKeys(event)});\n",
|
|
"\n",
|
|
" /* This prevents the web browser from automatically changing to\n",
|
|
" * the text insertion cursor when the button is pressed. We want\n",
|
|
" * to control all of the cursor setting manually through the\n",
|
|
" * 'cursor' event from matplotlib */\n",
|
|
" event.preventDefault();\n",
|
|
" return false;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
|
|
" // Handle any extra behaviour associated with a key event\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.key_event = function(event, name) {\n",
|
|
"\n",
|
|
" // Prevent repeat events\n",
|
|
" if (name == 'key_press')\n",
|
|
" {\n",
|
|
" if (event.which === this._key)\n",
|
|
" return;\n",
|
|
" else\n",
|
|
" this._key = event.which;\n",
|
|
" }\n",
|
|
" if (name == 'key_release')\n",
|
|
" this._key = null;\n",
|
|
"\n",
|
|
" var value = '';\n",
|
|
" if (event.ctrlKey && event.which != 17)\n",
|
|
" value += \"ctrl+\";\n",
|
|
" if (event.altKey && event.which != 18)\n",
|
|
" value += \"alt+\";\n",
|
|
" if (event.shiftKey && event.which != 16)\n",
|
|
" value += \"shift+\";\n",
|
|
"\n",
|
|
" value += 'k';\n",
|
|
" value += event.which.toString();\n",
|
|
"\n",
|
|
" this._key_event_extra(event, name);\n",
|
|
"\n",
|
|
" this.send_message(name, {key: value,\n",
|
|
" guiEvent: simpleKeys(event)});\n",
|
|
" return false;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
|
|
" if (name == 'download') {\n",
|
|
" this.handle_save(this, null);\n",
|
|
" } else {\n",
|
|
" this.send_message(\"toolbar_button\", {name: name});\n",
|
|
" }\n",
|
|
"};\n",
|
|
"\n",
|
|
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
|
|
" this.message.textContent = tooltip;\n",
|
|
"};\n",
|
|
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
|
|
"\n",
|
|
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
|
|
"\n",
|
|
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
|
|
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
|
|
" // object with the appropriate methods. Currently this is a non binary\n",
|
|
" // socket, so there is still some room for performance tuning.\n",
|
|
" var ws = {};\n",
|
|
"\n",
|
|
" ws.close = function() {\n",
|
|
" comm.close()\n",
|
|
" };\n",
|
|
" ws.send = function(m) {\n",
|
|
" //console.log('sending', m);\n",
|
|
" comm.send(m);\n",
|
|
" };\n",
|
|
" // Register the callback with on_msg.\n",
|
|
" comm.on_msg(function(msg) {\n",
|
|
" //console.log('receiving', msg['content']['data'], msg);\n",
|
|
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
|
|
" ws.onmessage(msg['content']['data'])\n",
|
|
" });\n",
|
|
" return ws;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.mpl_figure_comm = function(comm, msg) {\n",
|
|
" // This is the function which gets called when the mpl process\n",
|
|
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
|
|
"\n",
|
|
" var id = msg.content.data.id;\n",
|
|
" // Get hold of the div created by the display call when the Comm\n",
|
|
" // socket was opened in Python.\n",
|
|
" var element = $(\"#\" + id);\n",
|
|
" var ws_proxy = comm_websocket_adapter(comm)\n",
|
|
"\n",
|
|
" function ondownload(figure, format) {\n",
|
|
" window.open(figure.imageObj.src);\n",
|
|
" }\n",
|
|
"\n",
|
|
" var fig = new mpl.figure(id, ws_proxy,\n",
|
|
" ondownload,\n",
|
|
" element.get(0));\n",
|
|
"\n",
|
|
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
|
|
" // web socket which is closed, not our websocket->open comm proxy.\n",
|
|
" ws_proxy.onopen();\n",
|
|
"\n",
|
|
" fig.parent_element = element.get(0);\n",
|
|
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
|
|
" if (!fig.cell_info) {\n",
|
|
" console.error(\"Failed to find cell for figure\", id, fig);\n",
|
|
" return;\n",
|
|
" }\n",
|
|
"\n",
|
|
" var output_index = fig.cell_info[2]\n",
|
|
" var cell = fig.cell_info[0];\n",
|
|
"\n",
|
|
"};\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
|
|
" fig.root.unbind('remove')\n",
|
|
"\n",
|
|
" // Update the output cell to use the data from the current canvas.\n",
|
|
" fig.push_to_output();\n",
|
|
" var dataURL = fig.canvas.toDataURL();\n",
|
|
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
|
|
" // the notebook keyboard shortcuts fail.\n",
|
|
" IPython.keyboard_manager.enable()\n",
|
|
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n",
|
|
" fig.close_ws(fig, msg);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
|
|
" fig.send_message('closing', msg);\n",
|
|
" // fig.ws.close()\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
|
|
" // Turn the data on the canvas into data in the output cell.\n",
|
|
" var dataURL = this.canvas.toDataURL();\n",
|
|
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.updated_canvas_event = function() {\n",
|
|
" // Tell IPython that the notebook contents must change.\n",
|
|
" IPython.notebook.set_dirty(true);\n",
|
|
" this.send_message(\"ack\", {});\n",
|
|
" var fig = this;\n",
|
|
" // Wait a second, then push the new image to the DOM so\n",
|
|
" // that it is saved nicely (might be nice to debounce this).\n",
|
|
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._init_toolbar = function() {\n",
|
|
" var fig = this;\n",
|
|
"\n",
|
|
" var nav_element = $('<div/>')\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) { continue; };\n",
|
|
"\n",
|
|
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
|
|
" button.click(method_name, toolbar_event);\n",
|
|
" button.mouseover(tooltip, toolbar_mouse_event);\n",
|
|
" nav_element.append(button);\n",
|
|
" }\n",
|
|
"\n",
|
|
" // Add the status bar.\n",
|
|
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
|
|
" nav_element.append(status_bar);\n",
|
|
" this.message = status_bar[0];\n",
|
|
"\n",
|
|
" // Add the close button to the window.\n",
|
|
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
|
|
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
|
|
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
|
|
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
|
|
" buttongrp.append(button);\n",
|
|
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
|
|
" titlebar.prepend(buttongrp);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._root_extra_style = function(el){\n",
|
|
" var fig = this\n",
|
|
" el.on(\"remove\", function(){\n",
|
|
"\tfig.close_ws(fig, {});\n",
|
|
" });\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
|
|
" // this is important to make the div 'focusable\n",
|
|
" el.attr('tabindex', 0)\n",
|
|
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
|
|
" // off when our div gets focus\n",
|
|
"\n",
|
|
" // location in version 3\n",
|
|
" if (IPython.notebook.keyboard_manager) {\n",
|
|
" IPython.notebook.keyboard_manager.register_events(el);\n",
|
|
" }\n",
|
|
" else {\n",
|
|
" // location in version 2\n",
|
|
" IPython.keyboard_manager.register_events(el);\n",
|
|
" }\n",
|
|
"\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
|
|
" var manager = IPython.notebook.keyboard_manager;\n",
|
|
" if (!manager)\n",
|
|
" manager = IPython.keyboard_manager;\n",
|
|
"\n",
|
|
" // Check for shift+enter\n",
|
|
" if (event.shiftKey && event.which == 13) {\n",
|
|
" this.canvas_div.blur();\n",
|
|
" event.shiftKey = false;\n",
|
|
" // Send a \"J\" for go to next cell\n",
|
|
" event.which = 74;\n",
|
|
" event.keyCode = 74;\n",
|
|
" manager.command_mode();\n",
|
|
" manager.handle_keydown(event);\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
|
|
" fig.ondownload(fig, null);\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.find_output_cell = function(html_output) {\n",
|
|
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
|
|
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
|
|
" // IPython event is triggered only after the cells have been serialised, which for\n",
|
|
" // our purposes (turning an active figure into a static one), is too late.\n",
|
|
" var cells = IPython.notebook.get_cells();\n",
|
|
" var ncells = cells.length;\n",
|
|
" for (var i=0; i<ncells; i++) {\n",
|
|
" var cell = cells[i];\n",
|
|
" if (cell.cell_type === 'code'){\n",
|
|
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
|
|
" var data = cell.output_area.outputs[j];\n",
|
|
" if (data.data) {\n",
|
|
" // IPython >= 3 moved mimebundle to data attribute of output\n",
|
|
" data = data.data;\n",
|
|
" }\n",
|
|
" if (data['text/html'] == html_output) {\n",
|
|
" return [cell, data, j];\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"// Register the function which deals with the matplotlib target/channel.\n",
|
|
"// The kernel may be null if the page has been refreshed.\n",
|
|
"if (IPython.notebook.kernel != null) {\n",
|
|
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
|
|
"}\n"
|
|
],
|
|
"text/plain": [
|
|
"<IPython.core.display.Javascript object>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAAXNSR0IArs4c6QAAQABJREFUeAHsnQmYVNWZ99/qfd+7adkVXMEFFBRXMBogCUZlMYpMSKKoQaMx7WQZJWgyWbQn0cTdxCExRNnUkS/TMjpi3FFbUKHVURQFhN73ffv+76Wqa6Gqu6u6lnur/ud5Tt+z3bP8zq3b7z3Le0RoSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESCAmCMyePTvh0ksvnRATjWUjSYAEvBKI8xrKQBIgARIggagksHr16riioqJ/zcrKqvS3gYsXLy5esmTJtf7ex/QkQALmI2AzX5VYIxIgAasSgIDQjLr32+ufjGs8bBusvmv6bTbb/PXr178Kd1QYtHdrf3//yxs3blxllgahTi+D88d9fX2fxsXFnYT6zYX9HcL0g//ruP4V9oV169btdK3zwoULj4qPj78Jaa9H+COw6zZs2PCCCoy7du3SPkvRe3GtQN5ZaPMGuGlIgARIgARIgARIwEkAI0W/gDDygjPEWi7UPWmoGqsAuGjRojuGSjdU/HDKGioPjb/sssuOQX2WOtIi31/CPuHiPxv+Aw6/5xVx82D3uoajH89F2GWuYfBvgB2Sj+s9dJMACZiLQIK5qsPakAAJRDuB+fPnJ2dmZv4cI01L0NZc2Pdhb8Jo0w5tOwSLrRhpeh/xRfDOh22EvQWjWbsw8vQw3FNhdRRq2aZNmz6G27gHFx3RGg17IexB2F8gz8dwlaHK1DRaLi47UXYByv4q3OsgTKn/OrjHw7bCPg+rda1D3ANwn4P4Wbj3h3D3IzwLV83rM4T/AqOdj6pfDcL6cLkAaV7wKGsuwlVI+/5w6ol0Pk1vb+9ZGJlb45JgDtqio3YOkwfHXQ6P5xV11vTKQXTkr6KiYhnCytGOl1zTIo36vwnL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\">"
|
|
],
|
|
"text/plain": [
|
|
"<IPython.core.display.HTML object>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"fig = plt.figure()\n",
|
|
"ax = fig.add_subplot(111)\n",
|
|
"ax.semilogy(1000/ignitionDelays['T'], ignitionDelays['ignDelay'],'o-')\n",
|
|
"ax.set_ylabel('Ignition Delay (s)')\n",
|
|
"ax.set_xlabel(r'$\\frac{1000}{T (K)}$', fontsize=18)\n",
|
|
"\n",
|
|
"# Add a second axis on top to plot the temperature for better readability\n",
|
|
"ax2 = ax.twiny()\n",
|
|
"ticks = ax.get_xticks()\n",
|
|
"ax2.set_xticks(ticks)\n",
|
|
"ax2.set_xticklabels((1000/ticks).round(1))\n",
|
|
"ax2.set_xlim(ax.get_xlim())\n",
|
|
"ax2.set_xlabel(r'Temperature: $T(K)$');"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"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.8"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 1
|
|
}
|