-
Notifications
You must be signed in to change notification settings - Fork 621
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HEOM Parity support #2261
base: master
Are you sure you want to change the base?
HEOM Parity support #2261
Changes from 36 commits
1a2e5d0
27ed772
3ba219d
40a914d
3edecc0
f51033a
c880375
7080102
390c596
fa563b5
c6a7d4e
5c03d92
5f0003c
22cdee6
f16d52d
fc794bc
26c49ed
9699687
77f23a4
2c74559
b9d8093
3fe627e
65a8299
ca7095a
a79a305
5ee816a
aaa45f1
27c878d
4172aef
4b5cfc1
e7f1360
87a23a0
01058af
dd1f104
adaca75
a5ce6cc
ce69039
e004b44
07d1c38
41ddaba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
It adds odd parity support to HEOM's fermionic solver |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -105,6 +105,7 @@ class HierarchyADOs: | |
labels: list of tuples | ||
A list of the ADO labels within the hierarchy. | ||
""" | ||
|
||
def __init__(self, exponents, max_depth): | ||
self.exponents = exponents | ||
self.max_depth = max_depth | ||
|
@@ -347,6 +348,7 @@ class HierarchyADOsState: | |
See :class:`HierarchyADOs` for a full list of the available attributes | ||
and methods. | ||
""" | ||
|
||
def __init__(self, rho, ados, ado_state): | ||
self.rho = rho | ||
self._ado_state = ado_state | ||
|
@@ -566,6 +568,17 @@ class HEOMSolver(Solver): | |
If multiple baths are given, they must all be either fermionic | ||
or bosonic baths. | ||
|
||
odd_parity : Bool | ||
For fermionic baths only. Default is "False". If set to "True", | ||
the RHS construction differs slightly (it implies the RHS is acting on | ||
an initial density operator which has odd parity in terms of its | ||
representation in fermionic annhilation operators). In other words, a | ||
state with a well defined number of excitations has even parity, but | ||
one with superpositions of the number of excitations has odd parity. | ||
This is normally prohibited in 'normal' electronic systems, where | ||
charge is conserved, but is useful for the construction of | ||
electron spectrum (under linear response assumptions). | ||
|
||
max_depth : int | ||
The maximum depth of the heirarchy (i.e. the maximum number of bath | ||
exponent "excitations" to retain). | ||
|
@@ -602,9 +615,10 @@ class HEOMSolver(Solver): | |
"state_data_type": "dense", | ||
} | ||
|
||
def __init__(self, H, bath, max_depth, *, options=None): | ||
def __init__(self, H, bath, max_depth, *, odd_parity=False, options=None): | ||
_time_start = time() | ||
|
||
# we call bool here because odd_parity will be used in arithmetic | ||
self.odd_parity = bool(odd_parity) | ||
if not isinstance(H, (Qobj, QobjEvo)): | ||
raise TypeError("The Hamiltonian (H) must be a Qobj or QobjEvo") | ||
|
||
|
@@ -753,11 +767,9 @@ def _grad_prev_fermionic(self, he_n, k): | |
] | ||
|
||
n_excite = sum(he_fermionic_n) | ||
sign1 = (-1) ** (n_excite + 1) | ||
|
||
gsuarezr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
n_excite_before_m = sum(he_fermionic_n[:k]) | ||
sign2 = (-1) ** (n_excite_before_m) | ||
|
||
sign1 = (-1) ** (n_excite + 1 - self.odd_parity) | ||
sign2 = (-1)**(n_excite_before_m + self.odd_parity) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you put these lines back where they were so that there is a small block of code for the calculation of each sign instead of interleaving the two calculations? |
||
sigma_bar_k = k + self.ados.sigma_bar_k_offset[k] | ||
|
||
if self.ados.exponents[k].type == BathExponent.types["+"]: | ||
|
@@ -800,10 +812,9 @@ def _grad_next_fermionic(self, he_n, k): | |
for i, exp in zip(he_n, self.ados.exponents) | ||
] | ||
n_excite = sum(he_fermionic_n) | ||
sign1 = (-1) ** (n_excite + 1) | ||
|
||
n_excite_before_m = sum(he_fermionic_n[:k]) | ||
sign2 = (-1) ** (n_excite_before_m) | ||
sign1 = (-1) ** (n_excite + 1 - self.odd_parity) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. |
||
sign2 = (-1)**(n_excite_before_m + self.odd_parity) | ||
|
||
if self.ados.exponents[k].type == BathExponent.types["+"]: | ||
if sign1 == -1: | ||
|
@@ -1233,6 +1244,7 @@ class HSolverDL(HEOMSolver): | |
operator). See :meth:`BosonicBath.combine` for details. | ||
Keyword only. Default: True. | ||
""" | ||
|
||
def __init__( | ||
self, H_sys, coup_op, coup_strength, temperature, | ||
N_cut, N_exp, cut_freq, *, bnd_cut_approx=False, options=None, | ||
|
@@ -1281,6 +1293,7 @@ class _GatherHEOMRHS: | |
nhe : int | ||
The number of ADOs in the hierarchy. | ||
""" | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you again undo these unrelated changes? |
||
def __init__(self, f_idx, block, nhe): | ||
self._block_size = block | ||
self._n_blocks = nhe | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -9,7 +9,7 @@ | |||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
from qutip import ( | ||||||||||||||||||||||||||||||||||||||||||||
basis, destroy, expect, liouvillian, qeye, sigmax, sigmaz, | ||||||||||||||||||||||||||||||||||||||||||||
tensor, Qobj, QobjEvo | ||||||||||||||||||||||||||||||||||||||||||||
tensor, Qobj, QobjEvo, fcreate, fdestroy | ||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, I shouldn't have included it |
||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||
from qutip.core import data as _data | ||||||||||||||||||||||||||||||||||||||||||||
from qutip.solver.heom.bofin_baths import ( | ||||||||||||||||||||||||||||||||||||||||||||
|
@@ -54,8 +54,8 @@ def assert_raises_steady_state_time_dependent(hsolver): | |||||||||||||||||||||||||||||||||||||||||||
with pytest.raises(ValueError) as err: | ||||||||||||||||||||||||||||||||||||||||||||
hsolver.steady_state() | ||||||||||||||||||||||||||||||||||||||||||||
assert str(err.value) == ( | ||||||||||||||||||||||||||||||||||||||||||||
"A steady state cannot be determined for a time-dependent" | ||||||||||||||||||||||||||||||||||||||||||||
" system" | ||||||||||||||||||||||||||||||||||||||||||||
"A steady state cannot be determined for a time-dependent" | ||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can stay -- it's a valid indentation fix. |
||||||||||||||||||||||||||||||||||||||||||||
" system" | ||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
|
@@ -232,6 +232,7 @@ class DrudeLorentzPureDephasingModel: | |||||||||||||||||||||||||||||||||||||||||||
""" Analytic Drude-Lorentz pure-dephasing model for testing the HEOM | ||||||||||||||||||||||||||||||||||||||||||||
solver. | ||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove these too. |
||||||||||||||||||||||||||||||||||||||||||||
def __init__(self, lam, gamma, T, Nk): | ||||||||||||||||||||||||||||||||||||||||||||
self.lam = lam | ||||||||||||||||||||||||||||||||||||||||||||
self.gamma = gamma | ||||||||||||||||||||||||||||||||||||||||||||
|
@@ -289,6 +290,7 @@ class UnderdampedPureDephasingModel: | |||||||||||||||||||||||||||||||||||||||||||
""" Analytic Drude-Lorentz pure-dephasing model for testing the HEOM | ||||||||||||||||||||||||||||||||||||||||||||
solver. | ||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
def __init__(self, lam, gamma, w0, T, Nk): | ||||||||||||||||||||||||||||||||||||||||||||
self.lam = lam | ||||||||||||||||||||||||||||||||||||||||||||
self.gamma = gamma | ||||||||||||||||||||||||||||||||||||||||||||
|
@@ -331,6 +333,7 @@ class BosonicMode: | |||||||||||||||||||||||||||||||||||||||||||
""" A description of a bosonic mode for inclusion in a | ||||||||||||||||||||||||||||||||||||||||||||
DiscreteLevelCurrentModel. | ||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
def __init__(self, N, Lambda, Omega, gamma_b): | ||||||||||||||||||||||||||||||||||||||||||||
self.N = N | ||||||||||||||||||||||||||||||||||||||||||||
self.Lambda = Lambda | ||||||||||||||||||||||||||||||||||||||||||||
|
@@ -356,6 +359,7 @@ class DiscreteLevelCurrentModel: | |||||||||||||||||||||||||||||||||||||||||||
""" Analytic discrete level current model for testing the HEOM solver | ||||||||||||||||||||||||||||||||||||||||||||
with a fermionic bath (and optionally a bosonic mode). | ||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
def __init__(self, gamma, W, T, lmax, theta=2., e1=1., bosonic_mode=None): | ||||||||||||||||||||||||||||||||||||||||||||
# single fermion | ||||||||||||||||||||||||||||||||||||||||||||
self.e1 = e1 # energy | ||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1127,6 +1131,46 @@ def test_solving_with_step(self): | |||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
assert states[-1] == ado_state.extract(0) | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
def test_parity(self): | ||||||||||||||||||||||||||||||||||||||||||||
depth = 2 | ||||||||||||||||||||||||||||||||||||||||||||
Nk = 2 | ||||||||||||||||||||||||||||||||||||||||||||
# system: two fermions | ||||||||||||||||||||||||||||||||||||||||||||
N = 2 | ||||||||||||||||||||||||||||||||||||||||||||
d_1 = fdestroy(N, 0) | ||||||||||||||||||||||||||||||||||||||||||||
d_2 = fdestroy(N, 1) | ||||||||||||||||||||||||||||||||||||||||||||
# bath params: | ||||||||||||||||||||||||||||||||||||||||||||
mu = 0. # chemical potential | ||||||||||||||||||||||||||||||||||||||||||||
Gamma = 1 # coupling strenght | ||||||||||||||||||||||||||||||||||||||||||||
W = 2.5 # bath width | ||||||||||||||||||||||||||||||||||||||||||||
# system params: | ||||||||||||||||||||||||||||||||||||||||||||
# coulomb repulsion | ||||||||||||||||||||||||||||||||||||||||||||
U = 3 * np.pi * Gamma | ||||||||||||||||||||||||||||||||||||||||||||
# impurity energy | ||||||||||||||||||||||||||||||||||||||||||||
w0 = - U / 2. | ||||||||||||||||||||||||||||||||||||||||||||
beta = 1 / (0.2 * Gamma) # Inverse Temperature | ||||||||||||||||||||||||||||||||||||||||||||
H = w0 * (d_1.dag() * d_1 + d_2.dag() | ||||||||||||||||||||||||||||||||||||||||||||
* d_2) + U * d_1.dag() * d_1 * d_2.dag() * d_2 | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
L = liouvillian(H) | ||||||||||||||||||||||||||||||||||||||||||||
bath1 = LorentzianPadeBath( | ||||||||||||||||||||||||||||||||||||||||||||
Q=d_1, gamma=2 * Gamma, w=W, mu=mu, T=1 / beta, Nk=Nk, | ||||||||||||||||||||||||||||||||||||||||||||
tag="Lead 1") | ||||||||||||||||||||||||||||||||||||||||||||
bath2 = LorentzianPadeBath( | ||||||||||||||||||||||||||||||||||||||||||||
Q=d_2, gamma=2 * Gamma, w=W, mu=mu, T=1 / beta, Nk=Nk, | ||||||||||||||||||||||||||||||||||||||||||||
tag="Lead 2") | ||||||||||||||||||||||||||||||||||||||||||||
resultHEOMPade = HEOMSolver(L, [bath1, bath2], depth, odd_parity=True) | ||||||||||||||||||||||||||||||||||||||||||||
rhoss, _ = resultHEOMPade.steady_state(use_mkl=False) | ||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you explain why you needed to pass There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I used used_mkl=False, because if I don't for the test fails for python 3.10 with no cython (only in that setup it passes in all others), the test fails with Exception: Zero pivot, numerical factorization or iterative refinement problem. I found this old thread #791 suggesting that sometimes mkl solvers give some trouble so I decided to set it to false |
||||||||||||||||||||||||||||||||||||||||||||
rhoss = rhoss.full() | ||||||||||||||||||||||||||||||||||||||||||||
expected_odd = np.diag([-0.18472, 0.68472, 0.68472, -0.18472]) | ||||||||||||||||||||||||||||||||||||||||||||
expected = np.diag([0.10623, 0.39376, 0.39376, 0.10623]) | ||||||||||||||||||||||||||||||||||||||||||||
assert np.isclose(rhoss, expected_odd,atol=1e-5).all() | ||||||||||||||||||||||||||||||||||||||||||||
resultHEOMPade = HEOMSolver(L, [bath1, bath2], depth, odd_parity=False) | ||||||||||||||||||||||||||||||||||||||||||||
rhoss, _ = resultHEOMPade.steady_state(use_mkl=False) | ||||||||||||||||||||||||||||||||||||||||||||
rhoss = rhoss.full() | ||||||||||||||||||||||||||||||||||||||||||||
assert np.isclose(rhoss, expected,atol=1e-5).all() | ||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There appear to be too many blank lines here. |
||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
class TestHeomsolveFunction: | ||||||||||||||||||||||||||||||||||||||||||||
@pytest.mark.parametrize(['evo'], [ | ||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simon asked us to help distill and clarify this a little bit; how about:
" For fermionic baths only. Default is "False". "Parity" refers to the parity of the initial system state used with the HEOM. An example of an odd parity state is one made from applying an odd number of fermionic creation operators to a physical density operator. Physical systems have even parity, but allowing the generalization to odd-parity states allows one to calculate useful physical quantities like the system power spectrum or density of states. The form of the HEOM differs depending on the parity of the initial system state, so if this option is set to "True", a different RHS is constructed, which can then be used with a system state of odd parity. "