mirror of
https://github.com/vale981/two_qubit_model
synced 2025-03-04 17:21:43 -05:00
add power and steady state energy change
This commit is contained in:
parent
5d901b0878
commit
777808f3cc
2 changed files with 83 additions and 2 deletions
|
@ -16,9 +16,10 @@ from hops.util.dynamic_matrix import (
|
|||
MatrixType,
|
||||
)
|
||||
from .one_qubit_model import QubitModelMutliBath
|
||||
from .utility import linspace_with_strobe
|
||||
from .utility import linspace_with_strobe, strobe_times
|
||||
from numpy.typing import ArrayLike, NDArray
|
||||
|
||||
from typing import Optional
|
||||
from hops.core.hierarchy_data import HIData
|
||||
|
||||
Timings = tuple[float, float, float, float]
|
||||
Orders = tuple[int, int]
|
||||
|
@ -204,6 +205,14 @@ class OttoEngine(QubitModelMutliBath):
|
|||
self.Ω,
|
||||
)
|
||||
|
||||
@property
|
||||
def strobe(self):
|
||||
"""
|
||||
Returns a tuple with the times where a cycle is complete and
|
||||
their corresponding indices.
|
||||
"""
|
||||
return strobe_times(self.t, self.Ω)
|
||||
|
||||
@t.setter
|
||||
def t(self, _):
|
||||
pass
|
||||
|
@ -355,6 +364,58 @@ class OttoEngine(QubitModelMutliBath):
|
|||
# therm_methods=self.therm_methods,
|
||||
# )
|
||||
|
||||
def steady_index(
|
||||
self, σ_factor=2, data: Optional[HIData] = None, **kwargs
|
||||
) -> Optional[int]:
|
||||
"""
|
||||
Determine using the system energy (``data`` and ``kwargs`` are
|
||||
being passed to :any:`system_energy`) when the periodic steady
|
||||
state has been reached.
|
||||
|
||||
This is being done by comparing the change of the system
|
||||
energy from cycle to cycle against the standard deviation of
|
||||
this value multiplied by ``σ_factor``.
|
||||
"""
|
||||
_, indices = self.strobe
|
||||
|
||||
Δ_system = abs(
|
||||
(
|
||||
self.system_energy(data, **kwargs).slice(indices[1:])
|
||||
- self.system_energy(data, **kwargs).slice(indices[:-1])
|
||||
)
|
||||
* (1 / get_energy_gap(self.H(0)))
|
||||
)
|
||||
|
||||
steady_mask = Δ_system.value < Δ_system.σ * 2
|
||||
idx = np.argmax(steady_mask) + 1
|
||||
|
||||
if steady_mask[idx:].all():
|
||||
return int(idx)
|
||||
|
||||
return False
|
||||
|
||||
def steady_energy_change(self, σ_factor=2, data: Optional[HIData] = None, **kwargs):
|
||||
"""
|
||||
The steady energy change computed from ``data`` or online
|
||||
data. The ``kwargs`` are being passed on to the analysis
|
||||
methods.
|
||||
"""
|
||||
|
||||
_, indices = self.strobe
|
||||
steady_idx = self.steady_index(σ_factor, data, **kwargs)
|
||||
|
||||
if steady_idx is None:
|
||||
raise RuntimeError("No steady state available.")
|
||||
|
||||
Δ_energies = self.total_energy().slice(indices[1:]) - self.total_energy().slice(
|
||||
indices[:-1]
|
||||
)
|
||||
|
||||
return Δ_energies.mean
|
||||
|
||||
def power(self, *args, **kwargs):
|
||||
return self.steady_energy_change(*args, **kwargs) * (1 / self.Θ)
|
||||
|
||||
|
||||
def normalize_hamiltonian(hamiltonian: np.ndarray) -> np.ndarray:
|
||||
eigvals = np.linalg.eigvals(hamiltonian)
|
||||
|
|
|
@ -238,3 +238,23 @@ def linspace_with_strobe(
|
|||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def strobe_times(time: NDArray[np.float64], frequency: float, tolerance: float = 1e-4):
|
||||
r"""
|
||||
Given a time array ``time`` and an angular frequency ``frequency`` (ω) the
|
||||
time points (and their indices) coinciding with :math:`2π / ω \cdot n` within the
|
||||
``tolerance`` are being returned.
|
||||
"""
|
||||
|
||||
stroboscope_interval = 2 * np.pi / frequency
|
||||
sorted_times = np.sort(time)
|
||||
tolerance = min(tolerance, (sorted_times[1:] - sorted_times[:-1]).min() / 2)
|
||||
strobe_indices = np.where((time % stroboscope_interval) <= tolerance)[0]
|
||||
|
||||
if len(strobe_indices) == 0:
|
||||
raise ValueError("Can't match the strobe interval to the times.")
|
||||
|
||||
strobe_times = time[strobe_indices]
|
||||
|
||||
return strobe_times, strobe_indices
|
||||
|
|
Loading…
Add table
Reference in a new issue