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 CHANGED
@@ -1,7 +1,5 @@
1
- # SPDX-FileCopyrightText: 2024-present Tjark <tjarksievers@icloud.com>
1
+ # SPDX-FileCopyrightText: 2024 Tjark Sievers
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
4
 
5
- import numpy as np
6
-
7
- np.seterr(all="ignore")
5
+ """quant-met, a package to treat superconductivity in flat-band systems."""
@@ -0,0 +1,61 @@
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, quantum_metric_bdg
48
+ from .superfluid_weight import superfluid_weight
49
+
50
+ __all__ = [
51
+ "superfluid_weight",
52
+ "quantum_metric",
53
+ "quantum_metric_bdg",
54
+ "free_energy",
55
+ "free_energy_complex_gap",
56
+ "free_energy_real_gap",
57
+ "free_energy_uniform_pairing",
58
+ "BaseHamiltonian",
59
+ "GrapheneHamiltonian",
60
+ "EGXHamiltonian",
61
+ ]
@@ -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
@@ -0,0 +1,310 @@
1
+ # SPDX-FileCopyrightText: 2024 Tjark Sievers
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ """Provides the base class for Hamiltonians."""
6
+
7
+ import pathlib
8
+ from abc import ABC, abstractmethod
9
+
10
+ import h5py
11
+ import numpy as np
12
+ import numpy.typing as npt
13
+ import pandas as pd
14
+
15
+ from ._utils import _check_valid_array
16
+
17
+
18
+ class BaseHamiltonian(ABC):
19
+ """Base class for Hamiltonians."""
20
+
21
+ @property
22
+ @abstractmethod
23
+ def number_of_bands(self) -> int:
24
+ """Number of bands in the model."""
25
+ raise NotImplementedError
26
+
27
+ @property
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
+ """
37
+ raise NotImplementedError
38
+
39
+ @property
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
+ """
49
+ raise NotImplementedError
50
+
51
+ @delta_orbital_basis.setter
52
+ @abstractmethod
53
+ def delta_orbital_basis(self, new_delta: npt.NDArray[np.complex64]) -> None:
54
+ raise NotImplementedError
55
+
56
+ @abstractmethod
57
+ def hamiltonian(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]:
58
+ """
59
+ Return the normal state Hamiltonian in orbital basis.
60
+
61
+ Parameters
62
+ ----------
63
+ k : :class:`numpy.ndarray`
64
+ List of k points.
65
+
66
+ Returns
67
+ -------
68
+ :class:`numpy.ndarray`
69
+ Hamiltonian in matrix form.
70
+
71
+ """
72
+ raise NotImplementedError
73
+
74
+ @abstractmethod
75
+ def hamiltonian_derivative(
76
+ self, k: npt.NDArray[np.float64], direction: str
77
+ ) -> npt.NDArray[np.complex64]:
78
+ """
79
+ Deriative of the Hamiltonian.
80
+
81
+ Parameters
82
+ ----------
83
+ k: :class:`numpy.ndarray`
84
+ List of k points.
85
+ direction: str
86
+ Direction for derivative, either 'x' oder 'y'.
87
+
88
+ Returns
89
+ -------
90
+ :class:`numpy.ndarray`
91
+ Derivative of Hamiltonian.
92
+
93
+ """
94
+ raise NotImplementedError
95
+
96
+ def save(self, filename: pathlib.Path) -> None:
97
+ """
98
+ Save the Hamiltonian as a HDF5 file.
99
+
100
+ Parameters
101
+ ----------
102
+ filename : :class:`pathlib.Path`
103
+ Filename to save the Hamiltonian to, should end in .hdf5
104
+
105
+ """
106
+ with h5py.File(f"{filename}", "w") as f:
107
+ f.create_dataset("delta", data=self.delta_orbital_basis)
108
+ for key, value in vars(self).items():
109
+ if not key.startswith("_"):
110
+ f.attrs[key] = value
111
+
112
+ @classmethod
113
+ def from_file(cls, filename: pathlib.Path) -> "BaseHamiltonian":
114
+ """
115
+ Initialise a Hamiltonian from a HDF5 file.
116
+
117
+ Parameters
118
+ ----------
119
+ filename : :class:`pathlib.Path`
120
+ File to load the Hamiltonian from.
121
+
122
+ """
123
+ with h5py.File(f"{filename}", "r") as f:
124
+ config_dict = dict(f.attrs.items())
125
+ config_dict["delta"] = f["delta"][()]
126
+
127
+ return cls(**config_dict)
128
+
129
+ def bdg_hamiltonian(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]:
130
+ """
131
+ Bogoliuobov de Genne Hamiltonian.
132
+
133
+ Parameters
134
+ ----------
135
+ k : :class:`numpy.ndarray`
136
+ List of k points.
137
+
138
+ Returns
139
+ -------
140
+ :class:`numpy.ndarray`
141
+ BdG Hamiltonian.
142
+
143
+ """
144
+ assert _check_valid_array(k)
145
+ if k.ndim == 1:
146
+ k = np.expand_dims(k, axis=0)
147
+
148
+ h = np.zeros(
149
+ (k.shape[0], 2 * self.number_of_bands, 2 * self.number_of_bands), dtype=np.complex64
150
+ )
151
+
152
+ h[:, 0 : self.number_of_bands, 0 : self.number_of_bands] = self.hamiltonian(k)
153
+ h[
154
+ :,
155
+ self.number_of_bands : 2 * self.number_of_bands,
156
+ self.number_of_bands : 2 * self.number_of_bands,
157
+ ] = -self.hamiltonian(-k).conjugate()
158
+
159
+ for i in range(self.number_of_bands):
160
+ h[:, self.number_of_bands + i, i] = self.delta_orbital_basis[i]
161
+ h[:, 0:2, 2:4] = h[:, 2:4, 0:2].copy().conjugate()
162
+
163
+ return h.squeeze()
164
+
165
+ def bdg_hamiltonian_derivative(
166
+ self, k: npt.NDArray[np.float64], direction: str
167
+ ) -> npt.NDArray[np.complex64]:
168
+ """
169
+ Deriative of the BdG Hamiltonian.
170
+
171
+ Parameters
172
+ ----------
173
+ k: :class:`numpy.ndarray`
174
+ List of k points.
175
+ direction: str
176
+ Direction for derivative, either 'x' oder 'y'.
177
+
178
+ Returns
179
+ -------
180
+ :class:`numpy.ndarray`
181
+ Derivative of Hamiltonian.
182
+
183
+ """
184
+ assert _check_valid_array(k)
185
+ if k.ndim == 1:
186
+ k = np.expand_dims(k, axis=0)
187
+
188
+ h = np.zeros(
189
+ (k.shape[0], 2 * self.number_of_bands, 2 * self.number_of_bands), dtype=np.complex64
190
+ )
191
+
192
+ h[:, 0 : self.number_of_bands, 0 : self.number_of_bands] = self.hamiltonian_derivative(
193
+ k, direction
194
+ )
195
+ h[
196
+ :,
197
+ self.number_of_bands : 2 * self.number_of_bands,
198
+ self.number_of_bands : 2 * self.number_of_bands,
199
+ ] = -self.hamiltonian_derivative(-k, direction).conjugate()
200
+
201
+ return h.squeeze()
202
+
203
+ def diagonalize_nonint(
204
+ self, k: npt.NDArray[np.float64]
205
+ ) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]:
206
+ """
207
+ Diagonalize the normal state Hamiltonian.
208
+
209
+ Parameters
210
+ ----------
211
+ k : :class:`numpy.ndarray`
212
+ List of k points.
213
+
214
+ Returns
215
+ -------
216
+ :class:`numpy.ndarray`
217
+ Eigenvalues of the normal state Hamiltonian.
218
+ :class:`numpy.ndarray`
219
+ Diagonalising matrix of the normal state Hamiltonian.
220
+
221
+ """
222
+ k_point_matrix = self.hamiltonian(k)
223
+ if k_point_matrix.ndim == 2:
224
+ k_point_matrix = np.expand_dims(k_point_matrix, axis=0)
225
+ k = np.expand_dims(k, axis=0)
226
+
227
+ bloch_wavefunctions = np.zeros(
228
+ (len(k), self.number_of_bands, self.number_of_bands),
229
+ dtype=complex,
230
+ )
231
+ band_energies = np.zeros((len(k), self.number_of_bands))
232
+
233
+ for i in range(len(k)):
234
+ band_energies[i], bloch_wavefunctions[i] = np.linalg.eigh(k_point_matrix[i])
235
+
236
+ return band_energies.squeeze(), bloch_wavefunctions.squeeze()
237
+
238
+ def diagonalize_bdg(
239
+ self, k: npt.NDArray[np.float64]
240
+ ) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.complex64]]:
241
+ """
242
+ Diagonalize the BdG Hamiltonian.
243
+
244
+ Parameters
245
+ ----------
246
+ k : :class:`numpy.ndarray`
247
+ List of k points.
248
+
249
+ Returns
250
+ -------
251
+ :class:`numpy.ndarray`
252
+ Eigenvalues of the BdG Hamiltonian.
253
+ :class:`numpy.ndarray`
254
+ Diagonalising matrix of the BdG Hamiltonian.
255
+
256
+ """
257
+ bdg_matrix = self.bdg_hamiltonian(k)
258
+ if bdg_matrix.ndim == 2:
259
+ bdg_matrix = np.expand_dims(bdg_matrix, axis=0)
260
+ k = np.expand_dims(k, axis=0)
261
+
262
+ bdg_wavefunctions = np.zeros(
263
+ (len(k), 2 * self.number_of_bands, 2 * self.number_of_bands),
264
+ dtype=np.complex64,
265
+ )
266
+ bdg_energies = np.zeros((len(k), 2 * self.number_of_bands))
267
+
268
+ for i in range(len(k)):
269
+ bdg_energies[i], bdg_wavefunctions[i] = np.linalg.eigh(bdg_matrix[i])
270
+
271
+ return bdg_energies.squeeze(), bdg_wavefunctions.squeeze()
272
+
273
+ def calculate_bandstructure(
274
+ self,
275
+ k: npt.NDArray[np.float64],
276
+ overlaps: tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]] | None = None,
277
+ ) -> pd.DataFrame:
278
+ """
279
+ Calculate the band structure.
280
+
281
+ Parameters
282
+ ----------
283
+ k : :class:`numpy.ndarray`
284
+ List of k points.
285
+ overlaps : tuple(:class:`numpy.ndarray`, :class:`numpy.ndarray`), optional
286
+ Overlaps.
287
+
288
+ Returns
289
+ -------
290
+ `pandas.DataFrame`
291
+ Band structure.
292
+
293
+ """
294
+ results = pd.DataFrame(
295
+ index=range(len(k)),
296
+ dtype=float,
297
+ )
298
+ energies, wavefunctions = self.diagonalize_nonint(k)
299
+
300
+ for i, (energy_k, wavefunction_k) in enumerate(zip(energies, wavefunctions, strict=False)):
301
+ for band_index in range(self.number_of_bands):
302
+ results.loc[i, f"band_{band_index}"] = energy_k[band_index]
303
+
304
+ if overlaps is not None:
305
+ results.loc[i, f"wx_{band_index}"] = (
306
+ np.abs(np.dot(wavefunction_k[:, band_index], overlaps[0])) ** 2
307
+ - np.abs(np.dot(wavefunction_k[:, band_index], overlaps[1])) ** 2
308
+ )
309
+
310
+ return results
@@ -0,0 +1,173 @@
1
+ # SPDX-FileCopyrightText: 2024 Tjark Sievers
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ """Provides the implementation for the EG-X model."""
6
+
7
+ from typing import Any
8
+
9
+ import numpy as np
10
+ import numpy.typing as npt
11
+
12
+ from ._utils import _check_valid_array, _validate_float
13
+ from .base_hamiltonian import BaseHamiltonian
14
+
15
+
16
+ class EGXHamiltonian(BaseHamiltonian):
17
+ """Hamiltonian for the EG-X model."""
18
+
19
+ def __init__(
20
+ self,
21
+ hopping_gr: float,
22
+ hopping_x: float,
23
+ hopping_x_gr_a: float,
24
+ lattice_constant: float,
25
+ mu: float,
26
+ coloumb_gr: float,
27
+ coloumb_x: float,
28
+ delta: npt.NDArray[np.complex64] | None = None,
29
+ *args: tuple[Any, ...],
30
+ **kwargs: tuple[dict[str, Any], ...],
31
+ ) -> None:
32
+ del args
33
+ del kwargs
34
+ self.hopping_gr = _validate_float(hopping_gr, "Hopping graphene")
35
+ self.hopping_x = _validate_float(hopping_x, "Hopping impurity")
36
+ self.hopping_x_gr_a = _validate_float(hopping_x_gr_a, "Hybridisation")
37
+ self.lattice_constant = _validate_float(lattice_constant, "Lattice constant")
38
+ self.mu = _validate_float(mu, "Chemical potential")
39
+ self.coloumb_gr = _validate_float(coloumb_gr, "Coloumb interaction graphene")
40
+ self.coloumb_x = _validate_float(coloumb_x, "Coloumb interaction impurity")
41
+ self._coloumb_orbital_basis = np.array([self.coloumb_gr, self.coloumb_gr, self.coloumb_x])
42
+ self._number_of_bands = 3
43
+ if delta is None:
44
+ self._delta_orbital_basis = np.zeros(3, dtype=np.complex64)
45
+ else:
46
+ self._delta_orbital_basis = delta
47
+
48
+ @property
49
+ def coloumb_orbital_basis(self) -> npt.NDArray[np.float64]: # noqa: D102
50
+ return self._coloumb_orbital_basis
51
+
52
+ @property
53
+ def delta_orbital_basis(self) -> npt.NDArray[np.complex64]: # noqa: D102
54
+ return self._delta_orbital_basis
55
+
56
+ @delta_orbital_basis.setter
57
+ def delta_orbital_basis(self, new_delta: npt.NDArray[np.complex64]) -> None:
58
+ self._delta_orbital_basis = new_delta
59
+
60
+ @property
61
+ def number_of_bands(self) -> int: # noqa: D102
62
+ return self._number_of_bands
63
+
64
+ def hamiltonian(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]:
65
+ """
66
+ Return the normal state Hamiltonian in orbital basis.
67
+
68
+ Parameters
69
+ ----------
70
+ k : :class:`numpy.ndarray`
71
+ List of k points.
72
+
73
+ Returns
74
+ -------
75
+ :class:`numpy.ndarray`
76
+ Hamiltonian in matrix form.
77
+
78
+ """
79
+ assert _check_valid_array(k)
80
+
81
+ t_gr = self.hopping_gr
82
+ t_x = self.hopping_x
83
+ a = self.lattice_constant
84
+ v = self.hopping_x_gr_a
85
+ mu = self.mu
86
+ if k.ndim == 1:
87
+ k = np.expand_dims(k, axis=0)
88
+
89
+ h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex64)
90
+
91
+ h[:, 0, 1] = -t_gr * (
92
+ np.exp(1j * k[:, 1] * a / np.sqrt(3))
93
+ + 2 * np.exp(-0.5j * a / np.sqrt(3) * k[:, 1]) * (np.cos(0.5 * a * k[:, 0]))
94
+ )
95
+
96
+ h[:, 1, 0] = h[:, 0, 1].conjugate()
97
+
98
+ h[:, 2, 0] = v
99
+ h[:, 0, 2] = v
100
+
101
+ h[:, 2, 2] = (
102
+ -2
103
+ * t_x
104
+ * (
105
+ np.cos(a * k[:, 0])
106
+ + 2 * np.cos(0.5 * a * k[:, 0]) * np.cos(0.5 * np.sqrt(3) * a * k[:, 1])
107
+ )
108
+ )
109
+ h[:, 0, 0] -= mu
110
+ h[:, 1, 1] -= mu
111
+ h[:, 2, 2] -= mu
112
+
113
+ return h.squeeze()
114
+
115
+ def hamiltonian_derivative(
116
+ self, k: npt.NDArray[np.float64], direction: str
117
+ ) -> npt.NDArray[np.complex64]:
118
+ """
119
+ Deriative of the Hamiltonian.
120
+
121
+ Parameters
122
+ ----------
123
+ k: :class:`numpy.ndarray`
124
+ List of k points.
125
+ direction: str
126
+ Direction for derivative, either 'x' oder 'y'.
127
+
128
+ Returns
129
+ -------
130
+ :class:`numpy.ndarray`
131
+ Derivative of Hamiltonian.
132
+
133
+ """
134
+ assert _check_valid_array(k)
135
+ assert direction in ["x", "y"]
136
+
137
+ t_gr = self.hopping_gr
138
+ t_x = self.hopping_x
139
+ a = self.lattice_constant
140
+ if k.ndim == 1:
141
+ k = np.expand_dims(k, axis=0)
142
+
143
+ h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex64)
144
+
145
+ if direction == "x":
146
+ h[:, 0, 1] = (
147
+ t_gr * a * np.exp(-0.5j * a / np.sqrt(3) * k[:, 1]) * np.sin(0.5 * a * k[:, 0])
148
+ )
149
+ h[:, 1, 0] = h[:, 0, 1].conjugate()
150
+ h[:, 2, 2] = (
151
+ 2
152
+ * a
153
+ * t_x
154
+ * (
155
+ np.sin(a * k[:, 0])
156
+ + np.sin(0.5 * a * k[:, 0]) * np.cos(0.5 * np.sqrt(3) * a * k[:, 1])
157
+ )
158
+ )
159
+ else:
160
+ h[:, 0, 1] = (
161
+ -t_gr
162
+ * 1j
163
+ * a
164
+ / np.sqrt(3)
165
+ * (
166
+ np.exp(1j * a / np.sqrt(3) * k[:, 1])
167
+ - np.exp(-0.5j * a / np.sqrt(3) * k[:, 1]) * np.cos(0.5 * a * k[:, 0])
168
+ )
169
+ )
170
+ h[:, 1, 0] = h[:, 0, 1].conjugate()
171
+ h[:, 2, 2] = np.sqrt(3) * a * t_x * np.cos(0.5 * np.sqrt(3) * a * k[:, 1])
172
+
173
+ return h.squeeze()
@@ -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)