quant-met 0.0.1__py3-none-any.whl → 0.0.2__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 CHANGED
@@ -1,3 +1,7 @@
1
1
  # SPDX-FileCopyrightText: 2024-present Tjark <tjarksievers@icloud.com>
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
+
5
+ import numpy as np
6
+
7
+ np.seterr(all="ignore")
@@ -0,0 +1,14 @@
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
+ ]
@@ -0,0 +1,172 @@
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
@@ -0,0 +1,124 @@
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
@@ -0,0 +1,39 @@
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
+ )
@@ -0,0 +1,93 @@
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
@@ -0,0 +1,130 @@
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
@@ -0,0 +1,10 @@
1
+ import numpy as np
2
+
3
+
4
+ def _check_valid_float(float_in: float, parameter_name: str) -> float:
5
+ if np.isinf(float_in):
6
+ raise ValueError(f"{parameter_name} must not be Infinity")
7
+ elif np.isnan(float_in):
8
+ raise ValueError(f"{parameter_name} must not be NaN")
9
+ else:
10
+ return float_in
@@ -1,2 +1,7 @@
1
- from . import _plotting
2
- from ._plotting import *
1
+ from ._plotting import generate_bz_path, plot_bandstructure, scatter_into_bz
2
+
3
+ __all__ = [
4
+ "scatter_into_bz",
5
+ "plot_bandstructure",
6
+ "generate_bz_path",
7
+ ]
@@ -1,94 +1,56 @@
1
+ from typing import Any, List, Tuple
2
+
3
+ import matplotlib.axes
4
+ import matplotlib.colors
5
+ import matplotlib.figure
1
6
  import matplotlib.pyplot as plt
2
7
  import numpy as np
3
8
  import numpy.typing as npt
4
9
  from matplotlib.collections import LineCollection
5
-
6
-
7
- def plot_into_bz(
8
- bz_corners, k_points, fig: plt.Figure | None = None, ax: plt.Axes | None = None
9
- ):
10
- if fig is None:
11
- fig, ax = plt.subplots()
12
-
13
- ax.scatter(*zip(*k_points))
14
- ax.scatter(*zip(*bz_corners), alpha=0.8)
15
-
16
- ax.set_aspect("equal", adjustable="box")
17
-
18
- return fig
10
+ from numpy import dtype, generic, ndarray
19
11
 
20
12
 
21
13
  def scatter_into_bz(
22
- bz_corners,
23
- k_points,
24
- data,
25
- fig: plt.Figure | None = None,
26
- ax: plt.Axes | None = None,
27
- ):
28
- if fig is None:
14
+ bz_corners: List[npt.NDArray[np.float64]],
15
+ k_points: npt.NDArray[np.float64],
16
+ data: npt.NDArray[np.float64] | None = None,
17
+ data_label: str | None = None,
18
+ fig_in: matplotlib.figure.Figure | None = None,
19
+ ax_in: matplotlib.axes.Axes | None = None,
20
+ ) -> matplotlib.figure.Figure:
21
+ if fig_in is None or ax_in is None:
29
22
  fig, ax = plt.subplots()
23
+ else:
24
+ fig, ax = fig_in, ax_in
30
25
 
31
- scatter = ax.scatter(*zip(*k_points), c=data, cmap="viridis")
32
- ax.scatter(*zip(*bz_corners), alpha=0.8)
33
- fig.colorbar(scatter, ax=ax, fraction=0.046, pad=0.04)
26
+ if data is not None:
27
+ scatter = ax.scatter(*zip(*k_points), c=data, cmap="viridis")
28
+ fig.colorbar(scatter, ax=ax, fraction=0.046, pad=0.04, label=data_label)
29
+ else:
30
+ ax.scatter(*zip(*k_points))
34
31
 
32
+ ax.scatter(*zip(*bz_corners), alpha=0.8)
35
33
  ax.set_aspect("equal", adjustable="box")
34
+ ax.set_xlabel(r"$k_x\ [1/a_0]$")
35
+ ax.set_ylabel(r"$k_y\ [1/a_0]$")
36
36
 
37
37
  return fig
38
38
 
39
39
 
40
- def plot_bcs_bandstructure(
41
- non_interacting_bands,
42
- deltas,
43
- k_point_list,
44
- ticks,
45
- labels,
46
- fig: plt.Figure | None = None,
47
- ax: plt.Axes | None = None,
48
- ):
49
- if fig is None:
50
- fig, ax = plt.subplots()
51
-
52
- ax.axhline(y=0, alpha=0.7, linestyle="--", color="black")
53
-
54
- for index, (band, delta) in enumerate(zip(non_interacting_bands, deltas)):
55
- ax.plot(
56
- k_point_list,
57
- np.sqrt(band**2 + np.abs(delta) ** 2),
58
- label=f"band {index}, +",
59
- )
60
- ax.plot(
61
- k_point_list,
62
- -np.sqrt(band**2 + np.abs(delta) ** 2),
63
- label=f"band {index}, -",
64
- )
65
- ax.set_box_aspect(1)
66
-
67
- ax.set_xticks(ticks, labels)
68
- ax.set_yticks(range(-5, 6))
69
- ax.set_facecolor("lightgray")
70
- ax.grid(visible=True)
71
- # ax.set_ylim([-5, 5])
72
- ax.tick_params(
73
- axis="both", direction="in", bottom=True, top=True, left=True, right=True
74
- )
75
-
76
- ax.legend()
77
-
78
- return fig, ax
79
-
80
-
81
- def plot_nonint_bandstructure(
82
- bands,
83
- k_point_list,
84
- ticks,
85
- labels,
86
- overlaps: npt.NDArray | None = None,
87
- fig: plt.Figure | None = None,
88
- ax: plt.Axes | None = None,
89
- ):
90
- if fig is None:
40
+ def plot_bandstructure(
41
+ bands: npt.NDArray[np.float64],
42
+ k_point_list: npt.NDArray[np.float64],
43
+ ticks: List[float],
44
+ labels: List[str],
45
+ overlaps: npt.NDArray[np.float64] | None = None,
46
+ overlap_labels: List[str] | None = None,
47
+ fig_in: matplotlib.figure.Figure | None = None,
48
+ ax_in: matplotlib.axes.Axes | None = None,
49
+ ) -> matplotlib.figure.Figure:
50
+ if fig_in is None or ax_in is None:
91
51
  fig, ax = plt.subplots()
52
+ else:
53
+ fig, ax = fig_in, ax_in
92
54
 
93
55
  ax.axhline(y=0, alpha=0.7, linestyle="--", color="black")
94
56
 
