{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Imports for plotting\n", "\n", "import matplotlib.pyplot as plt\n", "\n", "%matplotlib inline\n", "import numpy as np\n", "import seaborn as sns\n", "\n", "sns.set_style(\"darkgrid\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Built-in Time Functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Field profiles are defined as functions of time. A base `rabi_freq` is multiplied by a time function `rabi_freq_t_func` and related arguments `rabi_freq_t_args`. For example, a Gaussian pulse with a peak of $\\Omega_0 = 2\\pi \\cdot 0.001 \\mathrm{~ MHz}$ and a full-width at half-maximum (FWHM) of $1 \\mathrm{~ \\mu s}$ arriving at the start of the medium at $t = 0 \\mathrm{~ \\mu s}$ can be specified in JSON with `\"rabi_freq\": 1.0e-3`, `\"rabi_freq_t_func\": \"gaussian\", ` and `\"rabi_freq_t_args\": {\"ampl\": 1.0, \"centre\": 0.0, \"fwhm\": 1.0}`.\n", "\n", "Here we'll show all of the built-in `t_funcs` you can use. It is also possible to write your own." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from maxwellbloch import t_funcs\n", "\n", "tlist = np.linspace(0.0, 1.0, 201)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Gaussian\n", "\n", "The Gaussian profile is defined as\n", "\n", "$$\n", "\\Omega_0 \\exp \\left[ -4 \\log 2 \\left( \\frac{t - t_0}{t_w}\n", "\\right)^2 \\right]\n", "$$\n", "\n", "where $t_0$ (`centre`) is the point at which the function reaches its peak amplitude\n", "$\\Omega_0$ (`ampl`). The width $t_w$ (`fwhm`) is\n", "the full width at half maximum (FWHM) of a Gaussian." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(\n", " tlist,\n", " t_funcs.gaussian(1)(tlist, args={\"ampl_1\": 1.0, \"fwhm_1\": 0.1, \"centre_1\": 0.6}),\n", ");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Note\n", "\n", "Why are these args written like `ampl_1` here instead of `ampl`? In the `t_funcs` module, each built-in time profile is specified in a [functor][wiki_functor] that takes an index as argument and returns a function whose `t_args` are suffixed with that index. This is because when we have multiple fields, MaxwellBloch needs to be able to distinguish the arguments of each function. When specifying MaxwellBloch problems, you won't need to worry about this.\n", "\n", "[wiki_functor]: https://en.wikipedia.org/wiki/Function_object" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Square\n", "\n", "The square profile just needs an amplitude `ampl` and switch `on` and `off` times." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(\n", " tlist, t_funcs.square(1)(tlist, args={\"ampl_1\": 1.0, \"on_1\": 0.2, \"off_1\": 0.8})\n", ");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ramp On\n", "\n", "The ramp on and off functions use a Gaussian profile to reach peak amplitude. For example, the `ramp_on` function is\n", "\n", "$$\n", "\\Omega(t) = \n", "\\begin{cases}\n", "\\Omega_0 \\exp \\left[ -4 \\log 2 \\left( \\frac{t - t_0}{t_w}\n", "\\right)^2 \\right] & t < t_0\\\\\n", "\\Omega_0 & t \\ge t_0\n", "\\end{cases}\n", "$$\n", " \n", "where $t_0$ (`centre_1`) is the point at which the function reaches its peak amplitude\n", "$\\Omega_0$ (`ampl_1`). The duration of the ramp-on is governed by $t_w$ (`fwhm_1`), which is\n", "the full width at half maximum (FWHM) of a Gaussian. The `ramp_off`, `ramp_onoff` and `ramp_offon` functions behave in the same way." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(\n", " tlist, t_funcs.ramp_on(1)(tlist, args={\"ampl_1\": 1.0, \"fwhm_1\": 0.1, \"on_1\": 0.6})\n", ");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ramp Off" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(\n", " tlist, t_funcs.ramp_off(1)(tlist, args={\"ampl_1\": 1.0, \"fwhm_1\": 0.1, \"off_1\": 0.6})\n", ");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ramp On and Off" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(\n", " tlist,\n", " t_funcs.ramp_onoff(1)(\n", " tlist, args={\"ampl_1\": 1.0, \"fwhm_1\": 0.1, \"on_1\": 0.4, \"off_1\": 0.6}\n", " ),\n", ");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ramp Off and On" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(\n", " tlist,\n", " t_funcs.ramp_offon(1)(\n", " tlist, args={\"ampl_1\": 1.0, \"fwhm_1\": 0.1, \"off_1\": 0.2, \"on_1\": 0.8}\n", " ),\n", ");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Sech\n", "\n", "\n", "The hyperbolic secant (sech) function is defined by\n", "\n", "$$\n", "\\Omega_0 \\textrm{sech}\\left(\\frac{t - t_0}{t_w}\\right)\n", "$$\n", "\n", "where $t_0$ (`centre_1`) is the point at which the function reaches its peak amplitude\n", "$\\Omega_0$ (`ampl_1`). The width is governed by $t_w$ (`width_1`)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(\n", " tlist, t_funcs.sech(1)(tlist, args={\"ampl_1\": 1.0, \"width_1\": 0.1, \"centre_1\": 0.5})\n", ");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Sinc\n", "\n", "The cardinal sine (sinc) function is defined by\n", "\n", "$$\n", "\\Omega_0 \\textrm{sinc} \\left( \\frac{w t}{\\sqrt{\\pi/2}} \\right)\n", "$$\n", "\n", "where $w$ is a width function and $\\Omega_0$ (`ampl_1`) is the peak amplitude of the function." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(tlist, t_funcs.sinc(1)(tlist, args={\"ampl_1\": 1.0, \"width_1\": 10.0}));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Combining Time Functions\n", "\n", "It is possible to create your own time functions, or combine the built-in time functions. To do this you have to pass the function into the Field object directly, it's not possible to specify in JSON." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = lambda t, args: t_funcs.gaussian(1)(t, args) + t_funcs.ramp_onoff(2)(t, args)\n", "plt.plot(\n", " tlist,\n", " f(\n", " tlist,\n", " args={\n", " \"ampl_1\": 1.0,\n", " \"fwhm_1\": 0.1,\n", " \"centre_1\": 0.2,\n", " \"ampl_2\": 0.6,\n", " \"fwhm_2\": 0.1,\n", " \"on_2\": 0.6,\n", " \"off_2\": 0.8,\n", " },\n", " ),\n", ");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "g = lambda t, args: (\n", " t_funcs.gaussian(1)(t, args)\n", " + t_funcs.gaussian(2)(t, args)\n", " + t_funcs.gaussian(3)(t, args)\n", " + t_funcs.gaussian(4)(t, args)\n", ")\n", "plt.plot(\n", " tlist,\n", " g(\n", " tlist,\n", " args={\n", " \"ampl_1\": 1.0,\n", " \"fwhm_1\": 0.05,\n", " \"centre_1\": 0.2,\n", " \"ampl_2\": 0.8,\n", " \"fwhm_2\": 0.05,\n", " \"centre_2\": 0.4,\n", " \"ampl_3\": 0.6,\n", " \"fwhm_3\": 0.05,\n", " \"centre_3\": 0.6,\n", " \"ampl_4\": 0.4,\n", " \"fwhm_4\": 0.05,\n", " \"centre_4\": 0.8,\n", " },\n", " ),\n", ");" ] } ], "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.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }