2022-03-18 15:34:49 +01:00
|
|
|
|
r"""
|
|
|
|
|
Operators for a general model of one qubit coupled to a single bath.
|
|
|
|
|
The energy scale is the characteristic energy of the qubit :math:`ω =
|
|
|
|
|
1`.
|
|
|
|
|
|
|
|
|
|
The total hamiltonian has the form
|
|
|
|
|
|
|
|
|
|
.. math::
|
|
|
|
|
|
|
|
|
|
H=\frac{1}{2}σ_z
|
|
|
|
|
+ \sqrt{δ} ∑_λ (L^† g_λ b^i_λ + L g_λ^\ast b^{i,†}_λ) + H_B.
|
|
|
|
|
|
|
|
|
|
The BCF is normalized so that the integral over its imaginary part is
|
|
|
|
|
:math:`-1`. The bath coupling strength is divided by :math:`\langle
|
|
|
|
|
L L^†\rangle 2` with respect to the inital state to normalize the
|
|
|
|
|
interaction energy to about the order of :math:`ω=1`.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from dataclasses import dataclass, field
|
2022-03-21 13:40:38 +01:00
|
|
|
|
import hopsflow
|
2022-03-18 15:34:49 +01:00
|
|
|
|
from numpy.typing import NDArray
|
2022-06-01 17:00:08 +02:00
|
|
|
|
from typing import Any, Optional, SupportsFloat, Union
|
2022-03-18 15:34:49 +01:00
|
|
|
|
import hops.util.bcf
|
|
|
|
|
import hops.util.bcf_fits
|
|
|
|
|
import hops.core.hierarchy_parameters as params
|
|
|
|
|
import numpy as np
|
|
|
|
|
import qutip as qt
|
|
|
|
|
from hops.util.abstract_truncation_scheme import TruncationScheme_Simplex
|
|
|
|
|
from hops.util.truncation_schemes import (
|
|
|
|
|
TruncationScheme_Power_multi,
|
|
|
|
|
BathMemory,
|
|
|
|
|
)
|
|
|
|
|
import stocproc as sp
|
|
|
|
|
|
|
|
|
|
from beartype import beartype
|
2022-04-20 11:41:21 +02:00
|
|
|
|
from .utility import StocProcTolerances, bcf_scale
|
2022-03-22 10:25:58 +01:00
|
|
|
|
from .model_base import Model
|
2022-03-18 15:34:49 +01:00
|
|
|
|
import scipy.special
|
2022-03-21 13:40:38 +01:00
|
|
|
|
import hopsflow
|
2022-04-06 18:28:53 +02:00
|
|
|
|
from hops.util.dynamic_matrix import DynamicMatrix, ConstantMatrix
|
2022-03-18 15:34:49 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@beartype
|
|
|
|
|
@dataclass(eq=False)
|
|
|
|
|
class QubitModel(Model):
|
|
|
|
|
"""
|
|
|
|
|
A class to dynamically calculate all the one qubit model parameters and
|
|
|
|
|
generate the HOPS configuration.
|
|
|
|
|
|
|
|
|
|
All attributes can be changed after initialization.
|
|
|
|
|
"""
|
|
|
|
|
|
2022-04-06 18:28:53 +02:00
|
|
|
|
__version__: int = 2
|
2022-03-21 13:45:05 +01:00
|
|
|
|
|
2022-03-18 15:34:49 +01:00
|
|
|
|
δ: SupportsFloat = 0.1
|
|
|
|
|
"""The bath coupling factor."""
|
|
|
|
|
|
2022-08-23 15:13:50 +02:00
|
|
|
|
bcf_norm_method: str = field(default_factory=lambda: "pure_dephasing")
|
|
|
|
|
r"""The normalization of the bath correlation function.
|
|
|
|
|
|
|
|
|
|
- `"pure dephasing"` corresponds to :math:`\Im ∫_0^∞ α(τ) dτ = -1`
|
|
|
|
|
- `"unit"` corresponds to :math:`α(0)=1` (zero temperature BCF)
|
|
|
|
|
- `"unit_therm"` corresponds to :math:`α_β(0)=1`
|
|
|
|
|
- `"sd_peak"` corresponds to :math:`\max_ω J(ω)=1` (zero temperature SD)
|
|
|
|
|
- `"sd_peak_therm"` corresponds to :math:`\max_ω J_β(ω)=1`
|
|
|
|
|
"""
|
|
|
|
|
|
2022-03-18 15:34:49 +01:00
|
|
|
|
ω_c: SupportsFloat = 2
|
|
|
|
|
"""The cutoff frequency :math:`ω_c`."""
|
|
|
|
|
|
2022-06-01 17:00:08 +02:00
|
|
|
|
ω_s: SupportsFloat = 0
|
|
|
|
|
"""The SD shift frequency :math:`ω_s`."""
|
|
|
|
|
|
|
|
|
|
therm_method: str = "tanhsinh"
|
|
|
|
|
"""
|
|
|
|
|
The method used for the thermal stochastic process. Either
|
|
|
|
|
``tanhsinh`` or ``fft``.
|
|
|
|
|
"""
|
|
|
|
|
|
2022-03-18 15:34:49 +01:00
|
|
|
|
s: SupportsFloat = 1
|
|
|
|
|
"""The BCF s parameter."""
|
|
|
|
|
|
2022-04-06 18:28:53 +02:00
|
|
|
|
L: DynamicMatrix = field(default_factory=lambda: ConstantMatrix(1 / 2 * qt.sigmax().full())) # type: ignore
|
2022-03-18 15:34:49 +01:00
|
|
|
|
"""
|
|
|
|
|
The :math:`L` coupling operator with shape ``(2, 2)``.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
T: SupportsFloat = 0
|
|
|
|
|
"""The temperature of the bath."""
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
|
# HOPS Parameters #
|
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
|
|
description: str = ""
|
|
|
|
|
"""A free-form description of the model instance."""
|
|
|
|
|
|
|
|
|
|
bcf_terms: int = 5
|
|
|
|
|
"""How many bcf terms to use in the expansions of the BCF."""
|
|
|
|
|
|
|
|
|
|
ψ_0: qt.Qobj = qt.basis([2], [1])
|
|
|
|
|
"""The initial state."""
|
|
|
|
|
|
2022-04-06 18:28:53 +02:00
|
|
|
|
t: NDArray[np.float64] = np.linspace(0, 10, 1000)
|
|
|
|
|
"""The simulation time points."""
|
2022-03-18 15:34:49 +01:00
|
|
|
|
|
|
|
|
|
k_fac: SupportsFloat = 1.7
|
|
|
|
|
"""The k_fac parameters for the truncation scheme.
|
|
|
|
|
|
|
|
|
|
See
|
|
|
|
|
:any:`hops.util.truncation_schemes.TruncationScheme_Power_multi`.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
k_max: int = 10
|
|
|
|
|
"""The kmax parameter for the truncation scheme.
|
|
|
|
|
|
|
|
|
|
See
|
|
|
|
|
:any:`hops.util.abstract_truncation_scheme.TruncationScheme_Simplex`
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
influence_tolerance: SupportsFloat = 1e-2
|
|
|
|
|
"""The ``influecne_tolerance`` parameter for the truncation
|
|
|
|
|
scheme.
|
|
|
|
|
|
|
|
|
|
See :any:`hops.util.truncation_schemes.BathMemory`.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
truncation_scheme: str = "bath_memory"
|
|
|
|
|
"""The truncation scheme to use."""
|
|
|
|
|
|
|
|
|
|
solver_args: dict[str, Any] = field(default_factory=dict)
|
|
|
|
|
"""Extra arguments for :any:`scipy.integrate.solve_ivp`."""
|
|
|
|
|
|
|
|
|
|
driving_process_tolerance: StocProcTolerances = field(
|
|
|
|
|
default_factory=lambda: StocProcTolerances()
|
|
|
|
|
)
|
|
|
|
|
"""
|
|
|
|
|
The integration and interpolation tolerance for the driving
|
|
|
|
|
processes.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
thermal_process_tolerance: StocProcTolerances = field(
|
|
|
|
|
default_factory=lambda: StocProcTolerances()
|
|
|
|
|
)
|
|
|
|
|
"""
|
|
|
|
|
The integration and interpolation tolerance for the thermal noise
|
|
|
|
|
processes.
|
|
|
|
|
"""
|
|
|
|
|
|
2022-04-12 18:22:54 +02:00
|
|
|
|
H: DynamicMatrix = field(
|
|
|
|
|
default_factory=lambda: ConstantMatrix(1 / 2 * qt.sigmaz().full())
|
|
|
|
|
) # type: ignore
|
|
|
|
|
"""
|
|
|
|
|
The system hamiltonian :math:`H` with shape ``(2, 2)``.
|
|
|
|
|
"""
|
|
|
|
|
|
2022-03-21 13:40:38 +01:00
|
|
|
|
@property
|
2022-04-06 18:28:53 +02:00
|
|
|
|
def coupling_operators(self) -> list[DynamicMatrix]:
|
2022-03-21 13:40:38 +01:00
|
|
|
|
"""The bath coupling operators :math:`L`."""
|
2022-04-06 18:28:53 +02:00
|
|
|
|
|
|
|
|
|
return [self.L]
|
2022-03-21 13:40:38 +01:00
|
|
|
|
|
2022-03-18 15:34:49 +01:00
|
|
|
|
@property
|
2022-04-12 18:22:54 +02:00
|
|
|
|
def system(self) -> DynamicMatrix:
|
2022-03-18 15:34:49 +01:00
|
|
|
|
"""The system hamiltonian."""
|
|
|
|
|
|
2022-04-12 18:22:54 +02:00
|
|
|
|
return self.H # type: ignore
|
2022-03-18 15:34:49 +01:00
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def bcf_norm(self) -> float:
|
|
|
|
|
"""The normalization factor for the BCF.
|
|
|
|
|
It is not used when generating the stochastic process due to
|
|
|
|
|
numerical reasons. It is being incorporated into the
|
|
|
|
|
:any:`bcf_scale`.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
np.pi
|
|
|
|
|
* float(self.s)
|
|
|
|
|
/ (
|
|
|
|
|
scipy.special.gamma(float(self.s) + 1)
|
|
|
|
|
* float(self.ω_c) ** float(self.s)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
2022-08-23 15:13:50 +02:00
|
|
|
|
@property
|
|
|
|
|
def full_thermal_spectral_density(self):
|
|
|
|
|
"""
|
|
|
|
|
:returns: The full thermal spectral density.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if self.T == 0:
|
|
|
|
|
return self.spectral_density
|
|
|
|
|
|
|
|
|
|
def thermal_sd(ω):
|
|
|
|
|
return self.spectral_density(ω) * (
|
|
|
|
|
1 / (np.expm1(ω / self.T)) + np.heaviside(ω, 0)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return thermal_sd
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def full_thermal_bcf(self):
|
|
|
|
|
"""
|
|
|
|
|
:returns: The full thermal bath correlation function.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if self.T == 0:
|
|
|
|
|
return self.bcf
|
|
|
|
|
|
|
|
|
|
def thermal_bcf(t):
|
|
|
|
|
return self.bcf(t) + 2 * (self.thermal_correlations(t).real)
|
|
|
|
|
|
|
|
|
|
return thermal_bcf
|
|
|
|
|
|
2022-03-23 12:55:37 +01:00
|
|
|
|
@property
|
|
|
|
|
def bcf_scale(self) -> float:
|
|
|
|
|
"""
|
2022-05-16 20:53:29 +02:00
|
|
|
|
The scaling factor of the BCF.
|
2022-03-23 12:55:37 +01:00
|
|
|
|
"""
|
|
|
|
|
|
2022-08-23 15:13:50 +02:00
|
|
|
|
if self.bcf_norm_method == "pure_dephasing":
|
|
|
|
|
return bcf_scale(self.δ, self.L, self.t.max(), self.s, self.ω_c)
|
|
|
|
|
|
|
|
|
|
if self.bcf_norm_method == "unit":
|
|
|
|
|
return float(self.δ) / self.bcf(0).real
|
|
|
|
|
|
|
|
|
|
if self.bcf_norm_method == "unit_therm":
|
|
|
|
|
return float(self.δ) / self.full_thermal_bcf(0).real
|
|
|
|
|
|
|
|
|
|
if self.bcf_norm_method == "sd_peak":
|
|
|
|
|
return (
|
|
|
|
|
float(self.δ) / self.spectral_density(self.ω_c * self.s + self.ω_s).real
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if self.bcf_norm_method == "sd_peak_therm":
|
|
|
|
|
return (
|
|
|
|
|
float(self.δ)
|
|
|
|
|
/ self.full_thermal_spectral_density(self.ω_c * self.s + self.ω_s).real
|
|
|
|
|
)
|
2022-03-21 13:40:38 +01:00
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def bcf_scales(self) -> list[float]:
|
|
|
|
|
"""The scaling factors for the bath correlation functions."""
|
|
|
|
|
|
|
|
|
|
return [self.bcf_scale]
|
2022-03-18 15:34:49 +01:00
|
|
|
|
|
|
|
|
|
@property
|
2022-06-01 17:00:08 +02:00
|
|
|
|
def bcf(self) -> Union[hops.util.bcf.OhmicBCF_zeroTemp, hops.util.bcf.ShiftedBCF]:
|
2022-03-18 15:34:49 +01:00
|
|
|
|
"""
|
|
|
|
|
The normalized zero temperature BCF.
|
|
|
|
|
"""
|
|
|
|
|
|
2022-06-01 17:00:08 +02:00
|
|
|
|
bcf = hops.util.bcf.OhmicBCF_zeroTemp(
|
2022-03-18 15:34:49 +01:00
|
|
|
|
s=self.s, eta=1, w_c=self.ω_c, normed=False
|
|
|
|
|
)
|
|
|
|
|
|
2022-06-01 17:00:08 +02:00
|
|
|
|
if float(self.ω_s) > 0:
|
|
|
|
|
return hops.util.bcf.ShiftedBCF(bcf, float(self.ω_s))
|
|
|
|
|
|
|
|
|
|
return bcf
|
|
|
|
|
|
2022-03-18 15:34:49 +01:00
|
|
|
|
@property
|
2022-06-01 17:00:08 +02:00
|
|
|
|
def spectral_density(
|
|
|
|
|
self,
|
|
|
|
|
) -> Union[hops.util.bcf.OhmicSD_zeroTemp, hops.util.bcf.ShiftedSD]:
|
2022-03-18 15:34:49 +01:00
|
|
|
|
"""
|
|
|
|
|
The normalized zero temperature spectral density.
|
|
|
|
|
"""
|
|
|
|
|
|
2022-06-01 17:00:08 +02:00
|
|
|
|
sd = hops.util.bcf.OhmicSD_zeroTemp(
|
2022-03-18 15:34:49 +01:00
|
|
|
|
s=float(self.s),
|
|
|
|
|
w_c=float(self.ω_c),
|
|
|
|
|
eta=1,
|
|
|
|
|
normed=False,
|
|
|
|
|
)
|
|
|
|
|
|
2022-06-01 17:00:08 +02:00
|
|
|
|
if float(self.ω_s) > 0:
|
|
|
|
|
return hops.util.bcf.ShiftedSD(sd, float(self.ω_s))
|
|
|
|
|
|
|
|
|
|
return sd
|
|
|
|
|
|
2022-03-18 15:34:49 +01:00
|
|
|
|
@property
|
|
|
|
|
def thermal_correlations(
|
|
|
|
|
self,
|
2022-06-01 17:00:08 +02:00
|
|
|
|
) -> Union[
|
|
|
|
|
Optional[hops.util.bcf.Ohmic_StochasticPotentialCorrelations],
|
|
|
|
|
hops.util.bcf.ShiftedBCF,
|
|
|
|
|
]:
|
2022-03-18 15:34:49 +01:00
|
|
|
|
"""
|
|
|
|
|
The normalized thermal noise corellation function.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if self.T == 0:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
return hops.util.bcf.Ohmic_StochasticPotentialCorrelations(
|
|
|
|
|
s=self.s,
|
|
|
|
|
eta=1,
|
|
|
|
|
w_c=self.ω_c,
|
|
|
|
|
normed=False,
|
|
|
|
|
beta=1 / float(self.T),
|
2022-06-01 17:00:08 +02:00
|
|
|
|
shift=float(self.ω_s),
|
2022-03-18 15:34:49 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def thermal_spectral_density(
|
|
|
|
|
self,
|
|
|
|
|
) -> Optional[hops.util.bcf.Ohmic_StochasticPotentialDensity]:
|
|
|
|
|
"""
|
|
|
|
|
The normalized thermal noise spectral density.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if self.T == 0:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
return hops.util.bcf.Ohmic_StochasticPotentialDensity(
|
|
|
|
|
s=self.s,
|
|
|
|
|
eta=1,
|
|
|
|
|
w_c=self.ω_c,
|
|
|
|
|
normed=False,
|
|
|
|
|
beta=1.0 / float(self.T),
|
2022-06-01 17:00:08 +02:00
|
|
|
|
shift=float(self.ω_s),
|
2022-03-18 15:34:49 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def bcf_coefficients(
|
|
|
|
|
self, n: Optional[int] = None
|
2022-03-21 13:40:38 +01:00
|
|
|
|
) -> tuple[list[NDArray[np.complex128]], list[NDArray[np.complex128]]]:
|
2022-03-18 15:34:49 +01:00
|
|
|
|
"""
|
|
|
|
|
The normalizedzero temperature BCF fit coefficients
|
|
|
|
|
:math:`G_i,W_i` with ``n`` terms.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
n = n or self.bcf_terms
|
2022-03-21 13:40:38 +01:00
|
|
|
|
g, w = self.bcf.exponential_coefficients(n)
|
|
|
|
|
return ([g], [w])
|
2022-03-18 15:34:49 +01:00
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def basis(n: int = 1) -> qt.Qobj:
|
|
|
|
|
"""
|
|
|
|
|
A state with of the qubit in the state state ``n`` where ``1``
|
|
|
|
|
means down and ``0`` means up.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
return qt.basis([2], [n])
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def driving_process(self) -> sp.StocProc:
|
|
|
|
|
"""The driving stochastic process of the ``i``th bath."""
|
|
|
|
|
|
|
|
|
|
return sp.StocProc_FFT(
|
|
|
|
|
spectral_density=self.spectral_density,
|
|
|
|
|
alpha=self.bcf,
|
2022-04-06 18:28:53 +02:00
|
|
|
|
t_max=self.t.max(),
|
2022-03-18 15:34:49 +01:00
|
|
|
|
intgr_tol=self.driving_process_tolerance.integration,
|
|
|
|
|
intpl_tol=self.driving_process_tolerance.interpolation,
|
|
|
|
|
negative_frequencies=False,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def thermal_process(self) -> Optional[sp.StocProc]:
|
2022-03-21 13:40:38 +01:00
|
|
|
|
"""The thermal noise stochastic process."""
|
2022-03-18 15:34:49 +01:00
|
|
|
|
|
|
|
|
|
if self.T == 0:
|
|
|
|
|
return None
|
|
|
|
|
|
2022-06-01 17:00:08 +02:00
|
|
|
|
return (
|
2022-06-08 15:25:34 +02:00
|
|
|
|
sp.StocProc_TanhSinh if self.therm_method == "tanhsinh" else sp.StocProc_FFT
|
2022-06-01 17:00:08 +02:00
|
|
|
|
)(
|
2022-03-18 15:34:49 +01:00
|
|
|
|
spectral_density=self.thermal_spectral_density,
|
|
|
|
|
alpha=self.thermal_correlations,
|
2022-04-06 18:28:53 +02:00
|
|
|
|
t_max=self.t.max(),
|
2022-03-18 15:34:49 +01:00
|
|
|
|
intgr_tol=self.thermal_process_tolerance.integration,
|
|
|
|
|
intpl_tol=self.thermal_process_tolerance.interpolation,
|
|
|
|
|
negative_frequencies=False,
|
|
|
|
|
)
|
|
|
|
|
|
2022-03-21 13:40:38 +01:00
|
|
|
|
@property
|
|
|
|
|
def thermal_processes(self) -> list[Optional[hopsflow.hopsflow.StocProc]]:
|
|
|
|
|
"""
|
|
|
|
|
The thermal noise stochastic processes for each bath.
|
|
|
|
|
:any:`None` means zero temperature.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
return [self.thermal_process]
|
|
|
|
|
|
2022-03-18 15:34:49 +01:00
|
|
|
|
###########################################################################
|
|
|
|
|
# Utility #
|
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
|
|
@property
|
2022-03-21 14:55:52 +01:00
|
|
|
|
def hops_config(self) -> params.HIParams:
|
2022-03-18 15:34:49 +01:00
|
|
|
|
"""
|
|
|
|
|
The hops :any:`hops.core.hierarchy_params.HIParams` parameter object
|
|
|
|
|
for this system.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
g, w = self.bcf_coefficients(self.bcf_terms)
|
|
|
|
|
|
|
|
|
|
system = params.SysP(
|
2022-04-12 18:22:54 +02:00
|
|
|
|
H_sys=self.system,
|
2022-04-06 18:28:53 +02:00
|
|
|
|
L=self.coupling_operators,
|
2022-03-21 13:40:38 +01:00
|
|
|
|
g=g,
|
|
|
|
|
w=w,
|
2022-03-18 15:34:49 +01:00
|
|
|
|
bcf_scale=[self.bcf_scale],
|
|
|
|
|
T=[self.T],
|
|
|
|
|
description=self.description,
|
|
|
|
|
psi0=self.ψ_0.full().flatten(),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if self.truncation_scheme == "bath_memory":
|
|
|
|
|
trunc_scheme = BathMemory.from_system(
|
|
|
|
|
system,
|
|
|
|
|
nonlinear=True,
|
|
|
|
|
influence_tolerance=float(self.influence_tolerance),
|
|
|
|
|
)
|
|
|
|
|
|
2022-03-23 12:55:37 +01:00
|
|
|
|
elif self.truncation_scheme == "simplex":
|
2022-03-18 15:34:49 +01:00
|
|
|
|
trunc_scheme = TruncationScheme_Simplex(self.k_max)
|
|
|
|
|
|
2022-03-23 12:55:37 +01:00
|
|
|
|
else:
|
|
|
|
|
trunc_scheme = TruncationScheme_Power_multi.from_g_w(
|
|
|
|
|
g=system.g,
|
|
|
|
|
w=system.w,
|
|
|
|
|
p=[1, 1],
|
|
|
|
|
q=[0.5, 0.5],
|
|
|
|
|
kfac=[float(self.k_fac)],
|
|
|
|
|
)
|
|
|
|
|
|
2022-03-18 15:34:49 +01:00
|
|
|
|
hierarchy = params.HiP(
|
|
|
|
|
seed=0,
|
|
|
|
|
nonlinear=True,
|
|
|
|
|
terminator=False,
|
|
|
|
|
result_type=params.ResultType.ZEROTH_AND_FIRST_ORDER,
|
|
|
|
|
accum_only=False,
|
|
|
|
|
rand_skip=None,
|
|
|
|
|
truncation_scheme=trunc_scheme,
|
|
|
|
|
save_therm_rng_seed=True,
|
|
|
|
|
auto_normalize=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
default_solver_args = dict(rtol=1e-8, atol=1e-8)
|
|
|
|
|
default_solver_args.update(self.solver_args)
|
|
|
|
|
|
2022-04-06 18:28:53 +02:00
|
|
|
|
integration = params.IntP(t=self.t, **default_solver_args)
|
2022-03-18 15:34:49 +01:00
|
|
|
|
|
|
|
|
|
return params.HIParams(
|
|
|
|
|
SysP=system,
|
|
|
|
|
IntP=integration,
|
|
|
|
|
HiP=hierarchy,
|
|
|
|
|
Eta=[self.driving_process],
|
|
|
|
|
EtaTherm=[self.thermal_process],
|
|
|
|
|
)
|
2022-04-20 11:41:21 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@beartype
|
|
|
|
|
@dataclass(eq=False)
|
|
|
|
|
class QubitModelMutliBath(Model):
|
|
|
|
|
"""
|
|
|
|
|
A class to dynamically calculate all the one qubit model
|
|
|
|
|
parameters and generate the HOPS configuration. Like
|
|
|
|
|
:any:`QubitModel` but supports multiple baths.
|
|
|
|
|
|
|
|
|
|
All attributes can be changed after initialization.
|
|
|
|
|
"""
|
|
|
|
|
|
2022-06-08 15:25:34 +02:00
|
|
|
|
__version__: int = 2
|
2022-04-20 11:41:21 +02:00
|
|
|
|
|
|
|
|
|
δ: list[SupportsFloat] = field(default_factory=lambda: [0.1] * 2)
|
|
|
|
|
"""The bath coupling factors."""
|
|
|
|
|
|
|
|
|
|
ω_c: list[SupportsFloat] = field(default_factory=lambda: [2] * 2)
|
|
|
|
|
"""The cutoff frequencies :math:`ω_c`."""
|
|
|
|
|
|
|
|
|
|
s: list[SupportsFloat] = field(default_factory=lambda: [1] * 2)
|
|
|
|
|
"""The BCF s parameter."""
|
|
|
|
|
|
2022-06-08 15:25:34 +02:00
|
|
|
|
ω_s: list[SupportsFloat] = field(default_factory=lambda: [0] * 2)
|
|
|
|
|
"""The SD shift frequencies :math:`ω_s`."""
|
|
|
|
|
|
|
|
|
|
therm_methods: list[str] = field(default_factory=lambda: ["tanhsinh"] * 2)
|
|
|
|
|
"""
|
|
|
|
|
The methods used for the thermal stochastic process. Either
|
|
|
|
|
``tanhsinh`` or ``fft``.
|
|
|
|
|
"""
|
|
|
|
|
|
2022-04-20 11:41:21 +02:00
|
|
|
|
L: list[DynamicMatrix] = field(default_factory=lambda: [ConstantMatrix(1 / 2 * qt.sigmax().full())] * 2) # type: ignore
|
|
|
|
|
"""
|
|
|
|
|
The :math:`L` coupling operators with shape ``(2, 2)``.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
T: list[SupportsFloat] = field(default_factory=lambda: [0] * 2)
|
|
|
|
|
"""The temperatures of the baths."""
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
|
# HOPS Parameters #
|
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
|
|
description: str = ""
|
|
|
|
|
"""A free-form description of the model instance."""
|
|
|
|
|
|
|
|
|
|
bcf_terms: list[int] = field(default_factory=lambda: [6] * 2)
|
|
|
|
|
"""How many bcf terms to use in the expansions of the BCF."""
|
|
|
|
|
|
|
|
|
|
ψ_0: qt.Qobj = qt.basis([2], [1])
|
|
|
|
|
"""The initial state."""
|
|
|
|
|
|
|
|
|
|
t: NDArray[np.float64] = np.linspace(0, 10, 1000)
|
|
|
|
|
"""The simulation time points."""
|
|
|
|
|
|
|
|
|
|
k_fac: list[SupportsFloat] = field(default_factory=lambda: [1.7] * 2)
|
|
|
|
|
"""The k_fac parameters for the truncation scheme.
|
|
|
|
|
|
|
|
|
|
See
|
|
|
|
|
:any:`hops.util.truncation_schemes.TruncationScheme_Power_multi`.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
k_max: int = 5
|
|
|
|
|
"""The kmax parameter for the truncation scheme.
|
|
|
|
|
|
|
|
|
|
See
|
|
|
|
|
:any:`hops.util.abstract_truncation_scheme.TruncationScheme_Simplex`
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
influence_tolerance: SupportsFloat = 1e-2
|
|
|
|
|
"""The ``influecne_tolerance`` parameter for the truncation
|
|
|
|
|
scheme.
|
|
|
|
|
|
|
|
|
|
See :any:`hops.util.truncation_schemes.BathMemory`.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
truncation_scheme: str = "simplex"
|
|
|
|
|
"""The truncation scheme to use."""
|
|
|
|
|
|
|
|
|
|
solver_args: dict[str, Any] = field(default_factory=dict)
|
|
|
|
|
"""Extra arguments for :any:`scipy.integrate.solve_ivp`."""
|
|
|
|
|
|
|
|
|
|
driving_process_tolerances: list[StocProcTolerances] = field(
|
|
|
|
|
default_factory=lambda: [StocProcTolerances(), StocProcTolerances()]
|
|
|
|
|
)
|
|
|
|
|
"""
|
|
|
|
|
The integration and interpolation tolerance for the driving
|
|
|
|
|
processes.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
thermal_process_tolerances: list[StocProcTolerances] = field(
|
|
|
|
|
default_factory=lambda: [StocProcTolerances(), StocProcTolerances()]
|
|
|
|
|
)
|
|
|
|
|
"""
|
|
|
|
|
The integration and interpolation tolerance for the thermal noise
|
|
|
|
|
processes.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
H: DynamicMatrix = field(
|
|
|
|
|
default_factory=lambda: ConstantMatrix(1 / 2 * qt.sigmaz().full()) # type: ignore
|
|
|
|
|
) # type: ignore
|
|
|
|
|
"""
|
|
|
|
|
The system hamiltonian :math:`H` with shape ``(2, 2)``.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def coupling_operators(self) -> list[DynamicMatrix]:
|
|
|
|
|
"""The bath coupling operators :math:`L`."""
|
|
|
|
|
|
|
|
|
|
return self.L
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def system(self) -> DynamicMatrix:
|
|
|
|
|
"""The system hamiltonian."""
|
|
|
|
|
|
|
|
|
|
return self.H
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def bcf_scales(self) -> list[float]:
|
|
|
|
|
"""The scaling factors for the bath correlation functions."""
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
bcf_scale(δ, L, self.t.max(), s, ω)
|
|
|
|
|
for δ, L, s, ω in zip(self.δ, self.L, self.s, self.ω_c)
|
|
|
|
|
]
|
|
|
|
|
|
2022-06-08 15:25:34 +02:00
|
|
|
|
def bcf(
|
|
|
|
|
self, i: int
|
|
|
|
|
) -> Union[hops.util.bcf.OhmicBCF_zeroTemp, hops.util.bcf.ShiftedBCF]:
|
2022-04-20 11:41:21 +02:00
|
|
|
|
"""
|
|
|
|
|
The zero temperature BCF of bath ``i``.
|
|
|
|
|
"""
|
|
|
|
|
|
2022-06-08 15:25:34 +02:00
|
|
|
|
bcf = hops.util.bcf.OhmicBCF_zeroTemp(
|
2022-04-20 11:41:21 +02:00
|
|
|
|
s=float(self.s[i]), eta=1, w_c=float(self.ω_c[i]), normed=False
|
|
|
|
|
)
|
|
|
|
|
|
2022-06-08 15:25:34 +02:00
|
|
|
|
if float(self.ω_s[i]) > 0:
|
|
|
|
|
return hops.util.bcf.ShiftedBCF(bcf, float(self.ω_s[i]))
|
|
|
|
|
|
|
|
|
|
return bcf
|
|
|
|
|
|
|
|
|
|
def spectral_density(
|
|
|
|
|
self, i: int
|
|
|
|
|
) -> Union[hops.util.bcf.OhmicSD_zeroTemp, hops.util.bcf.ShiftedSD]:
|
2022-04-20 11:41:21 +02:00
|
|
|
|
"""
|
|
|
|
|
The zero temperature spectral density of bath ``i``.
|
|
|
|
|
"""
|
|
|
|
|
|
2022-06-08 15:25:34 +02:00
|
|
|
|
sd = hops.util.bcf.OhmicSD_zeroTemp(
|
2022-04-20 11:41:21 +02:00
|
|
|
|
s=float(self.s[i]),
|
|
|
|
|
w_c=float(self.ω_c[i]),
|
|
|
|
|
eta=1,
|
|
|
|
|
normed=False,
|
|
|
|
|
)
|
|
|
|
|
|
2022-06-08 15:25:34 +02:00
|
|
|
|
if float(self.ω_s[i]) > 0:
|
|
|
|
|
return hops.util.bcf.ShiftedSD(sd, float(self.ω_s[i]))
|
|
|
|
|
|
|
|
|
|
return sd
|
|
|
|
|
|
2022-04-20 11:41:21 +02:00
|
|
|
|
def thermal_correlations(
|
|
|
|
|
self, i: int
|
|
|
|
|
) -> Optional[hops.util.bcf.Ohmic_StochasticPotentialCorrelations]:
|
|
|
|
|
"""
|
|
|
|
|
Thethermal noise corellation function of bath ``i``.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if self.T[i] == 0:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
return hops.util.bcf.Ohmic_StochasticPotentialCorrelations(
|
|
|
|
|
s=float(self.s[i]),
|
|
|
|
|
eta=1,
|
|
|
|
|
w_c=float(self.ω_c[i]),
|
|
|
|
|
normed=False,
|
|
|
|
|
beta=1 / float(self.T[i]),
|
2022-06-08 15:25:34 +02:00
|
|
|
|
shift=float(self.ω_s[i]),
|
2022-04-20 11:41:21 +02:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def thermal_spectral_density(
|
|
|
|
|
self, i: int
|
|
|
|
|
) -> Optional[hops.util.bcf.Ohmic_StochasticPotentialDensity]:
|
|
|
|
|
"""
|
|
|
|
|
The normalized thermal noise spectral density of bath ``i``.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if self.T[i] == 0:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
return hops.util.bcf.Ohmic_StochasticPotentialDensity(
|
|
|
|
|
s=float(self.s[i]),
|
|
|
|
|
eta=1,
|
|
|
|
|
w_c=float(self.ω_c[i]),
|
|
|
|
|
normed=False,
|
|
|
|
|
beta=1.0 / float(self.T[i]),
|
2022-06-08 15:25:34 +02:00
|
|
|
|
shift=float(self.ω_s[i]),
|
2022-04-20 11:41:21 +02:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def bcf_coefficients(
|
|
|
|
|
self, n: Optional[list[int]] = None
|
|
|
|
|
) -> tuple[list[NDArray[np.complex128]], list[NDArray[np.complex128]]]:
|
|
|
|
|
"""
|
|
|
|
|
The normalizedzero temperature BCF fit coefficients
|
|
|
|
|
:math:`G^{(i)}_j,W^{(i)}_j` with ``n`` terms of bath ``i``.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
n = n or self.bcf_terms
|
|
|
|
|
g, w = [], []
|
|
|
|
|
for i in range(self.num_baths):
|
|
|
|
|
g_i, w_i = self.bcf(i).exponential_coefficients(n[i])
|
|
|
|
|
g.append(g_i)
|
|
|
|
|
w.append(w_i)
|
|
|
|
|
|
|
|
|
|
return (g, w)
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def basis(n: int = 1) -> qt.Qobj:
|
|
|
|
|
"""
|
|
|
|
|
A state with of the qubit in the state state ``n`` where ``1``
|
|
|
|
|
means down and ``0`` means up.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
return qt.basis([2], [n])
|
|
|
|
|
|
|
|
|
|
def driving_process(self, i: int) -> sp.StocProc:
|
|
|
|
|
"""The driving stochastic process of the ``i``th bath."""
|
|
|
|
|
|
|
|
|
|
return sp.StocProc_FFT(
|
|
|
|
|
spectral_density=self.spectral_density(i),
|
|
|
|
|
alpha=self.bcf(i),
|
|
|
|
|
t_max=self.t.max(),
|
|
|
|
|
intgr_tol=self.driving_process_tolerances[i].integration,
|
|
|
|
|
intpl_tol=self.driving_process_tolerances[i].interpolation,
|
|
|
|
|
negative_frequencies=False,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def thermal_process(self, i: int) -> Optional[sp.StocProc]:
|
|
|
|
|
"""The thermal noise stochastic process of bath ``i``."""
|
|
|
|
|
|
|
|
|
|
if self.T[i] == 0:
|
|
|
|
|
return None
|
|
|
|
|
|
2022-06-08 15:25:34 +02:00
|
|
|
|
return (
|
|
|
|
|
sp.StocProc_TanhSinh
|
2022-06-09 16:10:56 +02:00
|
|
|
|
if self.therm_methods[i] == "tanhsinh"
|
2022-06-08 15:25:34 +02:00
|
|
|
|
else sp.StocProc_FFT
|
|
|
|
|
)(
|
2022-04-20 11:41:21 +02:00
|
|
|
|
spectral_density=self.thermal_spectral_density(i),
|
|
|
|
|
alpha=self.thermal_correlations(i),
|
|
|
|
|
t_max=self.t.max(),
|
|
|
|
|
intgr_tol=self.thermal_process_tolerances[i].integration,
|
|
|
|
|
intpl_tol=self.thermal_process_tolerances[i].interpolation,
|
|
|
|
|
negative_frequencies=False,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def thermal_processes(self) -> list[Optional[hopsflow.hopsflow.StocProc]]:
|
|
|
|
|
"""
|
|
|
|
|
The thermal noise stochastic processes for each bath.
|
|
|
|
|
:any:`None` means zero temperature.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
return [self.thermal_process(i) for i in range(self.num_baths)]
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
|
# Utility #
|
|
|
|
|
###########################################################################
|
|
|
|
|
|
2022-07-20 13:04:00 +02:00
|
|
|
|
def thermal_bcf(self, i: int):
|
|
|
|
|
"""
|
|
|
|
|
:returns: The thermal bath correlation function for the ``i``th bath.
|
|
|
|
|
"""
|
|
|
|
|
if self.T[i] == 0:
|
|
|
|
|
return self.bcf(i)
|
|
|
|
|
|
|
|
|
|
def thermal_bcf(t):
|
2022-07-20 15:04:05 +02:00
|
|
|
|
return (
|
|
|
|
|
self.bcf(i)(t) + 2 * (self.thermal_correlations(i)(t).real)
|
|
|
|
|
) * self.bcf_scales[i]
|
2022-07-20 13:04:00 +02:00
|
|
|
|
|
|
|
|
|
return thermal_bcf
|
|
|
|
|
|
2022-07-20 15:04:05 +02:00
|
|
|
|
def full_thermal_spectral_density(self, i: int):
|
|
|
|
|
"""
|
|
|
|
|
:returns: The full thermal spectral density for the ``i``th bath.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if self.T[i] == 0:
|
|
|
|
|
return self.spectral_density(i)
|
|
|
|
|
|
|
|
|
|
def thermal_sd(ω):
|
2022-08-23 15:13:50 +02:00
|
|
|
|
return self.spectral_density(i)(ω) * (
|
|
|
|
|
1 / (np.expm1(ω / self.T[i])) + np.heaviside(ω, 0)
|
2022-07-20 15:04:05 +02:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return thermal_sd
|
|
|
|
|
|
2022-08-26 09:52:01 +02:00
|
|
|
|
def full_thermal_bcf(self, i: int):
|
|
|
|
|
"""
|
|
|
|
|
:returns: The full thermal bath correlation function off bath
|
|
|
|
|
``i``.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
α_0 = self.bcf(i)
|
|
|
|
|
if self.T[i] == 0:
|
|
|
|
|
return α_0
|
|
|
|
|
|
|
|
|
|
α_therm = self.thermal_correlations(i)
|
|
|
|
|
|
|
|
|
|
def thermal_bcf(t):
|
|
|
|
|
return α_0(t) + 2 * (α_therm(t).real)
|
|
|
|
|
|
|
|
|
|
return thermal_bcf
|
|
|
|
|
|
2022-04-20 11:41:21 +02:00
|
|
|
|
@property
|
|
|
|
|
def hops_config(self) -> params.HIParams:
|
|
|
|
|
"""
|
|
|
|
|
The hops :any:`hops.core.hierarchy_params.HIParams` parameter object
|
|
|
|
|
for this system.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
g, w = self.bcf_coefficients(self.bcf_terms)
|
|
|
|
|
|
|
|
|
|
system = params.SysP(
|
|
|
|
|
H_sys=self.system,
|
|
|
|
|
L=self.coupling_operators,
|
|
|
|
|
g=g,
|
|
|
|
|
w=w,
|
|
|
|
|
bcf_scale=self.bcf_scales,
|
|
|
|
|
T=self.T,
|
|
|
|
|
description=self.description,
|
|
|
|
|
psi0=self.ψ_0.full().flatten(),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if self.truncation_scheme == "bath_memory":
|
|
|
|
|
trunc_scheme = BathMemory.from_system(
|
|
|
|
|
system,
|
|
|
|
|
nonlinear=True,
|
|
|
|
|
influence_tolerance=float(self.influence_tolerance),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
elif self.truncation_scheme == "simplex":
|
|
|
|
|
trunc_scheme = TruncationScheme_Simplex(self.k_max)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
trunc_scheme = TruncationScheme_Power_multi.from_g_w(
|
|
|
|
|
g=system.g,
|
|
|
|
|
w=system.w,
|
|
|
|
|
p=[1, 1],
|
|
|
|
|
q=[0.5, 0.5],
|
|
|
|
|
kfac=[float(k) for k in self.k_fac],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
hierarchy = params.HiP(
|
|
|
|
|
seed=0,
|
|
|
|
|
nonlinear=True,
|
|
|
|
|
terminator=False,
|
2022-08-29 15:33:24 +02:00
|
|
|
|
result_type=params.ResultType.ZEROTH_ORDER_ONLY,
|
|
|
|
|
stream_result_type=params.ResultType.ZEROTH_AND_FIRST_ORDER,
|
|
|
|
|
accum_only=True,
|
2022-04-20 11:41:21 +02:00
|
|
|
|
rand_skip=None,
|
|
|
|
|
truncation_scheme=trunc_scheme,
|
|
|
|
|
save_therm_rng_seed=True,
|
|
|
|
|
auto_normalize=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
default_solver_args = dict(rtol=1e-8, atol=1e-8)
|
|
|
|
|
default_solver_args.update(self.solver_args)
|
|
|
|
|
|
|
|
|
|
integration = params.IntP(t=self.t, **default_solver_args)
|
|
|
|
|
|
|
|
|
|
return params.HIParams(
|
|
|
|
|
SysP=system,
|
|
|
|
|
IntP=integration,
|
|
|
|
|
HiP=hierarchy,
|
|
|
|
|
Eta=[self.driving_process(i) for i in range(self.num_baths)],
|
|
|
|
|
EtaTherm=self.thermal_processes,
|
|
|
|
|
)
|