@@ -96,13 +58,12 @@ def plot_nonint_bandstructure(
96
58
  for band in bands:
97
59
  ax.plot(k_point_list, band)
98
60
  else:
99
- line = None
100
-
61
+ line = LineCollection(segments=[np.array([(0, 0)])])
101
62
  for band, wx in zip(bands, overlaps):
102
63
  points = np.array([k_point_list, band]).T.reshape(-1, 1, 2)
103
64
  segments = np.concatenate([points[:-1], points[1:]], axis=1)
104
65
 
105
- norm = plt.Normalize(-1, 1)
66
+ norm = matplotlib.colors.Normalize(-1, 1)
106
67
  lc = LineCollection(segments, cmap="seismic", norm=norm)
107
68
  lc.set_array(wx)
108
69
  lc.set_linewidth(2)
@@ -110,14 +71,17 @@ def plot_nonint_bandstructure(
110
71
 
111
72
  colorbar = fig.colorbar(line, fraction=0.046, pad=0.04, ax=ax)
112
73
  color_ticks = [-1, 1]
113
- colorbar.set_ticks(ticks=color_ticks, labels=[r"$w_{\mathrm{Gr}_1}$", r"$w_X$"])
74
+ colorbar.set_ticks(ticks=color_ticks, labels=overlap_labels)
114
75
 
76
+ ax.set_ylim(
77
+ top=np.max(bands) + 0.1 * np.max(bands),
78
+ bottom=np.min(bands) - 0.1 * np.abs(np.min(bands)),
79
+ )
115
80
  ax.set_box_aspect(1)
116
81
  ax.set_xticks(ticks, labels)
117
- ax.set_yticks(range(-5, 6))
82
+ ax.set_ylabel(r"$E\ [t]$")
118
83
  ax.set_facecolor("lightgray")
119
84
  ax.grid(visible=True)
120
- # ax.set_ylim([-5, 5])
121
85
  ax.tick_params(
122
86
  axis="both", direction="in", bottom=True, top=True, left=True, right=True
123
87
  )
@@ -125,7 +89,12 @@ def plot_nonint_bandstructure(
125
89
  return fig
126
90
 
127
91
 
128
- def _generate_part_of_path(p_0, p_1, n, length_whole_path):
92
+ def _generate_part_of_path(
93
+ p_0: npt.NDArray[np.float64],
94
+ p_1: npt.NDArray[np.float64],
95
+ n: int,
96
+ length_whole_path: int,
97
+ ) -> npt.NDArray[np.float64]:
129
98
  distance = np.linalg.norm(p_1 - p_0)
130
99
  number_of_points = int(n * distance / length_whole_path) + 1
131
100
 
@@ -139,7 +108,14 @@ def _generate_part_of_path(p_0, p_1, n, length_whole_path):
139
108
  return k_space_path
140
109
 
141
110
 
142
- def generate_bz_path(points=None, number_of_points=1000):
111
+ def generate_bz_path(
112
+ points: List[Tuple[npt.NDArray[np.float64], str]], number_of_points: int = 1000
113
+ ) -> tuple[
114
+ ndarray[Any, dtype[generic | generic | Any]],
115
+ ndarray[Any, dtype[generic | generic | Any]],
116
+ list[int | Any],
117
+ list[str],
118
+ ]:
143
119
  n = number_of_points
144
120
 
145
121
  cycle = [
quant_met/utils.py ADDED
@@ -0,0 +1,28 @@
1
+ import numpy as np
2
+ import numpy.typing as npt
3
+
4
+
5
+ def generate_uniform_grid(
6
+ ncols: int,
7
+ nrows: int,
8
+ corner_1: npt.NDArray[np.float64],
9
+ corner_2: npt.NDArray[np.float64],
10
+ origin: npt.NDArray[np.float64],
11
+ ) -> npt.NDArray[np.float64]:
12
+ if ncols <= 1 or nrows <= 1:
13
+ raise ValueError("Number of columns and rows must be greater than 1.")
14
+ if np.linalg.norm(corner_1) == 0 or np.linalg.norm(corner_2) == 0:
15
+ raise ValueError("Vectors to the corners cannot be zero.")
16
+
17
+ grid: npt.NDArray[np.float64] = np.concatenate(
18
+ [
19
+ np.linspace(
20
+ origin[0] + i / (nrows - 1) * corner_2,
21
+ origin[1] + corner_1 + i / (nrows - 1) * corner_2,
22
+ num=ncols,
23
+ )
24
+ for i in range(nrows)
25
+ ]
26
+ )
27
+
28
+ return grid
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quant-met
3
- Version: 0.0.1
4
- Summary:
3
+ Version: 0.0.2
4
+ Summary: Calculate superconductivity in flat-band systems.
5
5
  Author: Tjark Sievers
6
6
  Author-email: tsievers@physnet.uni-hamburg.de
7
7
  Requires-Python: >=3.10,<4.0
@@ -9,7 +9,7 @@ Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.10
10
10
  Classifier: Programming Language :: Python :: 3.11
11
11
  Classifier: Programming Language :: Python :: 3.12
12
- Requires-Dist: click (>=8.1.7,<9.0.0)
12
+ Requires-Dist: h5py (>=3.11.0,<4.0.0)
13
13
  Requires-Dist: matplotlib (>=3.8.4,<4.0.0)
14
14
  Requires-Dist: numpy (>=1.26.4,<2.0.0)
15
15
  Requires-Dist: pandas (>=2.2.2,<3.0.0)
@@ -21,18 +21,28 @@ Description-Content-Type: text/markdown
21
21
 
22
22
  [![Test](https://github.com/Ruberhauptmann/quant-met/actions/workflows/test.yml/badge.svg)](https://github.com/Ruberhauptmann/quant-met/actions/workflows/test.yml)
23
23
  [![Coverage Status](https://coveralls.io/repos/github/Ruberhauptmann/quant-met/badge.svg?branch=main)](https://coveralls.io/github/Ruberhauptmann/quant-met?branch=main)
24
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/quant-met)](https://pypi.org/project/quant-met/)
25
+ [![PyPI - Version](https://img.shields.io/pypi/v/quant-met)](https://pypi.org/project/quant-met/)
26
+
27
+ This is a python package to treat superconductivity in flat-band systems.
24
28
 
25
29
  * Documentation: [quant-met.readthedocs.io](https://quant-met.readthedocs.io/en/latest/)
26
30
 
27
31
  ## Installation
28
32
 
29
33
  The package can be installed via
34
+ ```shell
35
+ pip install quant-met
36
+ ```
30
37
 
31
38
  ## Usage
32
39
 
40
+ For usage examples see [documentation](https://quant-met.readthedocs.io/en/latest/examples.html).
41
+
33
42
  ## Contributing
34
43
 
35
- You are welcome to open an issue if you want something changed or added in the software or if there are bugs occuring.
44
+ This is a personal project, very geared to the work I did in my master's thesis.
45
+ If someone is using this and experiencing bugs or want the software extended, feel free to open an issue!
36
46
 
37
47
  ### Developing
38
48
 
@@ -49,13 +59,11 @@ Set up the development environment:
49
59
  * run `make environment`
50
60
  * now activate the conda environment `conda activate quant-met-dev`
51
61
 
52
- Now you can create a separate branch to work on the project.
53
-
54
62
  You can manually run tests using for example `tox -e py312` (for running against python 3.12).
55
- After pushing your branch, all tests will also be run via Gitlab Actions.
63
+ After pushing your branch, all tests will also be run via Github Actions.
56
64
 
57
65
  Using `pre-commit`, automatic linting and formatting is done before every commit, which may cause the first commit to fail.
58
66
  A second try should then succeed.
59
67
 
60
- After you are done working on an issue and all tests are running successful, you can add a new piece of changelog via `scriv create` and make a merge request.
68
+ After you are done working on an issue and all tests are running successful, you can add a new piece of changelog via `scriv create` and make a pull request.
61
69
 
@@ -0,0 +1,15 @@
1
+ quant_met/__init__.py,sha256=Exc923N_e87XwJA_lO22UiG4WQy7dnmPmnuLiHyamRk,149
2
+ quant_met/hamiltonians/__init__.py,sha256=PahN7ppBysli0rKnPLhTBMVaKC_nlD2mJfTvzfrrrRs,427
3
+ quant_met/hamiltonians/_base_hamiltonian.py,sha256=N-8Pik-TByDFeaHUH_X442A6mBOaQWlRcN8UdywfFzE,5857
4
+ quant_met/hamiltonians/_eg_x.py,sha256=QmVdrO26qMPp2AQA3ClHb1cBGHAx2BVjfF22WcpZMHw,3643
5
+ quant_met/hamiltonians/_free_energy.py,sha256=Y7OFL-PFTZsrC4tLY5jegwVhnUeaQwLFE1w_8U9hoPs,1065
6
+ quant_met/hamiltonians/_graphene.py,sha256=p8bRCcNsKguz2B3hbbtp-wGGAQtj6MDIZSwIQoY7Yug,2778
7
+ quant_met/hamiltonians/_superfluid_weight.py,sha256=_YUJ5yE1x4JswuY8gydo5iN7LS0mP2Aeikhhsjy7CeQ,4260
8
+ quant_met/hamiltonians/_utils.py,sha256=w2fMk6APN7kmSF6x4mVk-8CWKul-Ut01oBzQK0V6DbA,311
9
+ quant_met/plotting/__init__.py,sha256=b-r6EpFZdc0aX0OrN_SXTo84ojjV8P_htlnnsmVkQWI,165
10
+ quant_met/plotting/_plotting.py,sha256=YfJB6G4E_htnpBh-eogs1ieKNIXK7Hw0S4_qX9mGmj4,4737
11
+ quant_met/utils.py,sha256=wLW7Q-_RbcKBdxCOJqIW_5BDuReE6leRtagABJvlm6U,821
12
+ quant_met-0.0.2.dist-info/LICENSE.txt,sha256=QO_duPQihSJlaxSLxPAXo52X3esROP5wBkhxqBd1Z4E,1104
13
+ quant_met-0.0.2.dist-info/METADATA,sha256=c_Y95udJ7geJwTpY4Yb4FCwOs2mb718nzlut_5YAmnM,2602
14
+ quant_met-0.0.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
15
+ quant_met-0.0.2.dist-info/RECORD,,
quant_met/__about__.py DELETED
@@ -1,4 +0,0 @@
1
- # SPDX-FileCopyrightText: 2024-present Tjark <tjarksievers@icloud.com>
2
- #
3
- # SPDX-License-Identifier: MIT
4
- __version__ = "0.0.1"
quant_met/bcs/__init__.py DELETED
File without changes
@@ -1,65 +0,0 @@
1
- import numpy as np
2
- import numpy.typing as npt
3
- from scipy import interpolate, optimize
4
-
5
- from quant_met.bcs.gap_equation import gap_equation_real
6
- from quant_met.configuration import DeltaVector
7
- from quant_met.hamiltonians import BaseHamiltonian
8
-
9
-
10
- def generate_k_space_grid(nx, nrows, corner_1, corner_2):
11
- k_points = np.concatenate(
12
- [
13
- np.linspace(
14
- i / (nrows - 1) * corner_2,
15
- corner_1 + i / (nrows - 1) * corner_2,
16
- num=nx,
17
- )
18
- for i in range(nrows)
19
- ]
20
- )
21
-
22
- return k_points
23
-
24
-
25
- def solve_gap_equation(
26
- hamiltonian: BaseHamiltonian, k_points: npt.NDArray, beta: float = 0
27
- ) -> DeltaVector:
28
- energies, bloch_absolute = hamiltonian.generate_bloch(k_points=k_points)
29
-
30
- delta_vector = DeltaVector(
31
- k_points=k_points, initial=0.1, number_bands=hamiltonian.number_bands
32
- )
33
- try:
34
- solution = optimize.fixed_point(
35
- gap_equation_real,
36
- delta_vector.as_1d_vector,
37
- args=(hamiltonian.U, beta, bloch_absolute, energies, len(k_points)),
38
- )
39
- except RuntimeError:
40
- print("Failed")
41
- solution = DeltaVector(
42
- k_points=k_points, initial=0.0, number_bands=hamiltonian.number_bands
43
- ).as_1d_vector
44
-
45
- delta_vector.update_from_1d_vector(solution)
46
-
47
- return delta_vector
48
-
49
-
50
- def interpolate_gap(
51
- delta_vector_on_grid: DeltaVector, bandpath: npt.NDArray
52
- ) -> DeltaVector:
53
- delta_vector_interpolated = DeltaVector(
54
- k_points=bandpath, number_bands=delta_vector_on_grid.number_bands
55
- )
56
-
57
- for band in range(delta_vector_interpolated.number_bands):
58
- delta_vector_interpolated.data.loc[:, f"delta_{band}"] = interpolate.griddata(
59
- delta_vector_on_grid.k_points,
60
- delta_vector_on_grid.data.loc[:, f"delta_{band}"],
61
- bandpath,
62
- method="cubic",
63
- )
64
-
65
- return delta_vector_interpolated
@@ -1,43 +0,0 @@
1
- import numpy as np
2
- import numpy.typing as npt
3
-
4
-
5
- def gap_equation_real(
6
- delta_k: npt.NDArray,
7
- U: npt.NDArray,
8
- beta: float,
9
- bloch_absolute: npt.NDArray,
10
- energies: npt.NDArray,
11
- number_k_points: int,
12
- ):
13
- return_vector = np.zeros(len(delta_k))
14
-
15
- number_bands = int(len(return_vector) / number_k_points)
16
-
17
- for n in range(number_bands):
18
- offset_n = int(len(delta_k) / number_bands * n)
19
- for k_prime_index in range(0, number_k_points):
20
- sum_tmp = 0
21
- for alpha in range(number_bands):
22
- for m in range(number_bands):
23
- offset_m = int(len(delta_k) / number_bands * m)
24
- for k_index in range(0, number_k_points):
25
- sum_tmp += (
26
- U[alpha]
27
- * bloch_absolute[k_prime_index][alpha][n]
28
- * bloch_absolute[k_index][alpha][m]
29
- * delta_k[k_index + offset_m]
30
- / (
31
- 2
32
- * np.sqrt(
33
- (energies[k_index][m]) ** 2
34
- + np.abs(delta_k[k_index + offset_m]) ** 2
35
- )
36
- )
37
- )
38
-
39
- return_vector[k_prime_index + offset_n] = sum_tmp / (
40
- 2.5980762113533156 * number_k_points
41
- )
42
-
43
- return return_vector
quant_met/cli.py DELETED
@@ -1,16 +0,0 @@
1
- import click
2
-
3
- from quant_met.bcs import find_fixpoint
4
-
5
-
6
- @click.command()
7
- def cli():
8
- find_fixpoint.solve_gap_equation()
9
-
10
-
11
- def hello_world():
12
- return "Hello World!"
13
-
14
-
15
- if __name__ == "__main__":
16
- cli()
@@ -1,53 +0,0 @@
1
- import numpy as np
2
- import numpy.typing as npt
3
- import pandas as pd
4
-
5
-
6
- class DeltaVector:
7
- def __init__(
8
- self,
9
- number_bands: int,
10
- hdf_file=None,
11
- k_points: npt.NDArray | None = None,
12
- initial: float | None = None,
13
- ):
14
- self.number_bands = number_bands
15
- if hdf_file is not None:
16
- pass
17
- # self.data = pd.DataFrame(pd.read_hdf(hdf_file, key="table"))
18
- # self.k_points = np.column_stack(
19
- # (np.array(self.data.loc[:, "kx"]), np.array(self.data.loc[:, "ky"]))
20
- # )
21
- else:
22
- self.k_points = k_points
23
- self.data = pd.DataFrame(
24
- # columns=["kx", "ky", "delta_1", "delta_2", "delta_3"],
25
- index=range(len(k_points)),
26
- dtype=np.float64,
27
- )
28
- self.data.loc[:, "kx"] = self.k_points[:, 0]
29
- self.data.loc[:, "ky"] = self.k_points[:, 1]
30
- if initial is not None:
31
- for i in range(number_bands):
32
- self.data.loc[:, f"delta_{i}"] = initial
33
-
34
- def __repr__(self):
35
- return self.data.to_string(index=False)
36
-
37
- def update_from_1d_vector(self, delta: npt.NDArray):
38
- for n in range(self.number_bands):
39
- offset = int(n * len(delta) / self.number_bands)
40
- self.data.loc[:, f"delta_{n}"] = delta[offset : offset + len(self.k_points)]
41
-
42
- def save(self, path):
43
- pass
44
- # self.data.to_hdf(path, key="table", format="table", data_columns=True)
45
-
46
- @property
47
- def as_1d_vector(self) -> npt.NDArray:
48
- return np.concatenate(
49
- [
50
- np.array(self.data.loc[:, f"delta_{n}"].values)
51
- for n in range(self.number_bands)
52
- ]
53
- )
quant_met/hamiltonians.py DELETED
@@ -1,174 +0,0 @@
1
- from abc import ABC, abstractmethod
2
-
3
- import numpy as np
4
- import numpy.typing as npt
5
- import pandas as pd
6
-
7
-
8
- class BaseHamiltonian(ABC):
9
- @property
10
- @abstractmethod
11
- def number_bands(self) -> int:
12
- raise NotImplementedError
13
-
14
- @property
15
- @abstractmethod
16
- def U(self) -> list[float]:
17
- raise NotImplementedError
18
-
19
- @abstractmethod
20
- def _k_space_matrix_one_point(self, k: npt.NDArray, h: npt.NDArray) -> npt.NDArray:
21
- raise NotImplementedError
22
-
23
- def k_space_matrix(self, k: npt.NDArray) -> npt.NDArray:
24
- if k.ndim == 1:
25
- h = np.zeros((1, self.number_bands, self.number_bands), dtype=complex)
26
- h[0] = self._k_space_matrix_one_point(k, h[0])
27
- else:
28
- h = np.zeros(
29
- (k.shape[0], self.number_bands, self.number_bands), dtype=complex
30
- )
31
- for k_index, k in enumerate(k):
32
- h[k_index] = self._k_space_matrix_one_point(k, h[k_index])
33
- return h
34
-
35
- def calculate_bandstructure(self, k_point_list: npt.NDArray):
36
- k_point_matrix = self.k_space_matrix(k_point_list)
37
-
38
- results = pd.DataFrame(
39
- index=range(len(k_point_list)),
40
- dtype=float,
41
- )
42
-
43
- for i, k in enumerate(k_point_list):
44
- energies, eigenvectors = np.linalg.eigh(k_point_matrix[i])
45
-
46
- for band_index in range(self.number_bands):
47
- results.at[i, f"band_{band_index}"] = energies[band_index]
48
-
49
- return results
50
-
51
- def generate_bloch(self, k_points: npt.NDArray):
52
- k_point_matrix = self.k_space_matrix(k_points)
53
-
54
- if k_points.ndim == 1:
55
- energies, bloch = np.linalg.eigh(k_point_matrix[0])
56
- else:
57
- bloch = np.zeros(
58
- (len(k_points), self.number_bands, self.number_bands), dtype=complex
59
- )
60
- energies = np.zeros((len(k_points), self.number_bands))
61
-
62
- for i, k in enumerate(k_points):
63
- energies[i], bloch[i] = np.linalg.eigh(k_point_matrix[i])
64
-
65
- return energies, bloch
66
-
67
-
68
- class GrapheneHamiltonian(BaseHamiltonian):
69
- def __init__(self, t_nn: float, a: float, mu: float, U_gr: float):
70
- self.t_nn = t_nn
71
- self.a = a
72
- self.mu = mu
73
- self.U_gr = U_gr
74
-
75
- @property
76
- def U(self) -> list[float]:
77
- return [self.U_gr, self.U_gr]
78
-
79
- @property
80
- def number_bands(self) -> int:
81
- return 2
82
-
83
- def _k_space_matrix_one_point(self, k: npt.NDArray, h: npt.NDArray) -> npt.NDArray:
84
- t_nn = self.t_nn
85
- a = self.a
86
- mu = self.mu
87
-
88
- h[0, 1] = t_nn * (
89
- np.exp(1j * k[1] * a / np.sqrt(3))
90
- + 2 * np.exp(-0.5j * a / np.sqrt(3) * k[1]) * (np.cos(0.5 * a * k[0]))
91
- )
92
-
93
- h[1, 0] = h[0, 1].conjugate()
94
- h = h - mu * np.eye(2)
95
- return h
96
-
97
-
98
- class EGXHamiltonian(BaseHamiltonian):
99
- def __init__(
100
- self,
101
- t_gr: float,
102
- t_x: float,
103
- V: float,
104
- a: float,
105
- mu: float,
106
- U_gr: float,
107
- U_x: float,
108
- ):
109
- self.t_gr = t_gr
110
- self.t_x = t_x
111
- self.V = V
112
- self.a = a
113
- self.mu = mu
114
- self.U_gr = U_gr
115
- self.U_x = U_x
116
-
117
- @property
118
- def U(self) -> list[float]:
119
- return [self.U_gr, self.U_gr, self.U_x]
120
-
121
- @property
122
- def number_bands(self) -> int:
123
- return 3
124
-
125
- def _k_space_matrix_one_point(self, k: npt.NDArray, h: npt.NDArray) -> npt.NDArray:
126
- t_gr = self.t_gr
127
- t_x = self.t_x
128
- a = self.a
129
- a_0 = a / np.sqrt(3)
130
- V = self.V
131
- mu = self.mu
132
-
133
- h[0, 1] = t_gr * (
134
- np.exp(1j * k[1] * a / np.sqrt(3))
135
- + 2 * np.exp(-0.5j * a / np.sqrt(3) * k[1]) * (np.cos(0.5 * a * k[0]))
136
- )
137
-
138
- h[1, 0] = h[0, 1].conjugate()
139
-
140
- h[2, 0] = V
141
- h[0, 2] = V
142
-
143
- h[2, 2] = (
144
- -2
145
- * t_x
146
- * (
147
- np.cos(a * k[0])
148
- + 2 * np.cos(0.5 * a * k[0]) * np.cos(0.5 * np.sqrt(3) * a * k[1])
149
- )
150
- )
151
- h = h - mu * np.eye(3)
152
- return h
153
-
154
- def calculate_bandstructure(self, k_point_list: npt.NDArray):
155
- k_point_matrix = self.k_space_matrix(k_point_list)
156
-
157
- results = pd.DataFrame(
158
- index=range(len(k_point_list)),
159
- dtype=float,
160
- )
161
-
162
- for i, k in enumerate(k_point_list):
163
- energies, eigenvectors = np.linalg.eigh(k_point_matrix[i])
164
-
165
- for band_index in range(self.number_bands):
166
- results.at[i, f"band_{band_index}"] = energies[band_index]
167
- results.at[i, f"wx_{band_index}"] = (
168
- np.abs(np.dot(eigenvectors[:, band_index], np.array([0, 0, 1])))
169
- ** 2
170
- - np.abs(np.dot(eigenvectors[:, band_index], np.array([1, 0, 0])))
171
- ** 2
172
- )
173
-
174
- return results
@@ -1,15 +0,0 @@
1
- quant_met/__about__.py,sha256=6FvoyjKMderO3l6cPxDWjV4mVs2rLATIwiQbeNG2hv8,126
2
- quant_met/__init__.py,sha256=nK4YcOOHyCkCgRju6gu_7sPIFGqL6w07-uMzTmd1F6o,104
3
- quant_met/bcs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- quant_met/bcs/find_fixpoint.py,sha256=aJj1htdBg7Z8Kxsn_WDYCRK4_gm0vRIPgrkFJH2wd6c,1942
5
- quant_met/bcs/gap_equation.py,sha256=aCP7cDI-AdrF8o-Ois6nHJoX0HGCSwOEOziUE41vgj4,1489
6
- quant_met/cli.py,sha256=4yWAa7AQsilCO4Y3M8U9w9LmaGqJAb-LG5Bio1MEOFw,209
7
- quant_met/configuration.py,sha256=DL4_X47198sA1-C2Lu6W1hXVcqVem80PlFEWWX-Xnwg,1768
8
- quant_met/hamiltonians.py,sha256=0B78trWo2YP1R18GQWU7ZyDSPnOwkI-sM8P-JK7xLkc,4897
9
- quant_met/plotting/__init__.py,sha256=vm92FEALO5yc152WjNf04TgxxXR_JVYH5ha9FjtbXxM,49
10
- quant_met/plotting/_plotting.py,sha256=2CtYshJ53xLCTbcs1VLxKqBXyDu0OhIzFeRruvecJgg,4757
11
- quant_met-0.0.1.dist-info/LICENSE.txt,sha256=QO_duPQihSJlaxSLxPAXo52X3esROP5wBkhxqBd1Z4E,1104
12
- quant_met-0.0.1.dist-info/METADATA,sha256=N-kd1e91pO-jE_EQ04WDVy87qpg7O-9iKKkEHCyy4GM,2127
13
- quant_met-0.0.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
14
- quant_met-0.0.1.dist-info/entry_points.txt,sha256=qnX2LVrCzWILIWh5jQs_uzEPBIos013bRE82kyOr24Q,46
15
- quant_met-0.0.1.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- quantmet=quant_met.cli:cli
3
-