{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# `QobjEvo`: time-dependent quantum objects\n", "Made by Eric Giguere, updated by Jake Lishman" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Basic setup\n", "import qutip\n", "import numpy as np\n", "size = 4\n", "t = 1.0\n", "a = qutip.destroy(size)\n", "ad = qutip.create(size)\n", "n = qutip.num(size)\n", "I = qutip.qeye(size)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Contents\n", "\n", "- [Motivation](#Motivation)\n", "- [Instantiation](#Instantiation)\n", " * [Functional time dependence](#Function-time-dependence)\n", " * [String time dependence](#String-time-dependence)\n", " * [Array dependence](#Array-dependence)\n", "- [Evaluation](#Evaluation)\n", "- [Compilation](#Compilation)\n", "- [Arguments](#Arguments)\n", " * [Function form](#Function-form)\n", " * [String form](#String-form)\n", " * [Using objects](#Using-objects)\n", " * [Dynamic arguments](#Dynamic-arguments)\n", "- [Mathematics](#Mathematics)\n", "- [Superoperators](#Superoperators)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Motivation\n", "A `Qobj` is a generic quantum object, but it only represents constant objects. When we need to represent time-dependent objects, the relevant functions take a list of `(Qobj, )` tuples, where the time dependence is a function, a string or an array. Inside the function, this is then converted into a new, time-dependent class `QobjEvo`. We then use this for several compilation and optimisation steps to ensure that the solvers run quickly.\n", "\n", "You do not _need_ to use `QobjEvo`, but if you are planning to reuse some large operators for a long-running integration, you can instantiate one yourself and manually call the C compilation methods. This will have a one-off start-up cost of a couple of seconds, but will make all uses of it faster afterwards. This trade-off is often worthwhile if the integration will take over around 15 minutes, even if you do not reuse the object." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Instantiation\n", "\n", "`QobjEvo` is instantiated with the same time-dependent list that is passed to, say, `mesolve`. This doesn't even _have_ to be time dependent, but constant ones will not have significant benefits over varying ones. The three types of scalar time dependence are:\n", " - function\n", " - string\n", " - array\n", "\n", "This can represent objects of the form\n", "$$\n", "A(t) = \\sum_k f_k(t) A_k\n", "$$\n", "where the $f_k(t)$ are time-dependent scalars, and the $A_k$ are constant `Qobj` objects. The list then looks like\n", "```\n", "[A0, [A1, f1], [A2, f2], ...]\n", "```\n", "where all the `Ak` are constant `Qobj`s, and the `fk` are time dependences in one of the available forms.\n", "\n", "It is not recommended to mix formats within one `QobjEvo`, as the available optimisations will typically be reduced." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "constant_form = qutip.QobjEvo([n])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Function time dependence\n", "\n", "This should be a valid Python function with the signature\n", "```python\n", "(t: float, args: dict) -> complex\n", "```\n", "where `t` is the time, `args` is a dictionary containing arguments which you can change without needing a new `QobjEvo`, and the return value is the complex value of $f_k$. We'll look more at `args` later." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def cos_t(t, args):\n", " return np.cos(t)\n", "\n", "function_form = qutip.QobjEvo([n, [a+ad, cos_t]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you need something more complex, such as a state with memory or to build a parametrised set of functions where the arguments will not change once set, you can use a class which implements `__call__`." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "class callable_time_dependence:\n", " def __init__(self, add):\n", " self.add = add\n", " \n", " def __call__(self, t, args):\n", " return self.add + np.cos(t)\n", " \n", "callable_form = qutip.QobjEvo([n, [a+ad, callable_time_dependence(2)]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### String time dependence\n", "\n", "This should be a valid single Python expression that evaluates to a `complex`. Roughly, if you could do `eval(x)` and get a valid `complex`, you will be fine. In addition to `t` being the time, the following symbols are also defined in scope with their usual definitions:\n", "```\n", "sin cos tan asin acos atan\n", "sinh cosh tanh asinh acosh atanh \n", "exp log log10 erf zerf sqrt \n", "real imag conj abs norm arg\n", "proj pi\n", "```\n", "In addition, `np` refers to `numpy` and `spe` to `scipy.special`.\n", "\n", "String dependence can be compiled down to C code if Cython is available (or to pure Python if it isn't). Compiling to C takes a comparatively long time, but if you plan to reuse the same time dependence a lot, this will produce the fastest code." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "string_form = qutip.QobjEvo([n, [a+ad, \"cos(t)\"]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Array dependence\n", "\n", "If the time dependence is particularly costly to compute, you may pass an array containing the value of the functions evaluated at different times, and separately pass the corresponding list of times to the `tlist` keyword argument of the `QobjEvo` constructor. All times inbetween will be interpolated with cubic splines.\n", "\n", "The times in `tlist` must be sorted, but they don't need to be evenly distributed. If you use this for more than one entry, all entries must have the same values for `tlist` (you can only pass one)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "tlist = np.linspace(0, 10, 101)\n", "values = np.cos(tlist)\n", "array_form = qutip.QobjEvo([n, [a+ad, values]], tlist=tlist)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Evaluation\n", "\n", "No matter what type of time dependence was used, or even if only a constant was created, you can always call your `QobjEvo` instance like a function to get the value at that time. This will return a `Qobj`." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 1.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 2.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 3.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[0. 0. 0. 0.]\n", " [0. 1. 0. 0.]\n", " [0. 0. 2. 0.]\n", " [0. 0. 0. 3.]]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "constant_form(2)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & -0.416 & 0.0 & 0.0\\\\-0.416 & 1.0 & -0.589 & 0.0\\\\0.0 & -0.589 & 2.0 & -0.721\\\\0.0 & 0.0 & -0.721 & 3.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[ 0. -0.41614684 0. 0. ]\n", " [-0.41614684 1. -0.5885205 0. ]\n", " [ 0. -0.5885205 2. -0.72078746]\n", " [ 0. 0. -0.72078746 3. ]]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function_form(2)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & 1.584 & 0.0 & 0.0\\\\1.584 & 1.0 & 2.240 & 0.0\\\\0.0 & 2.240 & 2.0 & 2.743\\\\0.0 & 0.0 & 2.743 & 3.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[0. 1.58385316 0. 0. ]\n", " [1.58385316 1. 2.23990662 0. ]\n", " [0. 2.23990662 2. 2.74331415]\n", " [0. 0. 2.74331415 3. ]]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "callable_form(2)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & -0.416 & 0.0 & 0.0\\\\-0.416 & 1.0 & -0.589 & 0.0\\\\0.0 & -0.589 & 2.0 & -0.721\\\\0.0 & 0.0 & -0.721 & 3.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[ 0. -0.41614684 0. 0. ]\n", " [-0.41614684 1. -0.5885205 0. ]\n", " [ 0. -0.5885205 2. -0.72078746]\n", " [ 0. 0. -0.72078746 3. ]]" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "string_form(2)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & -0.416 & 0.0 & 0.0\\\\-0.416 & 1.0 & -0.589 & 0.0\\\\0.0 & -0.589 & 2.0 & -0.721\\\\0.0 & 0.0 & -0.721 & 3.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[ 0. -0.41614684 0. 0. ]\n", " [-0.41614684 1. -0.5885205 0. ]\n", " [ 0. -0.5885205 2. -0.72078746]\n", " [ 0. 0. -0.72078746 3. ]]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "array_form(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Compilation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you have Cython available, `QobjEvo` can compile itself down to C code for speed. This will be most successful with the string format of time dependence. The compilation process is likely to be slow, but afterwards the `QobjEvo` should return values significantly faster.\n", "\n", "Compilation is done with the `QobjEvo.compile()` method, and modifies the object in-place. Calling the same method again will not force a recompilation. This is important for re-using compiled `QobjEvo` objects - the solvers will not need to recompile each time the same object is passed." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & -0.654 & 0.0 & 0.0\\\\-0.654 & 1.0 & -0.924 & 0.0\\\\0.0 & -0.924 & 2.0 & -1.132\\\\0.0 & 0.0 & -1.132 & 3.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[ 0. -0.65364362 0. 0. ]\n", " [-0.65364362 1. -0.92439167 0. ]\n", " [ 0. -0.92439167 2. -1.13214396]\n", " [ 0. 0. -1.13214396 3. ]]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "string_form.compile()\n", "string_form(4)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## Arguments\n", "\n", "Data can be passed to the coefficient functions or strings using an `args` dictionary. In the functional form, this is passed as an explicit parameter. In the string form, `args` acts like additional variable definitions for the scope of the function. In other words, `'x + 2'` will work and return a value if, for example, `args` is `{'x': 1}`. \n", "The keys of `args` should always be strings representing valid Python identifiers (variable names), and they should not begin with an underscore (\\_).\n", "\n", "Values _can_ be any type, but if Cython compilation is used with string dependence, there will be a large performance penalty for using anything other than valid C numeric types (including `complex`), `numpy` arrays, or any object that Cython cannot call natively.\n", "\n", "You can pass `args` directly at instantiation, and these will be used in every call, unless you specifically override them using the `args` keyword argument in the call. The overriding is temporary, and all subsequent calls will use the values given at initialisation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Function form" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}3.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 3.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 3.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 3.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[3. 0. 0. 0.]\n", " [0. 3. 0. 0.]\n", " [0. 0. 3. 0.]\n", " [0. 0. 0. 3.]]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def coeff_with_args(t, args):\n", " return t + args['delta']\n", "\n", "td_args = qutip.QobjEvo([I, coeff_with_args], args={'delta': 1.}) \n", "td_args(2)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}12.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 12.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 12.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 12.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[12. 0. 0. 0.]\n", " [ 0. 12. 0. 0.]\n", " [ 0. 0. 12. 0.]\n", " [ 0. 0. 0. 12.]]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Temporarily overriding the arguments.\n", "td_args(2, args={\"delta\": 10})" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}3.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 3.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 3.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 3.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[3. 0. 0. 0.]\n", " [0. 3. 0. 0.]\n", " [0. 0. 3. 0.]\n", " [0. 0. 0. 3.]]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# A subsequent regular call will still use the args given at initialisation.\n", "td_args(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### String form" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}3.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 3.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 3.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 3.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[3. 0. 0. 0.]\n", " [0. 3. 0. 0.]\n", " [0. 0. 3. 0.]\n", " [0. 0. 0. 3.]]" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "td_args_str = qutip.QobjEvo([I, \"t + delta\"], args={\"delta\": 1.}) \n", "td_args_str(2)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}12.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 12.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 12.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 12.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[12. 0. 0. 0.]\n", " [ 0. 12. 0. 0.]\n", " [ 0. 0. 12. 0.]\n", " [ 0. 0. 0. 12.]]" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "td_args_str(2, args={\"delta\": 10})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using objects\n", "\n", "The argument value need not just be a number. Even Cython-compiled strings can accept functions which Cython can call natively, such as the core `numpy` functions." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}1.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 1.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 1.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 1.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[1. 0. 0. 0.]\n", " [0. 1. 0. 0.]\n", " [0. 0. 1. 0.]\n", " [0. 0. 0. 1.]]" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "td_args_str = qutip.QobjEvo([I, \"f(t)\"], args={'f': np.cos}) \n", "td_args_str.compile()\n", "td_args_str(0.)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}-1.0 & 0.0 & 0.0 & 0.0\\\\0.0 & -1.0 & 0.0 & 0.0\\\\0.0 & 0.0 & -1.0 & 0.0\\\\0.0 & 0.0 & 0.0 & -1.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[-1. 0. 0. 0.]\n", " [ 0. -1. 0. 0.]\n", " [ 0. 0. -1. 0.]\n", " [ 0. 0. 0. -1.]]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "td_args_str(np.pi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Dynamic arguments\n", "\n", "When `QobjEvo` is used in the solvers, certain dynamic arguments will be populated at each iteration, if and only if their names are present in the `args` dictionary used at `QobjEvo` intialisation. The initial values of all of these dynamic arguments will be a representation of `0` in the corresponding type, for example `\"state\"` will be `qzero()` of the correct dimensions.\n", "\n", "There several of these \"magic\" variables, mostly revolving around the state currently being evolved:\n", " - `\"state\"` or `\"state_qobj\"`: a `Qobj` of the current state.\n", " - `\"state_mat\"`: a dense 2D `np.ndarray` of the state as a matrix, similar to `state.full()`\n", " - `\"state_vec\"`: a dense 1D `np.ndarray` of the state as a vector. This only generally makes sense for kets.\n", " - `\"expect_op_\"`: `complex`, where `` is an index into `e_ops`, the current expectation value of `e_ops[n]` (the `<>` should not appear, e.g. `\"expect_op_0\"`).\n", " - `\"collapse\"`: a `list` of `(t: float, n: int)` indicating the time `t` a collapse occurred, and which of `c_ops` caused it. Only present when using `mcsolve`.\n" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\"state\":\n", "Quantum object: dims = [[4], [1]], shape = (4, 1), type = ket\n", "Qobj data =\n", "[[0.]\n", " [0.]\n", " [0.]\n", " [0.]]\n" ] }, { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 0.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[0. 0. 0. 0.]\n", " [0. 0. 0. 0.]\n", " [0. 0. 0. 0.]\n", " [0. 0. 0. 0.]]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "args = {\"state\": None}\n", "\n", "def print_args(t, args):\n", " print(\"\\n\".join([\n", " '\"' + key + '\":\\n' + repr(value)\n", " for key, value in args.items()\n", " ]))\n", " return t\n", "\n", "td_args = qutip.QobjEvo([I, print_args], args=args) \n", "td_args(0)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\"state\":\n", "Quantum object: dims = [[4], [1]], shape = (4, 1), type = ket\n", "Qobj data =\n", "[[0.]\n", " [0.]\n", " [1.]\n", " [0.]]\n" ] }, { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 0.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[0. 0. 0. 0.]\n", " [0. 0. 0. 0.]\n", " [0. 0. 0. 0.]\n", " [0. 0. 0. 0.]]" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The `state` keyword argument is typically unused.\n", "# Here it just simulates being inside a solver at a particular state.\n", "td_args(0, state=qutip.basis(4,2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Mathematics\n", "\n", "`QobjEvo` supports the basic mathematical operations which make sense for time-dependent quantum objects:\n", " - addition of `QobjEvo` and `Qobj`\n", " - subtraction of `QobjEvo` and `Qobj`\n", " - product with `QobjEvo`, `Qobj` or scalars\n", " - division by a scalar\n", " - negation: `-x`\n", " - conjugation: `QobjEvo.conj()`\n", " - adjoint (dagger): `QobjEvo.dag()`\n", " - transpose: `QobjEvo.trans`" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & 2.0 & 0.0 & 0.0\\\\2.0 & 2.0 & 2.828 & 0.0\\\\0.0 & 2.828 & 4.0 & 3.464\\\\0.0 & 0.0 & 3.464 & 6.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = True\n", "Qobj data =\n", "[[0. 2. 0. 0. ]\n", " [2. 2. 2.82842712 0. ]\n", " [0. 2.82842712 4. 3.46410162]\n", " [0. 0. 3.46410162 6. ]]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(array_form * 2)(0)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = False\\begin{equation*}\\left(\\begin{array}{*{11}c}1.0 & 2.0 & 0.0 & 0.0\\\\1.0 & 2.0 & 2.828 & 0.0\\\\0.0 & 1.414 & 3.0 & 3.464\\\\0.0 & 0.0 & 1.732 & 4.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = False\n", "Qobj data =\n", "[[1. 2. 0. 0. ]\n", " [1. 2. 2.82842712 0. ]\n", " [0. 1.41421356 3. 3.46410162]\n", " [0. 0. 1.73205081 4. ]]" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(array_form + 1 + a)(0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Superoperators\n", "\n", "The functions in `qutip.superoperator` can also be used for `QobjEvo`. Of particular importance is `liouvillian`, as `mesolve` can take the Liouvillian as its first argument (and will be faster this way), in place of separated Hamiltonians and collapse operators." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "Quantum object: dims = [[[4], [4]], [[4], [4]]], shape = (16, 16), type = super, isherm = False\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & -1.0j & 0.0 & 0.0 & 1.0j & \\cdots & 0.0 & 0.0 & 0.0 & 0.0 & 0.0\\\\-1.0j & (-0.500-1.0j) & -1.414j & 0.0 & 0.0 & \\cdots & 0.0 & 0.0 & 0.0 & 0.0 & 0.0\\\\0.0 & -1.414j & (-2.0-2.0j) & -1.732j & 0.0 & \\cdots & 0.0 & 0.0 & 0.0 & 0.0 & 0.0\\\\0.0 & 0.0 & -1.732j & (-4.500-3.0j) & 0.0 & \\cdots & 0.0 & 0.0 & 0.0 & 0.0 & 0.0\\\\1.0j & 0.0 & 0.0 & 0.0 & (-0.500+1.0j) & \\cdots & 0.0 & 0.0 & 0.0 & 0.0 & 0.0\\\\\\vdots & \\vdots & \\vdots & \\vdots & \\vdots & \\ddots & \\vdots & \\vdots & \\vdots & \\vdots & \\vdots\\\\0.0 & 0.0 & 0.0 & 0.0 & 0.0 & \\cdots & (-0.500-1.0j) & 0.0 & 0.0 & 0.0 & 1.732j\\\\0.0 & 0.0 & 0.0 & 0.0 & 0.0 & \\cdots & 0.0 & (-4.500+3.0j) & -1.0j & 0.0 & 0.0\\\\0.0 & 0.0 & 0.0 & 0.0 & 0.0 & \\cdots & 0.0 & -1.0j & (-2.0+2.0j) & -1.414j & 0.0\\\\0.0 & 0.0 & 0.0 & 0.0 & 0.0 & \\cdots & 0.0 & 0.0 & -1.414j & (-0.500+1.0j) & -1.732j\\\\0.0 & 0.0 & 0.0 & 0.0 & 0.0 & \\cdots & 1.732j & 0.0 & 0.0 & -1.732j & 0.0\\\\\\end{array}\\right)\\end{equation*}" ], "text/plain": [ "Quantum object: dims = [[[4], [4]], [[4], [4]]], shape = (16, 16), type = super, isherm = False\n", "Qobj data =\n", "[[ 0. +0.j 0. -1.j 0. +0.j 0. +0.j\n", " 0. +1.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j ]\n", " [ 0. -1.j -0.5-1.j 0. -1.41421356j 0. +0.j\n", " 0. +0.j 0. +1.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j ]\n", " [ 0. +0.j 0. -1.41421356j -2. -2.j 0. -1.73205081j\n", " 0. +0.j 0. +0.j 0. +1.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j ]\n", " [ 0. +0.j 0. +0.j 0. -1.73205081j -4.5-3.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +1.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j ]\n", " [ 0. +1.j 0. +0.j 0. +0.j 0. +0.j\n", " -0.5+1.j 0. -1.j 0. +0.j 0. +0.j\n", " 0. +1.41421356j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j ]\n", " [ 0. +0.j 0. +1.j 0. +0.j 0. +0.j\n", " 0. -1.j 0. +0.j 0. -1.41421356j 0. +0.j\n", " 0. +0.j 0. +1.41421356j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j ]\n", " [ 0. +0.j 0. +0.j 0. +1.j 0. +0.j\n", " 0. +0.j 0. -1.41421356j -0.5-1.j 0. -1.73205081j\n", " 0. +0.j 0. +0.j 0. +1.41421356j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j ]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +1.j\n", " 0. +0.j 0. +0.j 0. -1.73205081j -2. -2.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +1.41421356j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j ]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +1.41421356j 0. +0.j 0. +0.j 0. +0.j\n", " -2. +2.j 0. -1.j 0. +0.j 0. +0.j\n", " 0. +1.73205081j 0. +0.j 0. +0.j 0. +0.j ]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +1.41421356j 0. +0.j 0. +0.j\n", " 0. -1.j -0.5+1.j 0. -1.41421356j 0. +0.j\n", " 0. +0.j 0. +1.73205081j 0. +0.j 0. +0.j ]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +1.41421356j 0. +0.j\n", " 0. +0.j 0. -1.41421356j 0. +0.j 0. -1.73205081j\n", " 0. +0.j 0. +0.j 0. +1.73205081j 0. +0.j ]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +1.41421356j\n", " 0. +0.j 0. +0.j 0. -1.73205081j -0.5-1.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +1.73205081j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +1.73205081j 0. +0.j 0. +0.j 0. +0.j\n", " -4.5+3.j 0. -1.j 0. +0.j 0. +0.j ]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +1.73205081j 0. +0.j 0. +0.j\n", " 0. -1.j -2. +2.j 0. -1.41421356j 0. +0.j ]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +1.73205081j 0. +0.j\n", " 0. +0.j 0. -1.41421356j -0.5+1.j 0. -1.73205081j]\n", " [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +1.73205081j\n", " 0. +0.j 0. +0.j 0. -1.73205081j 0. +0.j ]]" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "liouv = qutip.liouvillian(array_form, c_ops=[constant_form])\n", "liouv(0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Epilogue" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "QuTiP: Quantum Toolbox in Python\n", "================================\n", "Copyright (c) QuTiP team 2011 and later.\n", "Original developers: R. J. Johansson & P. D. Nation.\n", "Previous lead developers: Chris Granade & A. Grimsmo.\n", "Current admin team: Alexander Pitchford, Paul D. Nation, Nathan Shammah, Shahnawaz Ahmed, Neill Lambert, Eric Giguère, and Boxi Li\n", "Project Manager: Franco Nori.\n", "Currently developed through wide collaboration. See https://github.com/qutip for details.\n", "\n", "QuTiP Version: 4.6.0.dev0+ef8e601f\n", "Numpy Version: 1.18.1\n", "Scipy Version: 1.2.1\n", "Cython Version: 0.29.17\n", "Matplotlib Version: 3.1.1\n", "Python Version: 3.7.6\n", "Number of CPUs: 2\n", "BLAS Info: OPENBLAS\n", "OPENMP Installed: True\n", "INTEL MKL Ext: False\n", "Platform Info: Darwin (x86_64)\n", "Installation path: /Users/jake/code/qutip/qutip/qutip\n", "==============================================================================\n", "Please cite QuTiP in your publication.\n", "==============================================================================\n", "For your convenience a bibtex reference can be easily generated using `qutip.cite()`\n" ] } ], "source": [ "qutip.about()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Further development notebooks\n", "\n", "These notebooks contain timing information and other advanced (possibly internal) usage of the `QobjEvo` class.\n", "\n", "- [Development usage](../development/development-qobjevo.ipynb)\n", "- [Timings](../development/development-qobjevo-timings.ipynb)\n", "- [Advanced methods](../development/development-qobjevo-adv.ipynb)" ] } ], "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.6" } }, "nbformat": 4, "nbformat_minor": 2 }