This release builds on our ongoing efforts to provide high-performance solvers for the stochastic Schrödinger and stochastic master equations. It also introduces new methods for solving the Lindblad master equation, including higher-order Rouchon methods with adaptive time-stepping, and jump and diffusive Monte Carlo methods (which perform especially well on GPUs!). An important performance issue that we thought had been resolved in the latest release v0.3.2 has also been fixed (multiplication of a sparse qarray by a dense qarray on the left).
Congratulations and welcome to @gitgan78, @derekeverett and @AurelienGauffre, who have made their first contributions to the library! 👏
🔨 Breaking changes
- Renamed
dq.operator_to_vector()
todq.vectorize()
anddq.vector_to_operator()
todq.unvectorize()
.
🚀 Features
-
New
Rouchon2
andRouchon3
methods fordq.mesolve()
with support for adaptive time-stepping! (#967, #968, #986 and #991) These solvers are significantly faster than existing ones when a stiff term is present in the Hamiltonian (e.g.$a^{\dagger 3}a^3$ ) or in a jump operator (e.g.$a^2$ ). For instance, for a stiff$H=a^{\dagger 3}a^3$ , x15 faster thanDopri5
for n=32 and x130 faster for n=64! 🏎️ (fixed rtol/atol precision per step, on a CPU, dense layout) -
New
JumpMonteCarlo
andDiffusiveMonteCarlo
methods fordq.mesolve()
(#952 and #992). -
Stochastic solvers
- Improved the
Event
method fordq.jssesolve()
: added thesmart_sampling
option to sample the no-click trajectory only once (#943 and #956) and thedtmax
parameter to control click times precision (#990). - Added a new
EulerJump
method fordq.jssesolve()
anddq.jsmesolve()
(#956 and #969). - Added the
Rouchon1
method fordq.dssesolve()
.
- Improved the
-
Added forward-mode automatic differentiation support by passing
gradient=dq.gradient.ForwardAutograd()
to solvers, see ForwardAutograd (#945). -
Added support for time-dependent Liouvillian in
dq.mepropagator()
(#953). -
Added
clip()
(#935) andprefactor()
methods to timeqarray (#974). This is the start of a work to ease the simulation of pulse sequencesf = lambda t: jnp.cos(2.0 * jnp.pi * t) H = dq.modulated(f, dq.sigmax()) H_clipped = H.clip(0, 1)
-
Utilities
- Added
dq.plot.wigner_data()
to plot pre-computed wigner functions (#966). - Added
dq.xyz()
utility, which returns the Pauli$\sigma_x$ ,$\sigma_y$ and$\sigma_z$ operators (#972). - Added
dq.thermal_dm()
utility to get the density matrix of a thermal state (#744). - Added
dq.ground_dm()
anddq.excited_dm()
(#977). - Added an
offsets
optional argument todq.asqarray()
to make it JIT-compatible (#954).
- Added
🐛 Bugs
- Fixed matrix multiplication of sparse dia qarray by dense qarray on the left (#973).
- Fixed a bug for modulated time-dependent qarrays preventing specifying functions returning a scalar output (#955).
- Make
method
a non-static argument for all solvers (#951). - Fixed
dq.plot.grid()
for a single subplot (#965). - Fixed the default layout of
dq.eye_like()
anddq.zeros_like()
, which was dense and is now the same as the argument (#979). - Added support for Hermitian matrices in
dq.norm()
and fixed the documentation (#957).
📖 Documentation
-
New advanced tutorial on Continuous jump measurement.
📦 Other changes
- Lifted the deprecated upper JAX version constraint, which was set to
<0.5.3
in the previous release v0.3.2 (#1000).
Full Changelog: v0.3.2...v0.3.3