quant-met 0.0.2__py3-none-any.whl → 0.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- quant_met/__init__.py +2 -4
- quant_met/mean_field/__init__.py +60 -0
- quant_met/mean_field/_utils.py +27 -0
- quant_met/{hamiltonians/_base_hamiltonian.py → mean_field/base_hamiltonian.py} +151 -27
- quant_met/mean_field/eg_x.py +120 -0
- quant_met/mean_field/free_energy.py +130 -0
- quant_met/{hamiltonians/_graphene.py → mean_field/graphene.py} +26 -22
- quant_met/mean_field/quantum_metric.py +59 -0
- quant_met/{hamiltonians/_superfluid_weight.py → mean_field/superfluid_weight.py} +66 -50
- quant_met/plotting/__init__.py +22 -1
- quant_met/plotting/plotting.py +230 -0
- quant_met/utils.py +45 -2
- quant_met-0.0.3.dist-info/LICENSES/MIT.txt +9 -0
- {quant_met-0.0.2.dist-info → quant_met-0.0.3.dist-info}/METADATA +11 -7
- quant_met-0.0.3.dist-info/RECORD +17 -0
- quant_met/hamiltonians/__init__.py +0 -14
- quant_met/hamiltonians/_eg_x.py +0 -124
- quant_met/hamiltonians/_free_energy.py +0 -39
- quant_met/hamiltonians/_utils.py +0 -10
- quant_met/plotting/_plotting.py +0 -156
- quant_met-0.0.2.dist-info/RECORD +0 -15
- {quant_met-0.0.2.dist-info → quant_met-0.0.3.dist-info}/LICENSE.txt +0 -0
- {quant_met-0.0.2.dist-info → quant_met-0.0.3.dist-info}/WHEEL +0 -0
quant_met/__init__.py
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
# SPDX-FileCopyrightText: 2024
|
1
|
+
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: MIT
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
np.seterr(all="ignore")
|
5
|
+
"""quant-met, a package to treat superconductivity in flat-band systems."""
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
|
5
|
+
"""
|
6
|
+
Mean field treatment (:mod:`quant_met.mean_field`)
|
7
|
+
==================================================
|
8
|
+
|
9
|
+
Hamiltonians
|
10
|
+
------------
|
11
|
+
|
12
|
+
Base
|
13
|
+
|
14
|
+
.. autosummary::
|
15
|
+
:toctree: generated/
|
16
|
+
|
17
|
+
BaseHamiltonian
|
18
|
+
|
19
|
+
.. autosummary::
|
20
|
+
:toctree: generated/
|
21
|
+
|
22
|
+
GrapheneHamiltonian
|
23
|
+
EGXHamiltonian
|
24
|
+
|
25
|
+
|
26
|
+
Functions
|
27
|
+
---------
|
28
|
+
|
29
|
+
.. autosummary::
|
30
|
+
:toctree: generated/
|
31
|
+
|
32
|
+
superfluid_weight
|
33
|
+
quantum_metric
|
34
|
+
free_energy
|
35
|
+
free_energy_uniform_pairing
|
36
|
+
""" # noqa: D205, D400
|
37
|
+
|
38
|
+
from .base_hamiltonian import BaseHamiltonian
|
39
|
+
from .eg_x import EGXHamiltonian
|
40
|
+
from .free_energy import (
|
41
|
+
free_energy,
|
42
|
+
free_energy_complex_gap,
|
43
|
+
free_energy_real_gap,
|
44
|
+
free_energy_uniform_pairing,
|
45
|
+
)
|
46
|
+
from .graphene import GrapheneHamiltonian
|
47
|
+
from .quantum_metric import quantum_metric
|
48
|
+
from .superfluid_weight import superfluid_weight
|
49
|
+
|
50
|
+
__all__ = [
|
51
|
+
"superfluid_weight",
|
52
|
+
"quantum_metric",
|
53
|
+
"free_energy",
|
54
|
+
"free_energy_complex_gap",
|
55
|
+
"free_energy_real_gap",
|
56
|
+
"free_energy_uniform_pairing",
|
57
|
+
"BaseHamiltonian",
|
58
|
+
"GrapheneHamiltonian",
|
59
|
+
"EGXHamiltonian",
|
60
|
+
]
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
|
5
|
+
from typing import Any
|
6
|
+
|
7
|
+
import numpy as np
|
8
|
+
import numpy.typing as npt
|
9
|
+
|
10
|
+
|
11
|
+
def _check_valid_array(array_in: npt.NDArray[Any]) -> bool:
|
12
|
+
if np.isnan(array_in).any() or np.isinf(array_in).any():
|
13
|
+
msg = "k is NaN or Infinity"
|
14
|
+
raise ValueError(msg)
|
15
|
+
|
16
|
+
return True
|
17
|
+
|
18
|
+
|
19
|
+
def _validate_float(float_in: float, parameter_name: str) -> float:
|
20
|
+
if np.isinf(float_in):
|
21
|
+
msg = f"{parameter_name} must not be Infinity"
|
22
|
+
raise ValueError(msg)
|
23
|
+
if np.isnan(float_in):
|
24
|
+
msg = f"{parameter_name} must not be NaN"
|
25
|
+
raise ValueError(msg)
|
26
|
+
|
27
|
+
return float_in
|
@@ -1,3 +1,9 @@
|
|
1
|
+
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
|
5
|
+
"""Provides the base class for Hamiltonians."""
|
6
|
+
|
1
7
|
import pathlib
|
2
8
|
from abc import ABC, abstractmethod
|
3
9
|
|
@@ -6,6 +12,8 @@ import numpy as np
|
|
6
12
|
import numpy.typing as npt
|
7
13
|
import pandas as pd
|
8
14
|
|
15
|
+
from ._utils import _check_valid_array
|
16
|
+
|
9
17
|
|
10
18
|
class BaseHamiltonian(ABC):
|
11
19
|
"""Base class for Hamiltonians."""
|
@@ -13,26 +21,40 @@ class BaseHamiltonian(ABC):
|
|
13
21
|
@property
|
14
22
|
@abstractmethod
|
15
23
|
def number_of_bands(self) -> int:
|
24
|
+
"""Number of bands in the model."""
|
16
25
|
raise NotImplementedError
|
17
26
|
|
18
27
|
@property
|
19
|
-
@abstractmethod
|
20
28
|
def coloumb_orbital_basis(self) -> npt.NDArray[np.float64]:
|
29
|
+
"""
|
30
|
+
Coloumb interaction split up in orbitals.
|
31
|
+
|
32
|
+
Returns
|
33
|
+
-------
|
34
|
+
:class:`numpy.ndarray`
|
35
|
+
|
36
|
+
"""
|
21
37
|
raise NotImplementedError
|
22
38
|
|
23
39
|
@property
|
24
|
-
def delta_orbital_basis(self) -> npt.NDArray[np.
|
40
|
+
def delta_orbital_basis(self) -> npt.NDArray[np.complex64]:
|
41
|
+
"""
|
42
|
+
Order parameter in orbital basis.
|
43
|
+
|
44
|
+
Returns
|
45
|
+
-------
|
46
|
+
:class:`numpy.ndarray`
|
47
|
+
|
48
|
+
"""
|
25
49
|
raise NotImplementedError
|
26
50
|
|
27
51
|
@delta_orbital_basis.setter
|
28
52
|
@abstractmethod
|
29
|
-
def delta_orbital_basis(self, new_delta: npt.NDArray[np.
|
53
|
+
def delta_orbital_basis(self, new_delta: npt.NDArray[np.complex64]) -> None:
|
30
54
|
raise NotImplementedError
|
31
55
|
|
32
56
|
@abstractmethod
|
33
|
-
def _hamiltonian_one_point(
|
34
|
-
self, k_point: npt.NDArray[np.float64]
|
35
|
-
) -> npt.NDArray[np.complex64]:
|
57
|
+
def _hamiltonian_one_point(self, k_point: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]:
|
36
58
|
raise NotImplementedError
|
37
59
|
|
38
60
|
@abstractmethod
|
@@ -49,15 +71,23 @@ class BaseHamiltonian(ABC):
|
|
49
71
|
)
|
50
72
|
np.fill_diagonal(delta_matrix, self.delta_orbital_basis)
|
51
73
|
|
52
|
-
|
74
|
+
return np.block(
|
53
75
|
[
|
54
76
|
[self.hamiltonian(k_point), delta_matrix],
|
55
77
|
[np.conjugate(delta_matrix), -np.conjugate(self.hamiltonian(-k_point))],
|
56
78
|
]
|
57
79
|
)
|
58
|
-
return h
|
59
80
|
|
60
81
|
def save(self, filename: pathlib.Path) -> None:
|
82
|
+
"""
|
83
|
+
Save the Hamiltonian as a HDF5 file.
|
84
|
+
|
85
|
+
Parameters
|
86
|
+
----------
|
87
|
+
filename : :class:`pathlib.Path`
|
88
|
+
Filename to save the Hamiltonian to, should end in .hdf5
|
89
|
+
|
90
|
+
"""
|
61
91
|
with h5py.File(f"{filename}", "a") as f:
|
62
92
|
f.create_dataset("delta", data=self.delta_orbital_basis)
|
63
93
|
for key, value in vars(self).items():
|
@@ -66,17 +96,39 @@ class BaseHamiltonian(ABC):
|
|
66
96
|
|
67
97
|
@classmethod
|
68
98
|
def from_file(cls, filename: pathlib.Path) -> "BaseHamiltonian":
|
69
|
-
|
99
|
+
"""
|
100
|
+
Initialise a Hamiltonian from a HDF5 file.
|
101
|
+
|
102
|
+
Parameters
|
103
|
+
----------
|
104
|
+
filename : :class:`pathlib.Path`
|
105
|
+
File to load the Hamiltonian from.
|
106
|
+
|
107
|
+
"""
|
70
108
|
with h5py.File(f"{filename}", "r") as f:
|
109
|
+
config_dict = dict(f.attrs.items())
|
71
110
|
config_dict["delta"] = f["delta"][()]
|
72
|
-
for key, value in f.attrs.items():
|
73
|
-
config_dict[key] = value
|
74
111
|
|
75
112
|
return cls(**config_dict)
|
76
113
|
|
77
114
|
def bdg_hamiltonian(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]:
|
115
|
+
"""
|
116
|
+
Bogoliuobov de Genne Hamiltonian.
|
117
|
+
|
118
|
+
Parameters
|
119
|
+
----------
|
120
|
+
k : :class:`numpy.ndarray`
|
121
|
+
List of k points.
|
122
|
+
|
123
|
+
Returns
|
124
|
+
-------
|
125
|
+
:class:`numpy.ndarray`
|
126
|
+
BdG Hamiltonian.
|
127
|
+
|
128
|
+
"""
|
78
129
|
if np.isnan(k).any() or np.isinf(k).any():
|
79
|
-
|
130
|
+
msg = "k is NaN or Infinity"
|
131
|
+
raise ValueError(msg)
|
80
132
|
if k.ndim == 1:
|
81
133
|
h = self._bdg_hamiltonian_one_point(k)
|
82
134
|
else:
|
@@ -84,8 +136,21 @@ class BaseHamiltonian(ABC):
|
|
84
136
|
return h
|
85
137
|
|
86
138
|
def hamiltonian(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]:
|
87
|
-
|
88
|
-
|
139
|
+
"""
|
140
|
+
Return the normal state Hamiltonian in orbital basis.
|
141
|
+
|
142
|
+
Parameters
|
143
|
+
----------
|
144
|
+
k : :class:`numpy.ndarray`
|
145
|
+
List of k points.
|
146
|
+
|
147
|
+
Returns
|
148
|
+
-------
|
149
|
+
:class:`numpy.ndarray`
|
150
|
+
Hamiltonian in matrix form.
|
151
|
+
|
152
|
+
"""
|
153
|
+
assert _check_valid_array(k)
|
89
154
|
if k.ndim == 1:
|
90
155
|
h = self._hamiltonian_one_point(k)
|
91
156
|
else:
|
@@ -95,19 +160,48 @@ class BaseHamiltonian(ABC):
|
|
95
160
|
def hamiltonian_derivative(
|
96
161
|
self, k: npt.NDArray[np.float64], direction: str
|
97
162
|
) -> npt.NDArray[np.complex64]:
|
98
|
-
|
99
|
-
|
163
|
+
"""
|
164
|
+
Deriative of the Hamiltonian.
|
165
|
+
|
166
|
+
Parameters
|
167
|
+
----------
|
168
|
+
k: :class:`numpy.ndarray`
|
169
|
+
List of k points.
|
170
|
+
direction: str
|
171
|
+
Direction for derivative, either 'x' oder 'y'.
|
172
|
+
|
173
|
+
Returns
|
174
|
+
-------
|
175
|
+
:class:`numpy.ndarray`
|
176
|
+
Derivative of Hamiltonian.
|
177
|
+
|
178
|
+
"""
|
179
|
+
assert _check_valid_array(k)
|
100
180
|
if k.ndim == 1:
|
101
181
|
h = self._hamiltonian_derivative_one_point(k, direction)
|
102
182
|
else:
|
103
|
-
h = np.array(
|
104
|
-
[self._hamiltonian_derivative_one_point(k, direction) for k in k]
|
105
|
-
)
|
183
|
+
h = np.array([self._hamiltonian_derivative_one_point(k, direction) for k in k])
|
106
184
|
return h
|
107
185
|
|
108
186
|
def diagonalize_nonint(
|
109
187
|
self, k: npt.NDArray[np.float64]
|
110
188
|
) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]:
|
189
|
+
"""
|
190
|
+
Diagonalize the normal state Hamiltonian.
|
191
|
+
|
192
|
+
Parameters
|
193
|
+
----------
|
194
|
+
k : :class:`numpy.ndarray`
|
195
|
+
List of k points.
|
196
|
+
|
197
|
+
Returns
|
198
|
+
-------
|
199
|
+
:class:`numpy.ndarray`
|
200
|
+
Eigenvalues of the normal state Hamiltonian.
|
201
|
+
:class:`numpy.ndarray`
|
202
|
+
Diagonalising matrix of the normal state Hamiltonian.
|
203
|
+
|
204
|
+
"""
|
111
205
|
k_point_matrix = self.hamiltonian(k)
|
112
206
|
|
113
207
|
if k.ndim == 1:
|
@@ -119,16 +213,30 @@ class BaseHamiltonian(ABC):
|
|
119
213
|
)
|
120
214
|
band_energies = np.zeros((len(k), self.number_of_bands))
|
121
215
|
|
122
|
-
for i
|
123
|
-
band_energies[i], bloch_wavefunctions[i] = np.linalg.eigh(
|
124
|
-
k_point_matrix[i]
|
125
|
-
)
|
216
|
+
for i in range(len(k)):
|
217
|
+
band_energies[i], bloch_wavefunctions[i] = np.linalg.eigh(k_point_matrix[i])
|
126
218
|
|
127
219
|
return band_energies, bloch_wavefunctions
|
128
220
|
|
129
221
|
def diagonalize_bdg(
|
130
222
|
self, k: npt.NDArray[np.float64]
|
131
223
|
) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.complex64]]:
|
224
|
+
"""
|
225
|
+
Diagonalize the BdG Hamiltonian.
|
226
|
+
|
227
|
+
Parameters
|
228
|
+
----------
|
229
|
+
k : :class:`numpy.ndarray`
|
230
|
+
List of k points.
|
231
|
+
|
232
|
+
Returns
|
233
|
+
-------
|
234
|
+
:class:`numpy.ndarray`
|
235
|
+
Eigenvalues of the BdG Hamiltonian.
|
236
|
+
:class:`numpy.ndarray`
|
237
|
+
Diagonalising matrix of the BdG Hamiltonian.
|
238
|
+
|
239
|
+
"""
|
132
240
|
bdg_matrix = self.bdg_hamiltonian(k)
|
133
241
|
|
134
242
|
if k.ndim == 1:
|
@@ -140,7 +248,7 @@ class BaseHamiltonian(ABC):
|
|
140
248
|
)
|
141
249
|
bdg_energies = np.zeros((len(k), 2 * self.number_of_bands))
|
142
250
|
|
143
|
-
for i
|
251
|
+
for i in range(len(k)):
|
144
252
|
bdg_energies[i], bdg_wavefunctions[i] = np.linalg.eigh(bdg_matrix[i])
|
145
253
|
|
146
254
|
return bdg_energies, bdg_wavefunctions
|
@@ -150,6 +258,22 @@ class BaseHamiltonian(ABC):
|
|
150
258
|
k: npt.NDArray[np.float64],
|
151
259
|
overlaps: tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]] | None = None,
|
152
260
|
) -> pd.DataFrame:
|
261
|
+
"""
|
262
|
+
Calculate the band structure.
|
263
|
+
|
264
|
+
Parameters
|
265
|
+
----------
|
266
|
+
k : :class:`numpy.ndarray`
|
267
|
+
List of k points.
|
268
|
+
overlaps : tuple(:class:`numpy.ndarray`, :class:`numpy.ndarray`), optional
|
269
|
+
Overlaps.
|
270
|
+
|
271
|
+
Returns
|
272
|
+
-------
|
273
|
+
`pandas.DataFrame`
|
274
|
+
Band structure.
|
275
|
+
|
276
|
+
"""
|
153
277
|
k_point_matrix = self.hamiltonian(k)
|
154
278
|
|
155
279
|
results = pd.DataFrame(
|
@@ -157,14 +281,14 @@ class BaseHamiltonian(ABC):
|
|
157
281
|
dtype=float,
|
158
282
|
)
|
159
283
|
|
160
|
-
for i
|
284
|
+
for i in range(len(k)):
|
161
285
|
energies, eigenvectors = np.linalg.eigh(k_point_matrix[i])
|
162
286
|
|
163
287
|
for band_index in range(self.number_of_bands):
|
164
|
-
results.
|
288
|
+
results.loc[i, f"band_{band_index}"] = energies[band_index]
|
165
289
|
|
166
290
|
if overlaps is not None:
|
167
|
-
results.
|
291
|
+
results.loc[i, f"wx_{band_index}"] = (
|
168
292
|
np.abs(np.dot(eigenvectors[:, band_index], overlaps[0])) ** 2
|
169
293
|
- np.abs(np.dot(eigenvectors[:, band_index], overlaps[1])) ** 2
|
170
294
|
)
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
|
5
|
+
"""Provides the implementation for the EG-X model."""
|
6
|
+
|
7
|
+
import numpy as np
|
8
|
+
import numpy.typing as npt
|
9
|
+
|
10
|
+
from ._utils import _validate_float
|
11
|
+
from .base_hamiltonian import BaseHamiltonian
|
12
|
+
|
13
|
+
|
14
|
+
class EGXHamiltonian(BaseHamiltonian):
|
15
|
+
"""Hamiltonian for the EG-X model."""
|
16
|
+
|
17
|
+
def __init__(
|
18
|
+
self,
|
19
|
+
hopping_gr: float,
|
20
|
+
hopping_x: float,
|
21
|
+
hopping_x_gr_a: float,
|
22
|
+
lattice_constant: float,
|
23
|
+
mu: float,
|
24
|
+
coloumb_gr: float,
|
25
|
+
coloumb_x: float,
|
26
|
+
delta: npt.NDArray[np.complex64] | None = None,
|
27
|
+
) -> None:
|
28
|
+
self.hopping_gr = _validate_float(hopping_gr, "Hopping graphene")
|
29
|
+
self.hopping_x = _validate_float(hopping_x, "Hopping impurity")
|
30
|
+
self.hopping_x_gr_a = _validate_float(hopping_x_gr_a, "Hybridisation")
|
31
|
+
self.lattice_constant = _validate_float(lattice_constant, "Lattice constant")
|
32
|
+
self.mu = _validate_float(mu, "Chemical potential")
|
33
|
+
self.coloumb_gr = _validate_float(coloumb_gr, "Coloumb interaction graphene")
|
34
|
+
self.coloumb_x = _validate_float(coloumb_x, "Coloumb interaction impurity")
|
35
|
+
self._coloumb_orbital_basis = np.array([self.coloumb_gr, self.coloumb_gr, self.coloumb_x])
|
36
|
+
self._number_of_bands = 3
|
37
|
+
if delta is None:
|
38
|
+
self._delta_orbital_basis = np.zeros(3, dtype=np.complex64)
|
39
|
+
else:
|
40
|
+
self._delta_orbital_basis = delta
|
41
|
+
|
42
|
+
@property
|
43
|
+
def coloumb_orbital_basis(self) -> npt.NDArray[np.float64]: # noqa: D102
|
44
|
+
return self._coloumb_orbital_basis
|
45
|
+
|
46
|
+
@property
|
47
|
+
def delta_orbital_basis(self) -> npt.NDArray[np.complex64]: # noqa: D102
|
48
|
+
return self._delta_orbital_basis
|
49
|
+
|
50
|
+
@delta_orbital_basis.setter
|
51
|
+
def delta_orbital_basis(self, new_delta: npt.NDArray[np.complex64]) -> None:
|
52
|
+
self._delta_orbital_basis = new_delta
|
53
|
+
|
54
|
+
@property
|
55
|
+
def number_of_bands(self) -> int: # noqa: D102
|
56
|
+
return self._number_of_bands
|
57
|
+
|
58
|
+
def _hamiltonian_derivative_one_point(
|
59
|
+
self, k: npt.NDArray[np.float64], direction: str
|
60
|
+
) -> npt.NDArray[np.complex64]:
|
61
|
+
assert direction in ["x", "y"]
|
62
|
+
|
63
|
+
t_gr = self.hopping_gr
|
64
|
+
t_x = self.hopping_x
|
65
|
+
a = self.lattice_constant
|
66
|
+
|
67
|
+
h = np.zeros((self.number_of_bands, self.number_of_bands), dtype=np.complex64)
|
68
|
+
|
69
|
+
if direction == "x":
|
70
|
+
h[0, 1] = t_gr * a * np.exp(-0.5j * a / np.sqrt(3) * k[1]) * np.sin(0.5 * a * k[0])
|
71
|
+
h[1, 0] = h[0, 1].conjugate()
|
72
|
+
h[2, 2] = (
|
73
|
+
2
|
74
|
+
* a
|
75
|
+
* t_x
|
76
|
+
* (np.sin(a * k[0]) + np.sin(0.5 * a * k[0]) * np.cos(0.5 * np.sqrt(3) * a * k[1]))
|
77
|
+
)
|
78
|
+
else:
|
79
|
+
h[0, 1] = (
|
80
|
+
-t_gr
|
81
|
+
* 1j
|
82
|
+
* a
|
83
|
+
/ np.sqrt(3)
|
84
|
+
* (
|
85
|
+
np.exp(1j * a / np.sqrt(3) * k[1])
|
86
|
+
- np.exp(-0.5j * a / np.sqrt(3) * k[1]) * np.cos(0.5 * a * k[0])
|
87
|
+
)
|
88
|
+
)
|
89
|
+
h[1, 0] = h[0, 1].conjugate()
|
90
|
+
h[2, 2] = np.sqrt(3) * a * t_x * np.cos(0.5 * np.sqrt(3) * a * k[1])
|
91
|
+
|
92
|
+
return h
|
93
|
+
|
94
|
+
def _hamiltonian_one_point(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]:
|
95
|
+
t_gr = self.hopping_gr
|
96
|
+
t_x = self.hopping_x
|
97
|
+
a = self.lattice_constant
|
98
|
+
v = self.hopping_x_gr_a
|
99
|
+
mu = self.mu
|
100
|
+
|
101
|
+
h = np.zeros((self.number_of_bands, self.number_of_bands), dtype=np.complex64)
|
102
|
+
|
103
|
+
h[0, 1] = -t_gr * (
|
104
|
+
np.exp(1j * k[1] * a / np.sqrt(3))
|
105
|
+
+ 2 * np.exp(-0.5j * a / np.sqrt(3) * k[1]) * (np.cos(0.5 * a * k[0]))
|
106
|
+
)
|
107
|
+
|
108
|
+
h[1, 0] = h[0, 1].conjugate()
|
109
|
+
|
110
|
+
h[2, 0] = v
|
111
|
+
h[0, 2] = v
|
112
|
+
|
113
|
+
h[2, 2] = (
|
114
|
+
-2
|
115
|
+
* t_x
|
116
|
+
* (np.cos(a * k[0]) + 2 * np.cos(0.5 * a * k[0]) * np.cos(0.5 * np.sqrt(3) * a * k[1]))
|
117
|
+
)
|
118
|
+
h -= mu * np.eye(3, dtype=np.complex64)
|
119
|
+
|
120
|
+
return h
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
|
5
|
+
"""Functions to calculate the free energy of a BdG Hamiltonian."""
|
6
|
+
|
7
|
+
import numpy as np
|
8
|
+
import numpy.typing as npt
|
9
|
+
|
10
|
+
from .base_hamiltonian import BaseHamiltonian
|
11
|
+
|
12
|
+
|
13
|
+
def free_energy(
|
14
|
+
hamiltonian: BaseHamiltonian,
|
15
|
+
k_points: npt.NDArray[np.float64],
|
16
|
+
) -> float:
|
17
|
+
"""Calculate the free energy of a BdG Hamiltonian.
|
18
|
+
|
19
|
+
Parameters
|
20
|
+
----------
|
21
|
+
hamiltonian : :class:`BaseHamiltonian`
|
22
|
+
Hamiltonian to be evaluated.
|
23
|
+
k_points : :class:`numpy.ndarray`
|
24
|
+
List of k points
|
25
|
+
|
26
|
+
Returns
|
27
|
+
-------
|
28
|
+
float
|
29
|
+
Free energy from the BdG Hamiltonian.
|
30
|
+
|
31
|
+
"""
|
32
|
+
number_k_points = len(k_points)
|
33
|
+
bdg_energies, _ = hamiltonian.diagonalize_bdg(k_points)
|
34
|
+
|
35
|
+
k_array = np.array(
|
36
|
+
[
|
37
|
+
np.sum(np.abs(bdg_energies[k_index][0 : hamiltonian.number_of_bands]))
|
38
|
+
for k_index in range(number_k_points)
|
39
|
+
]
|
40
|
+
)
|
41
|
+
|
42
|
+
integral: float = -np.sum(k_array, axis=-1) / number_k_points + np.sum(
|
43
|
+
np.power(np.abs(hamiltonian.delta_orbital_basis), 2) / hamiltonian.coloumb_orbital_basis
|
44
|
+
)
|
45
|
+
|
46
|
+
return integral
|
47
|
+
|
48
|
+
|
49
|
+
def free_energy_complex_gap(
|
50
|
+
delta_vector: npt.NDArray[np.float64],
|
51
|
+
hamiltonian: BaseHamiltonian,
|
52
|
+
k_points: npt.NDArray[np.float64],
|
53
|
+
) -> float:
|
54
|
+
"""Calculate the free energy of a BdG Hamiltonian, with a complex order parameter.
|
55
|
+
|
56
|
+
Parameters
|
57
|
+
----------
|
58
|
+
delta_vector : :class:`numpy.ndarray`
|
59
|
+
Delta in orbital basis, with consecutive floats getting converted into one complex number,
|
60
|
+
so [a, b, c, d] -> [a+b*j, c+d*j].
|
61
|
+
hamiltonian : :class:`BaseHamiltonian`
|
62
|
+
Hamiltonian to be evaluated.
|
63
|
+
k_points : :class:`numpy.ndarray`
|
64
|
+
List of k points
|
65
|
+
|
66
|
+
Returns
|
67
|
+
-------
|
68
|
+
float
|
69
|
+
Free energy from the BdG Hamiltonian.
|
70
|
+
|
71
|
+
"""
|
72
|
+
hamiltonian.delta_orbital_basis = delta_vector[0::2] + 1j * delta_vector[1::2]
|
73
|
+
|
74
|
+
return free_energy(hamiltonian=hamiltonian, k_points=k_points)
|
75
|
+
|
76
|
+
|
77
|
+
def free_energy_real_gap(
|
78
|
+
delta_vector: npt.NDArray[np.float64],
|
79
|
+
hamiltonian: BaseHamiltonian,
|
80
|
+
k_points: npt.NDArray[np.float64],
|
81
|
+
) -> float:
|
82
|
+
"""Calculate the free energy of a BdG Hamiltonian, with a real order parameter.
|
83
|
+
|
84
|
+
Parameters
|
85
|
+
----------
|
86
|
+
delta_vector : :class:`numpy.ndarray`
|
87
|
+
Delta in orbital basis.
|
88
|
+
hamiltonian : :class:`BaseHamiltonian`
|
89
|
+
Hamiltonian to be evaluated.
|
90
|
+
k_points : :class:`numpy.ndarray`
|
91
|
+
List of k points
|
92
|
+
|
93
|
+
Returns
|
94
|
+
-------
|
95
|
+
float
|
96
|
+
Free energy from the BdG Hamiltonian.
|
97
|
+
|
98
|
+
"""
|
99
|
+
hamiltonian.delta_orbital_basis = delta_vector.astype(np.complex64)
|
100
|
+
|
101
|
+
return free_energy(hamiltonian=hamiltonian, k_points=k_points)
|
102
|
+
|
103
|
+
|
104
|
+
def free_energy_uniform_pairing(
|
105
|
+
delta: float,
|
106
|
+
hamiltonian: BaseHamiltonian,
|
107
|
+
k_points: npt.NDArray[np.float64],
|
108
|
+
) -> float:
|
109
|
+
"""Calculate the free energy of a BdG Hamiltonian, with uniform pairing constraint.
|
110
|
+
|
111
|
+
Parameters
|
112
|
+
----------
|
113
|
+
delta : float
|
114
|
+
Delta.
|
115
|
+
hamiltonian : :class:`BaseHamiltonian`
|
116
|
+
Hamiltonian to be evaluated.
|
117
|
+
k_points : :class:`numpy.ndarray`
|
118
|
+
List of k points
|
119
|
+
|
120
|
+
Returns
|
121
|
+
-------
|
122
|
+
float
|
123
|
+
Free energy from the BdG Hamiltonian.
|
124
|
+
|
125
|
+
"""
|
126
|
+
hamiltonian.delta_orbital_basis = np.full(
|
127
|
+
hamiltonian.number_of_bands, fill_value=delta, dtype=np.float64
|
128
|
+
).astype(np.complex64)
|
129
|
+
|
130
|
+
return free_energy(hamiltonian=hamiltonian, k_points=k_points)
|