quant-met 0.0.2__py3-none-any.whl → 0.0.4__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 +61 -0
- quant_met/mean_field/_utils.py +27 -0
- quant_met/mean_field/base_hamiltonian.py +310 -0
- quant_met/mean_field/eg_x.py +173 -0
- quant_met/mean_field/free_energy.py +130 -0
- quant_met/mean_field/graphene.py +142 -0
- quant_met/mean_field/quantum_metric.py +108 -0
- quant_met/mean_field/superfluid_weight.py +146 -0
- quant_met/plotting/__init__.py +22 -1
- quant_met/plotting/plotting.py +230 -0
- quant_met/utils.py +45 -2
- quant_met-0.0.4.dist-info/LICENSES/MIT.txt +9 -0
- {quant_met-0.0.2.dist-info → quant_met-0.0.4.dist-info}/METADATA +11 -7
- quant_met-0.0.4.dist-info/RECORD +17 -0
- quant_met/hamiltonians/__init__.py +0 -14
- quant_met/hamiltonians/_base_hamiltonian.py +0 -172
- quant_met/hamiltonians/_eg_x.py +0 -124
- quant_met/hamiltonians/_free_energy.py +0 -39
- quant_met/hamiltonians/_graphene.py +0 -93
- quant_met/hamiltonians/_superfluid_weight.py +0 -130
- 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.4.dist-info}/LICENSE.txt +0 -0
- {quant_met-0.0.2.dist-info → quant_met-0.0.4.dist-info}/WHEEL +0 -0
quant_met/utils.py
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
|
5
|
+
"""
|
6
|
+
Utility functions (:mod:`quant_met.utils`)
|
7
|
+
==========================================
|
8
|
+
|
9
|
+
.. currentmodule:: quant_met.utils
|
10
|
+
|
11
|
+
Functions
|
12
|
+
---------
|
13
|
+
|
14
|
+
.. autosummary::
|
15
|
+
:toctree: generated/
|
16
|
+
|
17
|
+
generate_uniform_grid - Generate a uniform grid of points in 2D.
|
18
|
+
""" # noqa: D205, D400
|
19
|
+
|
1
20
|
import numpy as np
|
2
21
|
import numpy.typing as npt
|
3
22
|
|
@@ -9,10 +28,34 @@ def generate_uniform_grid(
|
|
9
28
|
corner_2: npt.NDArray[np.float64],
|
10
29
|
origin: npt.NDArray[np.float64],
|
11
30
|
) -> npt.NDArray[np.float64]:
|
31
|
+
"""
|
32
|
+
Generate a uniform grid of points in 2D.
|
33
|
+
|
34
|
+
Parameters
|
35
|
+
----------
|
36
|
+
ncols : int
|
37
|
+
Number of columns
|
38
|
+
nrows : int
|
39
|
+
Number of rows
|
40
|
+
corner_1 : :py:class:`numpy.ndarray`
|
41
|
+
First corner vector
|
42
|
+
corner_2 : :py:class:`numpy.ndarray`
|
43
|
+
Second corner vector
|
44
|
+
origin : :py:class:`numpy.ndarray`
|
45
|
+
Origin point
|
46
|
+
|
47
|
+
Returns
|
48
|
+
-------
|
49
|
+
:py:class:`numpy.ndarray`
|
50
|
+
Grid
|
51
|
+
|
52
|
+
"""
|
12
53
|
if ncols <= 1 or nrows <= 1:
|
13
|
-
|
54
|
+
msg = "Number of columns and rows must be greater than 1."
|
55
|
+
raise ValueError(msg)
|
14
56
|
if np.linalg.norm(corner_1) == 0 or np.linalg.norm(corner_2) == 0:
|
15
|
-
|
57
|
+
msg = "Vectors to the corners cannot be zero."
|
58
|
+
raise ValueError(msg)
|
16
59
|
|
17
60
|
grid: npt.NDArray[np.float64] = np.concatenate(
|
18
61
|
[
|
@@ -0,0 +1,9 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024-present Tjark <tsievers@physnet.uni-hamburg.de>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
|
+
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -1,22 +1,26 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: quant-met
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.4
|
4
4
|
Summary: Calculate superconductivity in flat-band systems.
|
5
5
|
Author: Tjark Sievers
|
6
6
|
Author-email: tsievers@physnet.uni-hamburg.de
|
7
|
-
Requires-Python: >=3.
|
7
|
+
Requires-Python: >=3.11,<4.0
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: Programming Language :: Python :: 3.10
|
10
9
|
Classifier: Programming Language :: Python :: 3.11
|
11
10
|
Classifier: Programming Language :: Python :: 3.12
|
12
11
|
Requires-Dist: h5py (>=3.11.0,<4.0.0)
|
13
|
-
Requires-Dist: matplotlib (>=3.
|
14
|
-
Requires-Dist: numpy (>=
|
12
|
+
Requires-Dist: matplotlib (>=3.9.1,<4.0.0)
|
13
|
+
Requires-Dist: numpy (>=2.0.0,<3.0.0)
|
15
14
|
Requires-Dist: pandas (>=2.2.2,<3.0.0)
|
16
|
-
Requires-Dist: scipy (>=1.
|
17
|
-
Requires-Dist: sympy (>=1.12,<2.0)
|
15
|
+
Requires-Dist: scipy (>=1.14.0,<2.0.0)
|
18
16
|
Description-Content-Type: text/markdown
|
19
17
|
|
18
|
+
<!--
|
19
|
+
SPDX-FileCopyrightText: 2024 Tjark Sievers
|
20
|
+
|
21
|
+
SPDX-License-Identifier: MIT
|
22
|
+
-->
|
23
|
+
|
20
24
|
# quant-met
|
21
25
|
|
22
26
|
[](https://github.com/Ruberhauptmann/quant-met/actions/workflows/test.yml)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
quant_met/__init__.py,sha256=ZO1UFz1awUYTI7B9ZkBwucvDz7GMGXnLLUGnEwLBhkc,155
|
2
|
+
quant_met/mean_field/__init__.py,sha256=msHp5Y5cuHjqr_EdC9jS9JKpeAi6CBHggtxrG_psDRk,1182
|
3
|
+
quant_met/mean_field/_utils.py,sha256=plkx6eYjyYV3CT3BWwlulqW7L-Q0t1TzZTLR4k7u0dg,666
|
4
|
+
quant_met/mean_field/base_hamiltonian.py,sha256=7rNBbkoSSaIQVg4GiKDI1WaSZxJiGR26bdidh9uygzw,8812
|
5
|
+
quant_met/mean_field/eg_x.py,sha256=y_DWBoyRaHVIof_itAgHaoaFEEssY_Q9mhvsKC7DxdM,5286
|
6
|
+
quant_met/mean_field/free_energy.py,sha256=FSGCHoBO1myHGwGQ8CqGu7_08whH0Ot3ikZhBu27tyM,3444
|
7
|
+
quant_met/mean_field/graphene.py,sha256=rKD2UjB0blN4ALePk4bQlg0XahHoe_3mCqRAvEUGiqI,4162
|
8
|
+
quant_met/mean_field/quantum_metric.py,sha256=B2QDjA4XpyWPhmElA_uqVn9pfllTvTOgqfy5yHV-nro,3820
|
9
|
+
quant_met/mean_field/superfluid_weight.py,sha256=jKzGsNSzDTach9viQ57iV16DNkIfgPOJqmVZJGIMIAE,4891
|
10
|
+
quant_met/plotting/__init__.py,sha256=QRQ3TNb0PNQi2lWXY0LHKgYSRuegM1N3dVVs9146Zug,457
|
11
|
+
quant_met/plotting/plotting.py,sha256=iVTFZ9tQz_GalzqbQhxCiNWOhYHJM4wiZPTjXaXnApM,7326
|
12
|
+
quant_met/utils.py,sha256=Tvw_YfqjIWx0FPGSReikSnw9xfN-T2dpQZN-KPMa69A,1709
|
13
|
+
quant_met-0.0.4.dist-info/LICENSE.txt,sha256=QO_duPQihSJlaxSLxPAXo52X3esROP5wBkhxqBd1Z4E,1104
|
14
|
+
quant_met-0.0.4.dist-info/LICENSES/MIT.txt,sha256=QO_duPQihSJlaxSLxPAXo52X3esROP5wBkhxqBd1Z4E,1104
|
15
|
+
quant_met-0.0.4.dist-info/METADATA,sha256=dsJwfAESdbjfAWZtzzwASpHi9eb9_lQEDAf3f18PU8s,2598
|
16
|
+
quant_met-0.0.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
17
|
+
quant_met-0.0.4.dist-info/RECORD,,
|
@@ -1,14 +0,0 @@
|
|
1
|
-
from ._base_hamiltonian import BaseHamiltonian
|
2
|
-
from ._eg_x import EGXHamiltonian
|
3
|
-
from ._free_energy import free_energy, free_energy_uniform_pairing
|
4
|
-
from ._graphene import GrapheneHamiltonian
|
5
|
-
from ._superfluid_weight import calculate_superfluid_weight
|
6
|
-
|
7
|
-
__all__ = [
|
8
|
-
"BaseHamiltonian",
|
9
|
-
"GrapheneHamiltonian",
|
10
|
-
"EGXHamiltonian",
|
11
|
-
"calculate_superfluid_weight",
|
12
|
-
"free_energy",
|
13
|
-
"free_energy_uniform_pairing",
|
14
|
-
]
|
@@ -1,172 +0,0 @@
|
|
1
|
-
import pathlib
|
2
|
-
from abc import ABC, abstractmethod
|
3
|
-
|
4
|
-
import h5py
|
5
|
-
import numpy as np
|
6
|
-
import numpy.typing as npt
|
7
|
-
import pandas as pd
|
8
|
-
|
9
|
-
|
10
|
-
class BaseHamiltonian(ABC):
|
11
|
-
"""Base class for Hamiltonians."""
|
12
|
-
|
13
|
-
@property
|
14
|
-
@abstractmethod
|
15
|
-
def number_of_bands(self) -> int:
|
16
|
-
raise NotImplementedError
|
17
|
-
|
18
|
-
@property
|
19
|
-
@abstractmethod
|
20
|
-
def coloumb_orbital_basis(self) -> npt.NDArray[np.float64]:
|
21
|
-
raise NotImplementedError
|
22
|
-
|
23
|
-
@property
|
24
|
-
def delta_orbital_basis(self) -> npt.NDArray[np.float64]:
|
25
|
-
raise NotImplementedError
|
26
|
-
|
27
|
-
@delta_orbital_basis.setter
|
28
|
-
@abstractmethod
|
29
|
-
def delta_orbital_basis(self, new_delta: npt.NDArray[np.float64]) -> None:
|
30
|
-
raise NotImplementedError
|
31
|
-
|
32
|
-
@abstractmethod
|
33
|
-
def _hamiltonian_one_point(
|
34
|
-
self, k_point: npt.NDArray[np.float64]
|
35
|
-
) -> npt.NDArray[np.complex64]:
|
36
|
-
raise NotImplementedError
|
37
|
-
|
38
|
-
@abstractmethod
|
39
|
-
def _hamiltonian_derivative_one_point(
|
40
|
-
self, k_point: npt.NDArray[np.float64], directions: str
|
41
|
-
) -> npt.NDArray[np.complex64]:
|
42
|
-
raise NotImplementedError
|
43
|
-
|
44
|
-
def _bdg_hamiltonian_one_point(
|
45
|
-
self, k_point: npt.NDArray[np.float64]
|
46
|
-
) -> npt.NDArray[np.complex64]:
|
47
|
-
delta_matrix: npt.NDArray[np.complex64] = np.zeros(
|
48
|
-
shape=(self.number_of_bands, self.number_of_bands), dtype=np.complex64
|
49
|
-
)
|
50
|
-
np.fill_diagonal(delta_matrix, self.delta_orbital_basis)
|
51
|
-
|
52
|
-
h = np.block(
|
53
|
-
[
|
54
|
-
[self.hamiltonian(k_point), delta_matrix],
|
55
|
-
[np.conjugate(delta_matrix), -np.conjugate(self.hamiltonian(-k_point))],
|
56
|
-
]
|
57
|
-
)
|
58
|
-
return h
|
59
|
-
|
60
|
-
def save(self, filename: pathlib.Path) -> None:
|
61
|
-
with h5py.File(f"{filename}", "a") as f:
|
62
|
-
f.create_dataset("delta", data=self.delta_orbital_basis)
|
63
|
-
for key, value in vars(self).items():
|
64
|
-
if not key.startswith("_"):
|
65
|
-
f.attrs[key] = value
|
66
|
-
|
67
|
-
@classmethod
|
68
|
-
def from_file(cls, filename: pathlib.Path) -> "BaseHamiltonian":
|
69
|
-
config_dict = {}
|
70
|
-
with h5py.File(f"{filename}", "r") as f:
|
71
|
-
config_dict["delta"] = f["delta"][()]
|
72
|
-
for key, value in f.attrs.items():
|
73
|
-
config_dict[key] = value
|
74
|
-
|
75
|
-
return cls(**config_dict)
|
76
|
-
|
77
|
-
def bdg_hamiltonian(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]:
|
78
|
-
if np.isnan(k).any() or np.isinf(k).any():
|
79
|
-
raise ValueError("k is NaN or Infinity")
|
80
|
-
if k.ndim == 1:
|
81
|
-
h = self._bdg_hamiltonian_one_point(k)
|
82
|
-
else:
|
83
|
-
h = np.array([self._bdg_hamiltonian_one_point(k) for k in k])
|
84
|
-
return h
|
85
|
-
|
86
|
-
def hamiltonian(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]:
|
87
|
-
if np.isnan(k).any() or np.isinf(k).any():
|
88
|
-
raise ValueError("k is NaN or Infinity")
|
89
|
-
if k.ndim == 1:
|
90
|
-
h = self._hamiltonian_one_point(k)
|
91
|
-
else:
|
92
|
-
h = np.array([self._hamiltonian_one_point(k) for k in k])
|
93
|
-
return h
|
94
|
-
|
95
|
-
def hamiltonian_derivative(
|
96
|
-
self, k: npt.NDArray[np.float64], direction: str
|
97
|
-
) -> npt.NDArray[np.complex64]:
|
98
|
-
if np.isnan(k).any() or np.isinf(k).any():
|
99
|
-
raise ValueError("k is NaN or Infinity")
|
100
|
-
if k.ndim == 1:
|
101
|
-
h = self._hamiltonian_derivative_one_point(k, direction)
|
102
|
-
else:
|
103
|
-
h = np.array(
|
104
|
-
[self._hamiltonian_derivative_one_point(k, direction) for k in k]
|
105
|
-
)
|
106
|
-
return h
|
107
|
-
|
108
|
-
def diagonalize_nonint(
|
109
|
-
self, k: npt.NDArray[np.float64]
|
110
|
-
) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]:
|
111
|
-
k_point_matrix = self.hamiltonian(k)
|
112
|
-
|
113
|
-
if k.ndim == 1:
|
114
|
-
band_energies, bloch_wavefunctions = np.linalg.eigh(k_point_matrix)
|
115
|
-
else:
|
116
|
-
bloch_wavefunctions = np.zeros(
|
117
|
-
(len(k), self.number_of_bands, self.number_of_bands),
|
118
|
-
dtype=complex,
|
119
|
-
)
|
120
|
-
band_energies = np.zeros((len(k), self.number_of_bands))
|
121
|
-
|
122
|
-
for i, k in enumerate(k):
|
123
|
-
band_energies[i], bloch_wavefunctions[i] = np.linalg.eigh(
|
124
|
-
k_point_matrix[i]
|
125
|
-
)
|
126
|
-
|
127
|
-
return band_energies, bloch_wavefunctions
|
128
|
-
|
129
|
-
def diagonalize_bdg(
|
130
|
-
self, k: npt.NDArray[np.float64]
|
131
|
-
) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.complex64]]:
|
132
|
-
bdg_matrix = self.bdg_hamiltonian(k)
|
133
|
-
|
134
|
-
if k.ndim == 1:
|
135
|
-
bdg_energies, bdg_wavefunctions = np.linalg.eigh(bdg_matrix)
|
136
|
-
else:
|
137
|
-
bdg_wavefunctions = np.zeros(
|
138
|
-
(len(k), 2 * self.number_of_bands, 2 * self.number_of_bands),
|
139
|
-
dtype=np.complex64,
|
140
|
-
)
|
141
|
-
bdg_energies = np.zeros((len(k), 2 * self.number_of_bands))
|
142
|
-
|
143
|
-
for i, k in enumerate(k):
|
144
|
-
bdg_energies[i], bdg_wavefunctions[i] = np.linalg.eigh(bdg_matrix[i])
|
145
|
-
|
146
|
-
return bdg_energies, bdg_wavefunctions
|
147
|
-
|
148
|
-
def calculate_bandstructure(
|
149
|
-
self,
|
150
|
-
k: npt.NDArray[np.float64],
|
151
|
-
overlaps: tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]] | None = None,
|
152
|
-
) -> pd.DataFrame:
|
153
|
-
k_point_matrix = self.hamiltonian(k)
|
154
|
-
|
155
|
-
results = pd.DataFrame(
|
156
|
-
index=range(len(k)),
|
157
|
-
dtype=float,
|
158
|
-
)
|
159
|
-
|
160
|
-
for i, k in enumerate(k):
|
161
|
-
energies, eigenvectors = np.linalg.eigh(k_point_matrix[i])
|
162
|
-
|
163
|
-
for band_index in range(self.number_of_bands):
|
164
|
-
results.at[i, f"band_{band_index}"] = energies[band_index]
|
165
|
-
|
166
|
-
if overlaps is not None:
|
167
|
-
results.at[i, f"wx_{band_index}"] = (
|
168
|
-
np.abs(np.dot(eigenvectors[:, band_index], overlaps[0])) ** 2
|
169
|
-
- np.abs(np.dot(eigenvectors[:, band_index], overlaps[1])) ** 2
|
170
|
-
)
|
171
|
-
|
172
|
-
return results
|
quant_met/hamiltonians/_eg_x.py
DELETED
@@ -1,124 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
import numpy.typing as npt
|
3
|
-
|
4
|
-
from ._base_hamiltonian import BaseHamiltonian
|
5
|
-
from ._utils import _check_valid_float
|
6
|
-
|
7
|
-
|
8
|
-
class EGXHamiltonian(BaseHamiltonian):
|
9
|
-
def __init__(
|
10
|
-
self,
|
11
|
-
t_gr: float,
|
12
|
-
t_x: float,
|
13
|
-
V: float,
|
14
|
-
a: float,
|
15
|
-
mu: float,
|
16
|
-
U_gr: float,
|
17
|
-
U_x: float,
|
18
|
-
delta: npt.NDArray[np.float64] | None = None,
|
19
|
-
):
|
20
|
-
self.t_gr = _check_valid_float(t_gr, "Hopping graphene")
|
21
|
-
self.t_x = _check_valid_float(t_x, "Hopping impurity")
|
22
|
-
self.V = _check_valid_float(V, "Hybridisation")
|
23
|
-
self.a = _check_valid_float(a, "Lattice constant")
|
24
|
-
self.mu = _check_valid_float(mu, "Chemical potential")
|
25
|
-
self.U_gr = _check_valid_float(U_gr, "Coloumb interaction graphene")
|
26
|
-
self.U_x = _check_valid_float(U_x, "Coloumb interaction impurity")
|
27
|
-
if delta is None:
|
28
|
-
self._delta_orbital_basis = np.zeros(3)
|
29
|
-
else:
|
30
|
-
self._delta_orbital_basis = delta
|
31
|
-
|
32
|
-
@property
|
33
|
-
def coloumb_orbital_basis(self) -> npt.NDArray[np.float64]:
|
34
|
-
return np.array([self.U_gr, self.U_gr, self.U_x])
|
35
|
-
|
36
|
-
@property
|
37
|
-
def delta_orbital_basis(self) -> npt.NDArray[np.float64]:
|
38
|
-
return self._delta_orbital_basis
|
39
|
-
|
40
|
-
@delta_orbital_basis.setter
|
41
|
-
def delta_orbital_basis(self, new_delta: npt.NDArray[np.float64]) -> None:
|
42
|
-
self._delta_orbital_basis = new_delta
|
43
|
-
|
44
|
-
@property
|
45
|
-
def number_of_bands(self) -> int:
|
46
|
-
return 3
|
47
|
-
|
48
|
-
def _hamiltonian_derivative_one_point(
|
49
|
-
self, k: npt.NDArray[np.float64], direction: str
|
50
|
-
) -> npt.NDArray[np.complex64]:
|
51
|
-
assert direction in ["x", "y"]
|
52
|
-
|
53
|
-
t_gr = self.t_gr
|
54
|
-
t_x = self.t_x
|
55
|
-
a = self.a
|
56
|
-
|
57
|
-
h = np.zeros((self.number_of_bands, self.number_of_bands), dtype=np.complex64)
|
58
|
-
|
59
|
-
if direction == "x":
|
60
|
-
h[0, 1] = (
|
61
|
-
t_gr
|
62
|
-
* a
|
63
|
-
* np.exp(-0.5j * a / np.sqrt(3) * k[1])
|
64
|
-
* np.sin(0.5 * a * k[0])
|
65
|
-
)
|
66
|
-
h[1, 0] = h[0, 1].conjugate()
|
67
|
-
h[2, 2] = (
|
68
|
-
2
|
69
|
-
* a
|
70
|
-
* t_x
|
71
|
-
* (
|
72
|
-
np.sin(a * k[0])
|
73
|
-
+ np.sin(0.5 * a * k[0]) * np.cos(0.5 * np.sqrt(3) * a * k[1])
|
74
|
-
)
|
75
|
-
)
|
76
|
-
else:
|
77
|
-
h[0, 1] = (
|
78
|
-
-t_gr
|
79
|
-
* 1j
|
80
|
-
* a
|
81
|
-
/ np.sqrt(3)
|
82
|
-
* (
|
83
|
-
np.exp(1j * a / np.sqrt(3) * k[1])
|
84
|
-
- np.exp(-0.5j * a / np.sqrt(3) * k[1]) * np.cos(0.5 * a * k[0])
|
85
|
-
)
|
86
|
-
)
|
87
|
-
h[1, 0] = h[0, 1].conjugate()
|
88
|
-
h[2, 2] = np.sqrt(3) * a * t_x * np.cos(0.5 * np.sqrt(3) * a * k[1])
|
89
|
-
|
90
|
-
return h
|
91
|
-
|
92
|
-
def _hamiltonian_one_point(
|
93
|
-
self, k: npt.NDArray[np.float64]
|
94
|
-
) -> npt.NDArray[np.complex64]:
|
95
|
-
t_gr = self.t_gr
|
96
|
-
t_x = self.t_x
|
97
|
-
a = self.a
|
98
|
-
# a_0 = a / np.sqrt(3)
|
99
|
-
V = self.V
|
100
|
-
mu = self.mu
|
101
|
-
|
102
|
-
h = np.zeros((self.number_of_bands, self.number_of_bands), dtype=np.complex64)
|
103
|
-
|
104
|
-
h[0, 1] = -t_gr * (
|
105
|
-
np.exp(1j * k[1] * a / np.sqrt(3))
|
106
|
-
+ 2 * np.exp(-0.5j * a / np.sqrt(3) * k[1]) * (np.cos(0.5 * a * k[0]))
|
107
|
-
)
|
108
|
-
|
109
|
-
h[1, 0] = h[0, 1].conjugate()
|
110
|
-
|
111
|
-
h[2, 0] = V
|
112
|
-
h[0, 2] = V
|
113
|
-
|
114
|
-
h[2, 2] = (
|
115
|
-
-2
|
116
|
-
* t_x
|
117
|
-
* (
|
118
|
-
np.cos(a * k[0])
|
119
|
-
+ 2 * np.cos(0.5 * a * k[0]) * np.cos(0.5 * np.sqrt(3) * a * k[1])
|
120
|
-
)
|
121
|
-
)
|
122
|
-
h -= mu * np.eye(3, dtype=np.complex64)
|
123
|
-
|
124
|
-
return h
|
@@ -1,39 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
import numpy.typing as npt
|
3
|
-
|
4
|
-
from ._base_hamiltonian import BaseHamiltonian
|
5
|
-
|
6
|
-
|
7
|
-
def free_energy(
|
8
|
-
delta_vector: npt.NDArray[np.float64],
|
9
|
-
hamiltonian: BaseHamiltonian,
|
10
|
-
k_points: npt.NDArray[np.float64],
|
11
|
-
) -> float:
|
12
|
-
number_k_points = len(k_points)
|
13
|
-
hamiltonian.delta_orbital_basis = delta_vector
|
14
|
-
bdg_energies, _ = hamiltonian.diagonalize_bdg(k_points)
|
15
|
-
|
16
|
-
k_array = np.array(
|
17
|
-
[
|
18
|
-
np.sum(np.abs(bdg_energies[k_index][0 : hamiltonian.number_of_bands]))
|
19
|
-
for k_index in range(number_k_points)
|
20
|
-
]
|
21
|
-
)
|
22
|
-
|
23
|
-
integral: float = -np.sum(k_array, axis=-1) / number_k_points + np.sum(
|
24
|
-
np.power(np.abs(delta_vector), 2) / hamiltonian.coloumb_orbital_basis
|
25
|
-
)
|
26
|
-
|
27
|
-
return integral
|
28
|
-
|
29
|
-
|
30
|
-
def free_energy_uniform_pairing(
|
31
|
-
delta: float,
|
32
|
-
hamiltonian: BaseHamiltonian,
|
33
|
-
k_points: npt.NDArray[np.float64],
|
34
|
-
) -> float:
|
35
|
-
delta_vector = np.ones(hamiltonian.number_of_bands) * delta
|
36
|
-
|
37
|
-
return free_energy(
|
38
|
-
delta_vector=delta_vector, hamiltonian=hamiltonian, k_points=k_points
|
39
|
-
)
|
@@ -1,93 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
import numpy.typing as npt
|
3
|
-
|
4
|
-
from ._base_hamiltonian import BaseHamiltonian
|
5
|
-
from ._utils import _check_valid_float
|
6
|
-
|
7
|
-
|
8
|
-
class GrapheneHamiltonian(BaseHamiltonian):
|
9
|
-
def __init__(
|
10
|
-
self,
|
11
|
-
t_nn: float,
|
12
|
-
a: float,
|
13
|
-
mu: float,
|
14
|
-
coulomb_gr: float,
|
15
|
-
delta: npt.NDArray[np.float64] | None = None,
|
16
|
-
):
|
17
|
-
self.t_nn = _check_valid_float(t_nn, "Hopping")
|
18
|
-
if a <= 0:
|
19
|
-
raise ValueError("Lattice constant must be positive")
|
20
|
-
self.a = _check_valid_float(a, "Lattice constant")
|
21
|
-
self.mu = _check_valid_float(mu, "Chemical potential")
|
22
|
-
self.coulomb_gr = _check_valid_float(coulomb_gr, "Coloumb interaction")
|
23
|
-
if delta is None:
|
24
|
-
self._delta_orbital_basis = np.zeros(2)
|
25
|
-
else:
|
26
|
-
self._delta_orbital_basis = delta
|
27
|
-
|
28
|
-
@property
|
29
|
-
def coloumb_orbital_basis(self) -> npt.NDArray[np.float64]:
|
30
|
-
return np.array([self.coulomb_gr, self.coulomb_gr])
|
31
|
-
|
32
|
-
@property
|
33
|
-
def number_of_bands(self) -> int:
|
34
|
-
return 2
|
35
|
-
|
36
|
-
@property
|
37
|
-
def delta_orbital_basis(self) -> npt.NDArray[np.float64]:
|
38
|
-
return self._delta_orbital_basis
|
39
|
-
|
40
|
-
@delta_orbital_basis.setter
|
41
|
-
def delta_orbital_basis(self, new_delta: npt.NDArray[np.float64]) -> None:
|
42
|
-
self._delta_orbital_basis = new_delta
|
43
|
-
|
44
|
-
def _hamiltonian_derivative_one_point(
|
45
|
-
self, k: npt.NDArray[np.float64], direction: str
|
46
|
-
) -> npt.NDArray[np.complex64]:
|
47
|
-
assert direction in ["x", "y"]
|
48
|
-
|
49
|
-
t_nn = self.t_nn
|
50
|
-
a = self.a
|
51
|
-
|
52
|
-
h = np.zeros((self.number_of_bands, self.number_of_bands), dtype=np.complex64)
|
53
|
-
|
54
|
-
if direction == "x":
|
55
|
-
h[0, 1] = (
|
56
|
-
t_nn
|
57
|
-
* a
|
58
|
-
* np.exp(-0.5j * a / np.sqrt(3) * k[1])
|
59
|
-
* np.sin(0.5 * a * k[0])
|
60
|
-
)
|
61
|
-
h[1, 0] = h[0, 1].conjugate()
|
62
|
-
else:
|
63
|
-
h[0, 1] = (
|
64
|
-
-t_nn
|
65
|
-
* 1j
|
66
|
-
* a
|
67
|
-
/ np.sqrt(3)
|
68
|
-
* (
|
69
|
-
np.exp(1j * a / np.sqrt(3) * k[1])
|
70
|
-
- np.exp(-0.5j * a / np.sqrt(3) * k[1]) * np.cos(0.5 * a * k[0])
|
71
|
-
)
|
72
|
-
)
|
73
|
-
h[1, 0] = h[0, 1].conjugate()
|
74
|
-
|
75
|
-
return h
|
76
|
-
|
77
|
-
def _hamiltonian_one_point(
|
78
|
-
self, k: npt.NDArray[np.float64]
|
79
|
-
) -> npt.NDArray[np.complex64]:
|
80
|
-
t_nn = self.t_nn
|
81
|
-
a = self.a
|
82
|
-
mu = self.mu
|
83
|
-
|
84
|
-
h = np.zeros((self.number_of_bands, self.number_of_bands), dtype=np.complex64)
|
85
|
-
|
86
|
-
h[0, 1] = -t_nn * (
|
87
|
-
np.exp(1j * k[1] * a / np.sqrt(3))
|
88
|
-
+ 2 * np.exp(-0.5j * a / np.sqrt(3) * k[1]) * (np.cos(0.5 * a * k[0]))
|
89
|
-
)
|
90
|
-
h[1, 0] = h[0, 1].conjugate()
|
91
|
-
h -= mu * np.eye(2)
|
92
|
-
|
93
|
-
return h
|
@@ -1,130 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
import numpy.typing as npt
|
3
|
-
|
4
|
-
from ._base_hamiltonian import BaseHamiltonian
|
5
|
-
|
6
|
-
|
7
|
-
def calculate_current_operator(
|
8
|
-
h: BaseHamiltonian, direction: str, k: npt.NDArray[np.float64]
|
9
|
-
) -> npt.NDArray[np.complex64]:
|
10
|
-
j = np.zeros(shape=(h.number_of_bands, h.number_of_bands), dtype=np.complex64)
|
11
|
-
|
12
|
-
_, bloch = h.diagonalize_nonint(k=k)
|
13
|
-
|
14
|
-
for m in range(h.number_of_bands):
|
15
|
-
for n in range(h.number_of_bands):
|
16
|
-
j[m, n] = (
|
17
|
-
np.conjugate(bloch[:, m])
|
18
|
-
@ h.hamiltonian_derivative(direction=direction, k=k)
|
19
|
-
@ bloch[:, n]
|
20
|
-
)
|
21
|
-
|
22
|
-
return j
|
23
|
-
|
24
|
-
|
25
|
-
def calculate_w_matrix(
|
26
|
-
h: BaseHamiltonian, k: npt.NDArray[np.float64]
|
27
|
-
) -> tuple[npt.NDArray[np.complex64], npt.NDArray[np.complex64]]:
|
28
|
-
_, bloch = h.diagonalize_nonint(k=k)
|
29
|
-
_, bdg_functions = h.diagonalize_bdg(k=k)
|
30
|
-
|
31
|
-
w_plus = np.zeros((2 * h.number_of_bands, h.number_of_bands), dtype=np.complex64)
|
32
|
-
for i in range(2 * h.number_of_bands):
|
33
|
-
for m in range(h.number_of_bands):
|
34
|
-
w_plus[i, m] = (
|
35
|
-
np.tensordot(bloch[:, m], np.array([1, 0]), axes=0).reshape(-1)
|
36
|
-
@ bdg_functions[:, i]
|
37
|
-
)
|
38
|
-
|
39
|
-
w_minus = np.zeros((2 * h.number_of_bands, h.number_of_bands), dtype=np.complex64)
|
40
|
-
for i in range(2 * h.number_of_bands):
|
41
|
-
for m in range(h.number_of_bands):
|
42
|
-
w_minus[i, m] = (
|
43
|
-
np.tensordot(
|
44
|
-
np.conjugate(bloch[:, m]), np.array([0, 1]), axes=0
|
45
|
-
).reshape(-1)
|
46
|
-
@ bdg_functions[:, i]
|
47
|
-
)
|
48
|
-
|
49
|
-
return w_plus, w_minus
|
50
|
-
|
51
|
-
|
52
|
-
def calculate_c_factor(
|
53
|
-
h: BaseHamiltonian, k: npt.NDArray[np.float64]
|
54
|
-
) -> npt.NDArray[np.complex64]:
|
55
|
-
bdg_energies, _ = h.diagonalize_bdg(k)
|
56
|
-
w_plus, w_minus = calculate_w_matrix(h, k)
|
57
|
-
C_mnpq = np.zeros(
|
58
|
-
shape=(
|
59
|
-
h.number_of_bands,
|
60
|
-
h.number_of_bands,
|
61
|
-
h.number_of_bands,
|
62
|
-
h.number_of_bands,
|
63
|
-
),
|
64
|
-
dtype=np.complex64,
|
65
|
-
)
|
66
|
-
|
67
|
-
for m in range(h.number_of_bands):
|
68
|
-
for n in range(h.number_of_bands):
|
69
|
-
for p in range(h.number_of_bands):
|
70
|
-
for q in range(h.number_of_bands):
|
71
|
-
C_tmp: float = 0
|
72
|
-
for i in range(2 * h.number_of_bands):
|
73
|
-
for j in range(2 * h.number_of_bands):
|
74
|
-
if bdg_energies[i] != bdg_energies[j]:
|
75
|
-
C_tmp += (
|
76
|
-
fermi_dirac(bdg_energies[i])
|
77
|
-
- fermi_dirac(bdg_energies[j])
|
78
|
-
) / (bdg_energies[j] - bdg_energies[i])
|
79
|
-
else:
|
80
|
-
C_tmp -= fermi_dirac_derivative()
|
81
|
-
|
82
|
-
C_tmp *= (
|
83
|
-
np.conjugate(w_minus[i, m])
|
84
|
-
* w_plus[j, n]
|
85
|
-
* np.conjugate(w_minus[j, p])
|
86
|
-
* w_minus[i, q]
|
87
|
-
)
|
88
|
-
|
89
|
-
C_mnpq[m, n, p, q] = 2 * C_tmp
|
90
|
-
|
91
|
-
return C_mnpq
|
92
|
-
|
93
|
-
|
94
|
-
def fermi_dirac_derivative() -> float:
|
95
|
-
return 0
|
96
|
-
|
97
|
-
|
98
|
-
def fermi_dirac(energy: np.float64) -> np.float64:
|
99
|
-
if energy > 0:
|
100
|
-
return np.float64(0)
|
101
|
-
else:
|
102
|
-
return np.float64(1)
|
103
|
-
|
104
|
-
|
105
|
-
def calculate_superfluid_weight(
|
106
|
-
h: BaseHamiltonian,
|
107
|
-
k_grid: npt.NDArray[np.float64],
|
108
|
-
direction_1: str,
|
109
|
-
direction_2: str,
|
110
|
-
) -> tuple[float, float]:
|
111
|
-
# number_k_points = len(k_grid)
|
112
|
-
|
113
|
-
s_weight_conv = 0
|
114
|
-
s_weight_geom = 0
|
115
|
-
|
116
|
-
for k in k_grid:
|
117
|
-
C_mnpq = calculate_c_factor(h, k)
|
118
|
-
j_up = calculate_current_operator(h, direction_1, k)
|
119
|
-
j_down = calculate_current_operator(h, direction_2, -k)
|
120
|
-
for m in range(h.number_of_bands):
|
121
|
-
for n in range(h.number_of_bands):
|
122
|
-
for p in range(h.number_of_bands):
|
123
|
-
for q in range(h.number_of_bands):
|
124
|
-
s_weight = C_mnpq[m, n, p, q] * j_up[m, n] * j_down[q, p]
|
125
|
-
if m == n and p == q:
|
126
|
-
s_weight_conv += s_weight
|
127
|
-
else:
|
128
|
-
s_weight_geom += s_weight
|
129
|
-
|
130
|
-
return s_weight_conv, s_weight_geom
|