|
| 1 | +--- |
| 2 | +jupyter: |
| 3 | + jupytext: |
| 4 | + text_representation: |
| 5 | + extension: .md |
| 6 | + format_name: markdown |
| 7 | + format_version: '1.3' |
| 8 | + jupytext_version: 1.13.8 |
| 9 | + kernelspec: |
| 10 | + display_name: Python 3 (ipykernel) |
| 11 | + language: python |
| 12 | + name: python3 |
| 13 | +--- |
| 14 | + |
| 15 | +# Calculate time propagators with Dysolve |
| 16 | + |
| 17 | +Author: Mathis Beaudoin, 2025 |
| 18 | + |
| 19 | +### Introduction |
| 20 | + |
| 21 | +This notebook shows how to compute time propagators with Dysolve using QuTiP. Dysolve is a method to compute time propagators for hamiltonians of the form $H(t) = H_0 + \cos(\omega t)X$ where $H_0$ is some base hamiltonian and $X$ a perturbation. It performs better than other general methods for this class of hamiltonians and, later on, should support more complicated oscillating perturbations. It is still in development with more features to come in the future. For more details on Dysolve, see the corresponding guide in the documentation. |
| 22 | + |
| 23 | +For the moment, Dysolve can be used with the class `DysolvePropagator` and the function `dysolve_propagator` from QuTiP's solvers. They follow a similar structure to the class `Propagator` and the function `propagator`, another solver that also computes time propagators. |
| 24 | + |
| 25 | +Here, we import the necessary packages. |
| 26 | + |
| 27 | +```python |
| 28 | +from qutip.solver.dysolve_propagator import DysolvePropagator, dysolve_propagator |
| 29 | +from qutip.solver.propagator import propagator |
| 30 | +from qutip import qeye, sigmax, sigmay, sigmaz, tensor, CoreOptions, about |
| 31 | +import numpy as np |
| 32 | +``` |
| 33 | + |
| 34 | +### One qubit example using `DysolvePropagator` |
| 35 | + |
| 36 | +We have to define what $H_0$, $X$ and $\omega$ will be. For example, $H(t) = \sigma_z + \cos(10t)\sigma_x$. |
| 37 | + |
| 38 | +```python |
| 39 | +H_0 = sigmaz() |
| 40 | +X = sigmax() |
| 41 | +omega = 10.0 |
| 42 | +``` |
| 43 | + |
| 44 | +Some options can be defined. `max_order` will be the order of approximation used when calculating a propagator. The higher this integer is, the more precise the results will be (at a cost of taking more time to calculate). `a_tol` is simply the absolute tolerance used in the calculations. Finally, a time propagator can be computed using subpropagators of time increment `max_dt`. If `max_dt` is set to 0.25, then the propagator $U(1, 0)$ will come from the multiplication of the supropagators $U(0.25, 0)$, $U(0.5, 0.25)$, $U(0.75, 0.5)$ and $U(1, 0.75)$. This allows for more precise results when the evolution is over a long period of time. In our case, we keep `a_tol` and `max_dt` to their default value, but we change `max_order` to 5. |
| 45 | + |
| 46 | +```python |
| 47 | +options = {'max_order': 5} |
| 48 | +``` |
| 49 | + |
| 50 | +Everything is now defined to initialize an instance. |
| 51 | + |
| 52 | +```python |
| 53 | +dy = DysolvePropagator(H_0, X, omega, options=options) |
| 54 | +``` |
| 55 | + |
| 56 | +Then, to compute a time propagator, simply call the instance with a given initial time and final time. Also, only a final time can be given and, in that case, the initial time is considered to be 0. |
| 57 | + |
| 58 | +```python |
| 59 | +t_i = -1 |
| 60 | +t_f = 1 |
| 61 | +U = dy(t_f, t_i) |
| 62 | +``` |
| 63 | + |
| 64 | +This returns a single time propagator $U(t_f = 1, t_i = -1)$. To verify that the $U$ is correct, we compare it to what `propagator` would return. |
| 65 | + |
| 66 | +```python |
| 67 | +# Solve using propagator |
| 68 | +def X_coeff(t, omega): |
| 69 | + return np.cos(omega * t) |
| 70 | + |
| 71 | +H = [H_0, [X, X_coeff]] |
| 72 | +args = {'omega': omega} |
| 73 | +prop = propagator( |
| 74 | + H, [t_i, t_f], args=args, options={"atol": 1e-10, "rtol": 1e-8} |
| 75 | +) |
| 76 | + |
| 77 | +# Comparison |
| 78 | +with CoreOptions(atol=1e-10, rtol=1e-6): |
| 79 | + assert U == prop[1] |
| 80 | +``` |
| 81 | + |
| 82 | +### Two qubits example with `dysolve_propagator` |
| 83 | + |
| 84 | +We proceed like the previous example. |
| 85 | + |
| 86 | +```python |
| 87 | +# Define the system |
| 88 | +H_0 = tensor(sigmax(), sigmaz()) + tensor(qeye(2), sigmay()) |
| 89 | +X = tensor(qeye(2), sigmaz()) |
| 90 | +omega = 5.0 |
| 91 | + |
| 92 | +# Keep options to default |
| 93 | +``` |
| 94 | + |
| 95 | +`dysolve_propagator` can take more than one time value. If a single time is passed, a single propagator $U(t,0)$ is returned. If a list of times is given, the function will return a list of propagator $[U(\text{times}[i], \text{times}[0])]$ for all $i$. |
| 96 | + |
| 97 | +```python |
| 98 | +times = [-0.1, 0, 0.1] |
| 99 | +Us = dysolve_propagator(H_0, X, omega, times) |
| 100 | +``` |
| 101 | + |
| 102 | +Again, we compare the results with `propagator`. |
| 103 | + |
| 104 | +```python |
| 105 | +# Solve using propagator |
| 106 | +def X_coeff(t, omega): |
| 107 | + return np.cos(omega * t) |
| 108 | + |
| 109 | +H = [H_0, [X, X_coeff]] |
| 110 | +args = {'omega': omega} |
| 111 | +props = propagator( |
| 112 | + H, times, args=args, options={"atol": 1e-10, "rtol": 1e-8} |
| 113 | +) |
| 114 | + |
| 115 | +# Comparison |
| 116 | +with CoreOptions(atol=1e-10, rtol=1e-6): |
| 117 | + assert Us == props |
| 118 | +``` |
| 119 | + |
| 120 | +### About |
| 121 | + |
| 122 | +```python |
| 123 | +about() |
| 124 | +``` |
0 commit comments