quant-met 0.0.27__py3-none-any.whl → 0.1.0__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 -7
- quant_met/bdg/__init__.py +26 -0
- quant_met/bdg/bdg_hamiltonian.py +97 -0
- quant_met/bdg/gap_equation.py +127 -0
- quant_met/bdg/sc_current.py +60 -0
- quant_met/bdg/superfluid_weight.py +110 -0
- quant_met/cli/__init__.py +0 -5
- quant_met/cli/crit_temp.py +18 -16
- quant_met/cli/main.py +8 -5
- quant_met/cli/q_analysis.py +60 -0
- quant_met/cli/q_loop.py +91 -0
- quant_met/cli/scf.py +44 -23
- quant_met/parameters/__init__.py +0 -26
- quant_met/parameters/control.py +57 -0
- quant_met/parameters/main.py +2 -55
- quant_met/quantum_geometry/__init__.py +13 -0
- quant_met/quantum_geometry/qgt.py +37 -0
- quant_met/routines/__init__.py +22 -0
- quant_met/routines/analyse_q_data.py +226 -0
- quant_met/routines/loop_over_q.py +154 -0
- quant_met/{mean_field → routines}/search_crit_temp.py +71 -48
- quant_met/{mean_field → routines}/self_consistency.py +32 -28
- quant_met/utils.py +1 -6
- {quant_met-0.0.27.dist-info → quant_met-0.1.0.dist-info}/METADATA +5 -11
- quant_met-0.1.0.dist-info/RECORD +28 -0
- quant_met/cli/_utils.py +0 -32
- quant_met/geometry/__init__.py +0 -36
- quant_met/geometry/base_lattice.py +0 -100
- quant_met/geometry/bz_path.py +0 -90
- quant_met/geometry/graphene.py +0 -48
- quant_met/geometry/square.py +0 -47
- quant_met/mean_field/__init__.py +0 -38
- quant_met/mean_field/_utils.py +0 -17
- quant_met/mean_field/hamiltonians/__init__.py +0 -34
- quant_met/mean_field/hamiltonians/base_hamiltonian.py +0 -793
- quant_met/mean_field/hamiltonians/dressed_graphene.py +0 -118
- quant_met/mean_field/hamiltonians/graphene.py +0 -95
- quant_met/mean_field/hamiltonians/one_band_tight_binding.py +0 -70
- quant_met/mean_field/hamiltonians/three_band_tight_binding.py +0 -85
- quant_met/mean_field/hamiltonians/two_band_tight_binding.py +0 -76
- quant_met/parameters/hamiltonians.py +0 -182
- quant_met/plotting/__init__.py +0 -31
- quant_met/plotting/plotting.py +0 -215
- quant_met-0.0.27.dist-info/RECORD +0 -33
- {quant_met-0.0.27.dist-info → quant_met-0.1.0.dist-info}/WHEEL +0 -0
- {quant_met-0.0.27.dist-info → quant_met-0.1.0.dist-info}/entry_points.txt +0 -0
- {quant_met-0.0.27.dist-info → quant_met-0.1.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -0,0 +1,154 @@
|
|
1
|
+
"""Function to run search for critical temperature."""
|
2
|
+
|
3
|
+
import logging
|
4
|
+
from functools import partial
|
5
|
+
from multiprocessing import Pool
|
6
|
+
from typing import Any
|
7
|
+
|
8
|
+
import numpy as np
|
9
|
+
import numpy.typing as npt
|
10
|
+
import pandas as pd
|
11
|
+
import sisl
|
12
|
+
|
13
|
+
from quant_met import bdg
|
14
|
+
|
15
|
+
from .self_consistency import self_consistency_loop
|
16
|
+
|
17
|
+
logger = logging.getLogger(__name__)
|
18
|
+
|
19
|
+
MAX_Q = 0.5
|
20
|
+
|
21
|
+
|
22
|
+
def is_gap_zero(result: dict[str, float], atol: float = 1e-8) -> bool:
|
23
|
+
"""Check if all delta values in result are (approximately) zero."""
|
24
|
+
deltas = np.array([x for key, x in result.items() if key.startswith("delta")])
|
25
|
+
return np.isclose(np.max(np.abs(deltas)), 0, atol=atol)
|
26
|
+
|
27
|
+
|
28
|
+
def adjust_q_upper_bound(
|
29
|
+
gap_for_q_partial: partial[dict[str, Any] | None], initial_q: float = 0.5
|
30
|
+
) -> float:
|
31
|
+
"""
|
32
|
+
Adjust q_upper_bound until gap is non-zero or exceeds upper limit.
|
33
|
+
|
34
|
+
Returns the adjusted q_upper_bound.
|
35
|
+
"""
|
36
|
+
q_upper_bound = initial_q
|
37
|
+
|
38
|
+
while True:
|
39
|
+
result_tmp: dict[str, float] | None = gap_for_q_partial(q_upper_bound)
|
40
|
+
|
41
|
+
if result_tmp is None or is_gap_zero(result_tmp):
|
42
|
+
q_upper_bound /= 2
|
43
|
+
else:
|
44
|
+
break
|
45
|
+
|
46
|
+
while True:
|
47
|
+
result_tmp = gap_for_q_partial(q_upper_bound)
|
48
|
+
|
49
|
+
if result_tmp is None or is_gap_zero(result_tmp):
|
50
|
+
q_upper_bound *= 1.1
|
51
|
+
if q_upper_bound > MAX_Q:
|
52
|
+
break
|
53
|
+
else:
|
54
|
+
break
|
55
|
+
|
56
|
+
return q_upper_bound
|
57
|
+
|
58
|
+
|
59
|
+
def _gap_for_q( # noqa: PLR0913
|
60
|
+
q_fraction: float,
|
61
|
+
hamiltonian: sisl.Hamiltonian,
|
62
|
+
kgrid: sisl.MonkhorstPack,
|
63
|
+
hubbard_int_orbital_basis: npt.NDArray[np.float64],
|
64
|
+
epsilon: float,
|
65
|
+
temp: float,
|
66
|
+
max_iter: int = 1000,
|
67
|
+
) -> dict[str, Any] | None: # pragma: no cover
|
68
|
+
beta = np.inf if temp == 0 else 1 / temp
|
69
|
+
q = q_fraction * hamiltonian.geometry.rcell[0]
|
70
|
+
data_dict: dict[str, Any] = {
|
71
|
+
"q_fraction": q_fraction,
|
72
|
+
}
|
73
|
+
try:
|
74
|
+
gap = self_consistency_loop(
|
75
|
+
hamiltonian=hamiltonian,
|
76
|
+
kgrid=kgrid,
|
77
|
+
beta=beta,
|
78
|
+
hubbard_int_orbital_basis=hubbard_int_orbital_basis,
|
79
|
+
epsilon=epsilon,
|
80
|
+
max_iter=max_iter,
|
81
|
+
q=q,
|
82
|
+
)
|
83
|
+
except RuntimeError:
|
84
|
+
logger.exception("Did not converge.")
|
85
|
+
return None
|
86
|
+
else:
|
87
|
+
bdg_energies, bdg_wavefunctions = bdg.diagonalize_bdg(
|
88
|
+
hamiltonian=hamiltonian,
|
89
|
+
kgrid=kgrid,
|
90
|
+
delta_orbital_basis=gap,
|
91
|
+
q=q,
|
92
|
+
)
|
93
|
+
current = bdg.calculate_current_density(
|
94
|
+
hamiltonian=hamiltonian,
|
95
|
+
k=kgrid,
|
96
|
+
bdg_energies=bdg_energies,
|
97
|
+
bdg_wavefunctions=bdg_wavefunctions,
|
98
|
+
beta=beta,
|
99
|
+
)
|
100
|
+
data_dict.update({f"delta_{orbital}": gap[orbital] for orbital in range(len(gap))})
|
101
|
+
data_dict.update(
|
102
|
+
{
|
103
|
+
"current_x": current[0],
|
104
|
+
"current_y": current[1],
|
105
|
+
"current_abs": np.linalg.norm(current),
|
106
|
+
},
|
107
|
+
)
|
108
|
+
return data_dict
|
109
|
+
|
110
|
+
|
111
|
+
def loop_over_q( # noqa: PLR0913
|
112
|
+
hamiltonian: sisl.Hamiltonian,
|
113
|
+
kgrid: sisl.MonkhorstPack,
|
114
|
+
hubbard_int_orbital_basis: npt.NDArray[np.float64],
|
115
|
+
epsilon: float,
|
116
|
+
max_iter: int,
|
117
|
+
n_q_points: int,
|
118
|
+
crit_temps: npt.NDArray[np.float64],
|
119
|
+
) -> dict[str, pd.DataFrame]: # pragma: no cover
|
120
|
+
"""Loop over q."""
|
121
|
+
logger.info("Start search for upper bound for q.")
|
122
|
+
|
123
|
+
crit_temp = np.max(crit_temps)
|
124
|
+
temp_list = [crit_temp * x for x in [0.65, 0.7, 0.75, 0.8, 0.85, 0.87, 0.89, 0.91, 0.93, 0.95]]
|
125
|
+
|
126
|
+
delta_vs_q = {}
|
127
|
+
for temp in temp_list:
|
128
|
+
gap_for_q_partial = partial(
|
129
|
+
_gap_for_q,
|
130
|
+
hamiltonian=hamiltonian,
|
131
|
+
kgrid=kgrid,
|
132
|
+
hubbard_int_orbital_basis=hubbard_int_orbital_basis,
|
133
|
+
epsilon=epsilon,
|
134
|
+
max_iter=max_iter,
|
135
|
+
temp=temp,
|
136
|
+
)
|
137
|
+
q_upper_bound = adjust_q_upper_bound(gap_for_q_partial, initial_q=0.5)
|
138
|
+
logger.info("q upper bound: %s", q_upper_bound)
|
139
|
+
|
140
|
+
q_list = np.linspace(
|
141
|
+
0,
|
142
|
+
q_upper_bound,
|
143
|
+
num=n_q_points,
|
144
|
+
)
|
145
|
+
|
146
|
+
with Pool() as p:
|
147
|
+
delta_vs_q_list = [x for x in p.map(gap_for_q_partial, q_list) if x is not None] # type: ignore[arg-type]
|
148
|
+
|
149
|
+
delta_vs_q_tmp = (
|
150
|
+
pd.DataFrame(delta_vs_q_list).sort_values(by=["q_fraction"]).reset_index(drop=True)
|
151
|
+
)
|
152
|
+
delta_vs_q[f"{temp}"] = delta_vs_q_tmp
|
153
|
+
|
154
|
+
return delta_vs_q
|
@@ -1,8 +1,3 @@
|
|
1
|
-
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
-
# SPDX-FileCopyrightText: 2025 Tjark Sievers
|
3
|
-
#
|
4
|
-
# SPDX-License-Identifier: MIT
|
5
|
-
|
6
1
|
"""Function to run search for critical temperature."""
|
7
2
|
|
8
3
|
import logging
|
@@ -15,16 +10,16 @@ import matplotlib.pyplot as plt
|
|
15
10
|
import numpy as np
|
16
11
|
import numpy.typing as npt
|
17
12
|
import pandas as pd
|
13
|
+
import sisl
|
18
14
|
from scipy import stats
|
19
15
|
|
20
|
-
from quant_met import plotting
|
21
|
-
from quant_met.parameters import GenericParameters
|
22
|
-
|
23
|
-
from .hamiltonians import BaseHamiltonian
|
24
16
|
from .self_consistency import self_consistency_loop
|
25
17
|
|
26
18
|
logger = logging.getLogger(__name__)
|
27
19
|
|
20
|
+
MIN_NUMBER_OF_T_POINTS_FITTING = 4
|
21
|
+
MAX_ITERATIONS_GET_BOUNDS = 100
|
22
|
+
|
28
23
|
|
29
24
|
def _get_bounds(
|
30
25
|
initial_temp: float,
|
@@ -38,7 +33,9 @@ def _get_bounds(
|
|
38
33
|
temp = initial_temp
|
39
34
|
direction = "down"
|
40
35
|
iterations = 0
|
41
|
-
while (
|
36
|
+
while (
|
37
|
+
found_zero_gap and found_nonzero_gap
|
38
|
+
) is False and iterations < MAX_ITERATIONS_GET_BOUNDS:
|
42
39
|
logger.info("Trying temperature: %s", temp)
|
43
40
|
data_dict = gap_for_temp_partial(temp)
|
44
41
|
logger.info("Result: %s", data_dict)
|
@@ -51,7 +48,9 @@ def _get_bounds(
|
|
51
48
|
found_zero_gap = True
|
52
49
|
temp = 0.5 * temp
|
53
50
|
elif np.allclose(
|
54
|
-
gap,
|
51
|
+
gap,
|
52
|
+
zero_temperature_gap,
|
53
|
+
atol=0.10 * np.max(np.abs(zero_temperature_gap)),
|
55
54
|
):
|
56
55
|
logger.info("Found temperature with nonzero gap.")
|
57
56
|
nonzero_gap_temp = temp
|
@@ -62,7 +61,7 @@ def _get_bounds(
|
|
62
61
|
temp = 0.5 * temp
|
63
62
|
else:
|
64
63
|
logger.info(
|
65
|
-
"Gap is neither zero nor equal to the zero gap. Increasing temperature."
|
64
|
+
"Gap is neither zero nor equal to the zero gap. Increasing temperature.",
|
66
65
|
)
|
67
66
|
temp = 2 * temp
|
68
67
|
elif direction == "down":
|
@@ -86,7 +85,8 @@ def _get_bounds(
|
|
86
85
|
|
87
86
|
|
88
87
|
def _fit_for_crit_temp(
|
89
|
-
delta_vs_temp: pd.DataFrame,
|
88
|
+
delta_vs_temp: pd.DataFrame,
|
89
|
+
orbital: int,
|
90
90
|
) -> tuple[pd.DataFrame | None, pd.DataFrame, float | None, float | None]: # pragma: no cover
|
91
91
|
filtered_results = delta_vs_temp.iloc[
|
92
92
|
np.where(
|
@@ -104,21 +104,22 @@ def _fit_for_crit_temp(
|
|
104
104
|
rtol=1e-2,
|
105
105
|
atol=0,
|
106
106
|
),
|
107
|
-
)
|
108
|
-
)
|
107
|
+
),
|
108
|
+
),
|
109
109
|
)
|
110
110
|
]
|
111
111
|
|
112
112
|
err = []
|
113
|
-
if len(filtered_results) <=
|
113
|
+
if len(filtered_results) <= MIN_NUMBER_OF_T_POINTS_FITTING:
|
114
114
|
return None, filtered_results, None, None
|
115
115
|
|
116
|
-
lengths = range(
|
116
|
+
lengths = range(MIN_NUMBER_OF_T_POINTS_FITTING, len(filtered_results))
|
117
117
|
|
118
118
|
for length in lengths:
|
119
119
|
range_results = filtered_results.iloc[-length:]
|
120
120
|
linreg = stats.linregress(
|
121
|
-
range_results["T"],
|
121
|
+
range_results["T"],
|
122
|
+
np.abs(range_results[f"delta_{orbital}"]) ** 2,
|
122
123
|
)
|
123
124
|
err.append(linreg.stderr)
|
124
125
|
|
@@ -129,64 +130,83 @@ def _fit_for_crit_temp(
|
|
129
130
|
return range_results, filtered_results, linreg.intercept, linreg.slope
|
130
131
|
|
131
132
|
|
132
|
-
def _gap_for_temp(
|
133
|
+
def _gap_for_temp( # noqa: PLR0913
|
133
134
|
temp: float,
|
134
|
-
|
135
|
-
|
135
|
+
hamiltonian: sisl.Hamiltonian,
|
136
|
+
kgrid: sisl.MonkhorstPack,
|
137
|
+
hubbard_int_orbital_basis: npt.NDArray[np.float64],
|
136
138
|
epsilon: float,
|
137
139
|
max_iter: int = 1000,
|
140
|
+
delta_init: npt.NDArray[np.complex128] | None = None,
|
141
|
+
q: npt.NDArray[np.float64] | None = None,
|
138
142
|
) -> dict[str, Any] | None: # pragma: no cover
|
139
143
|
beta = np.inf if temp == 0 else 1 / temp
|
140
|
-
h.beta = beta
|
141
144
|
try:
|
142
|
-
|
145
|
+
gap = self_consistency_loop(
|
146
|
+
hamiltonian=hamiltonian,
|
147
|
+
kgrid=kgrid,
|
148
|
+
beta=beta,
|
149
|
+
hubbard_int_orbital_basis=hubbard_int_orbital_basis,
|
150
|
+
epsilon=epsilon,
|
151
|
+
max_iter=max_iter,
|
152
|
+
delta_init=delta_init,
|
153
|
+
q=q,
|
154
|
+
)
|
143
155
|
except RuntimeError:
|
144
156
|
logger.exception("Did not converge.")
|
145
157
|
return None
|
146
158
|
else:
|
147
|
-
data_dict = {
|
159
|
+
data_dict: dict[str, Any] = {
|
148
160
|
"T": temp,
|
149
161
|
}
|
150
|
-
|
151
|
-
data_dict.update(
|
152
|
-
{
|
153
|
-
f"delta_{orbital}": zero_temperature_gap[orbital]
|
154
|
-
for orbital in range(len(zero_temperature_gap))
|
155
|
-
}
|
156
|
-
)
|
162
|
+
data_dict.update({f"delta_{orbital}": gap[orbital] for orbital in range(len(gap))})
|
157
163
|
return data_dict
|
158
164
|
|
159
165
|
|
160
|
-
def search_crit_temp(
|
161
|
-
|
162
|
-
|
166
|
+
def search_crit_temp( # noqa: PLR0913
|
167
|
+
hamiltonian: sisl.Hamiltonian,
|
168
|
+
kgrid: sisl.MonkhorstPack,
|
169
|
+
hubbard_int_orbital_basis: npt.NDArray[np.float64],
|
163
170
|
epsilon: float,
|
164
171
|
max_iter: int,
|
165
172
|
n_temp_points: int,
|
173
|
+
q: npt.NDArray[np.float64] | None = None,
|
174
|
+
beta_init: float | None = None,
|
166
175
|
) -> tuple[pd.DataFrame, list[float], matplotlib.figure.Figure]: # pragma: no cover
|
167
176
|
"""Search for critical temperature."""
|
168
177
|
logger.info("Start search for bounds for T_C")
|
169
|
-
|
178
|
+
beta = 10 * hubbard_int_orbital_basis[0] if beta_init is None else beta_init
|
179
|
+
temp = 1 / beta if not np.isinf(beta) else 1e-8
|
170
180
|
|
171
181
|
delta_vs_temp_list = []
|
172
182
|
critical_temp_list = []
|
173
183
|
|
174
184
|
gap_for_temp_partial = partial(
|
175
|
-
_gap_for_temp,
|
185
|
+
_gap_for_temp,
|
186
|
+
hamiltonian=hamiltonian,
|
187
|
+
kgrid=kgrid,
|
188
|
+
hubbard_int_orbital_basis=hubbard_int_orbital_basis,
|
189
|
+
epsilon=epsilon,
|
190
|
+
max_iter=max_iter,
|
191
|
+
q=q,
|
176
192
|
)
|
177
193
|
|
178
194
|
logger.info("Calculating zero temperature gap")
|
179
195
|
data_dict = gap_for_temp_partial(0)
|
180
|
-
|
196
|
+
if data_dict is None:
|
197
|
+
err_msg = "Calculation for T = 0 did not converge."
|
198
|
+
raise ValueError(err_msg)
|
181
199
|
logger.info("Result: %s", data_dict)
|
182
200
|
|
183
201
|
zero_temperature_gap = np.array(
|
184
|
-
[data_dict[key] for key in data_dict if key.startswith("delta")]
|
202
|
+
[data_dict[key] for key in data_dict if key.startswith("delta")],
|
185
203
|
)
|
186
204
|
delta_vs_temp_list.append(data_dict)
|
187
205
|
|
188
206
|
delta_vs_temp_list_tmp, zero_gap_temp, nonzero_gap_temp = _get_bounds(
|
189
|
-
temp,
|
207
|
+
temp,
|
208
|
+
gap_for_temp_partial,
|
209
|
+
zero_temperature_gap,
|
190
210
|
)
|
191
211
|
delta_vs_temp_list.extend(delta_vs_temp_list_tmp)
|
192
212
|
logger.info("Temperature bounds: %s to %s", nonzero_gap_temp, zero_gap_temp)
|
@@ -200,12 +220,18 @@ def search_crit_temp(
|
|
200
220
|
endpoint=False,
|
201
221
|
),
|
202
222
|
np.linspace(
|
203
|
-
nonzero_gap_temp,
|
223
|
+
nonzero_gap_temp,
|
224
|
+
zero_gap_temp,
|
225
|
+
num=int(0.9 * n_temp_points),
|
226
|
+
endpoint=False,
|
204
227
|
),
|
205
228
|
np.linspace(
|
206
|
-
zero_gap_temp,
|
229
|
+
zero_gap_temp,
|
230
|
+
1.2 * zero_gap_temp,
|
231
|
+
num=int(0.05 * n_temp_points),
|
232
|
+
endpoint=True,
|
207
233
|
),
|
208
|
-
]
|
234
|
+
],
|
209
235
|
)
|
210
236
|
|
211
237
|
with Pool() as p:
|
@@ -214,14 +240,12 @@ def search_crit_temp(
|
|
214
240
|
|
215
241
|
delta_vs_temp = pd.DataFrame(delta_vs_temp_list).sort_values(by=["T"]).reset_index(drop=True)
|
216
242
|
|
217
|
-
fit_fig, fit_axs = plt.subplots(
|
218
|
-
nrows=1, ncols=h.number_of_bands, figsize=(h.number_of_bands * 6, 6)
|
219
|
-
)
|
243
|
+
fit_fig, fit_axs = plt.subplots(nrows=1, ncols=hamiltonian.no, figsize=(hamiltonian.no * 6, 6))
|
220
244
|
|
221
|
-
for orbital in range(
|
245
|
+
for orbital in range(hamiltonian.no):
|
222
246
|
fit_range, filtered_range, intercept, slope = _fit_for_crit_temp(delta_vs_temp, orbital)
|
223
247
|
|
224
|
-
ax = fit_axs if
|
248
|
+
ax = fit_axs if hamiltonian.no == 1 else fit_axs[orbital]
|
225
249
|
|
226
250
|
if fit_range is not None and intercept is not None and slope is not None:
|
227
251
|
critical_temp = -intercept / slope
|
@@ -249,7 +273,6 @@ def search_crit_temp(
|
|
249
273
|
"--x",
|
250
274
|
color=f"C{orbital}",
|
251
275
|
)
|
252
|
-
ax = plotting.format_plot(ax)
|
253
276
|
ax.set_ylabel(r"$\vert\Delta\vert^2\ [t^2]$")
|
254
277
|
|
255
278
|
return delta_vs_temp, critical_temp_list, fit_fig
|
@@ -1,28 +1,27 @@
|
|
1
|
-
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
-
# SPDX-FileCopyrightText: 2025 Tjark Sievers
|
3
|
-
#
|
4
|
-
# SPDX-License-Identifier: MIT
|
5
|
-
|
6
1
|
"""Self-consistency loop."""
|
7
2
|
|
8
3
|
import logging
|
9
4
|
|
10
5
|
import numpy as np
|
11
6
|
import numpy.typing as npt
|
7
|
+
import sisl
|
8
|
+
from numpy import complexfloating, dtype, ndarray
|
12
9
|
|
13
|
-
from quant_met.
|
14
|
-
from quant_met.parameters import GenericParameters
|
10
|
+
from quant_met.bdg import gap_equation
|
15
11
|
|
16
12
|
logger = logging.getLogger(__name__)
|
17
13
|
|
18
14
|
|
19
|
-
def self_consistency_loop(
|
20
|
-
|
21
|
-
|
15
|
+
def self_consistency_loop( # noqa: PLR0913
|
16
|
+
hamiltonian: sisl.Hamiltonian,
|
17
|
+
kgrid: sisl.MonkhorstPack,
|
18
|
+
beta: float,
|
19
|
+
hubbard_int_orbital_basis: npt.NDArray[np.float64],
|
22
20
|
epsilon: float,
|
23
21
|
max_iter: int = 1000,
|
24
22
|
delta_init: npt.NDArray[np.complex128] | None = None,
|
25
|
-
|
23
|
+
q: npt.NDArray[np.float64] | None = None,
|
24
|
+
) -> ndarray[tuple[int, ...], dtype[complexfloating]]:
|
26
25
|
"""Self-consistently solves the gap equation for a given Hamiltonian.
|
27
26
|
|
28
27
|
This function performs a self-consistency loop to solve the gap equation
|
@@ -32,11 +31,12 @@ def self_consistency_loop(
|
|
32
31
|
|
33
32
|
Parameters
|
34
33
|
----------
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
q
|
35
|
+
kgrid
|
36
|
+
hubbard_int_orbital_basis
|
37
|
+
beta
|
38
|
+
hamiltonian : sisl.Hamiltonian
|
39
|
+
The Hamiltonian object.
|
40
40
|
|
41
41
|
epsilon : float
|
42
42
|
The convergence criterion. The loop will terminate when the change
|
@@ -64,12 +64,12 @@ def self_consistency_loop(
|
|
64
64
|
|
65
65
|
if delta_init is None:
|
66
66
|
rng = np.random.default_rng()
|
67
|
-
delta_init = np.zeros(shape=
|
68
|
-
delta_init += (0.2 * rng.random(size=
|
69
|
-
0.2 * rng.random(size=
|
67
|
+
delta_init = np.zeros(shape=hamiltonian.no, dtype=np.complex128)
|
68
|
+
delta_init += (0.2 * rng.random(size=hamiltonian.no) - 1) + 1.0j * (
|
69
|
+
0.2 * rng.random(size=hamiltonian.no) - 1
|
70
70
|
)
|
71
|
-
|
72
|
-
|
71
|
+
logger.debug("Initial gaps set to: %s", delta_init)
|
72
|
+
delta = delta_init
|
73
73
|
|
74
74
|
iteration_count = 0
|
75
75
|
while True:
|
@@ -80,16 +80,20 @@ def self_consistency_loop(
|
|
80
80
|
|
81
81
|
logger.debug("Iteration %d: Computing new gaps.", iteration_count)
|
82
82
|
|
83
|
-
new_gap =
|
83
|
+
new_gap = gap_equation(
|
84
|
+
hamiltonian=hamiltonian,
|
85
|
+
kgrid=kgrid,
|
86
|
+
q=q,
|
87
|
+
beta=beta,
|
88
|
+
hubbard_int_orbital_basis=hubbard_int_orbital_basis,
|
89
|
+
delta_orbital_basis=delta,
|
90
|
+
)
|
84
91
|
|
85
92
|
logger.debug("New gaps computed: %s", new_gap)
|
86
93
|
|
87
|
-
if np.allclose(
|
88
|
-
h.delta_orbital_basis = new_gap # type: ignore[assignment]
|
94
|
+
if np.allclose(delta, new_gap, atol=1e-10, rtol=epsilon):
|
89
95
|
logger.info("Convergence achieved after %d iterations.", iteration_count)
|
90
|
-
return
|
96
|
+
return new_gap
|
91
97
|
|
92
98
|
mixing_greed = 0.2
|
93
|
-
|
94
|
-
logger.debug("Updated gaps: %s", h.delta_orbital_basis)
|
95
|
-
logger.debug("Change in gaps: %s", np.abs(h.delta_orbital_basis - new_gap))
|
99
|
+
delta = mixing_greed * new_gap + (1 - mixing_greed) * delta
|
quant_met/utils.py
CHANGED
@@ -1,8 +1,3 @@
|
|
1
|
-
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
-
# SPDX-FileCopyrightText: 2025 Tjark Sievers
|
3
|
-
#
|
4
|
-
# SPDX-License-Identifier: MIT
|
5
|
-
|
6
1
|
"""
|
7
2
|
Utility functions (:mod:`quant_met.utils`)
|
8
3
|
==========================================
|
@@ -67,7 +62,7 @@ def generate_uniform_grid(
|
|
67
62
|
num=ncols,
|
68
63
|
)
|
69
64
|
for i in range(nrows)
|
70
|
-
]
|
65
|
+
],
|
71
66
|
)
|
72
67
|
|
73
68
|
return grid
|
@@ -1,8 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: quant-met
|
3
|
-
Version: 0.0
|
3
|
+
Version: 0.1.0
|
4
4
|
Summary: Calculate superconductivity in flat-band systems.
|
5
|
-
Author-email: Tjark Sievers <
|
5
|
+
Author-email: Tjark Sievers <tjarksievers@icloud.com>
|
6
6
|
License-File: LICENSE.txt
|
7
7
|
Requires-Python: >=3.11
|
8
8
|
Requires-Dist: click>=8.1.8
|
@@ -10,28 +10,22 @@ Requires-Dist: h5py>=3.12.1
|
|
10
10
|
Requires-Dist: matplotlib>=3.10.0
|
11
11
|
Requires-Dist: numba>=0.61.0
|
12
12
|
Requires-Dist: numpy>=2.1
|
13
|
-
Requires-Dist: numpydantic>=1.6.
|
13
|
+
Requires-Dist: numpydantic>=1.6.8
|
14
14
|
Requires-Dist: pandas>=2.2.3
|
15
15
|
Requires-Dist: pydantic>=2.10.4
|
16
|
-
Requires-Dist: pythtb>=1.8.0
|
17
16
|
Requires-Dist: pyyaml>=6.0.2
|
18
17
|
Requires-Dist: scipy>=1.15.0
|
18
|
+
Requires-Dist: sisl[viz]>0.16.0
|
19
19
|
Requires-Dist: tables>=3.10.2
|
20
|
+
Requires-Dist: tbmodels>=1.4.3
|
20
21
|
Description-Content-Type: text/markdown
|
21
22
|
|
22
|
-
<!--
|
23
|
-
SPDX-FileCopyrightText: 2024 Tjark Sievers
|
24
|
-
SPDX-FileCopyrightText: 2025 Tjark Sievers
|
25
|
-
|
26
|
-
SPDX-License-Identifier: MIT
|
27
|
-
-->
|
28
23
|
|
29
24
|
# quant-met
|
30
25
|
|
31
26
|
[](https://zenodo.org/badge/latestdoi/800628635)
|
32
27
|
[](https://github.com/Ruberhauptmann/quant-met/actions/workflows/unit_tests.yml)
|
33
28
|
[](https://coveralls.io/github/Ruberhauptmann/quant-met?branch=main)
|
34
|
-
[](https://pypi.org/project/quant-met/)
|
35
29
|
[](https://pypi.org/project/quant-met/)
|
36
30
|
|
37
31
|
quant-met is a python package to treat superconductivity in flat-band systems.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
quant_met/__init__.py,sha256=9WVEpcOuJ6ObayeK9u9Vkm2D-iPyb5Olc4PZdLWPORk,186
|
2
|
+
quant_met/utils.py,sha256=pr-J_ElUDKxmSdErxsz4Eclvojoejbaup-Fg12QKMVQ,1989
|
3
|
+
quant_met/bdg/__init__.py,sha256=RHxvGyCTDeK4vlIm807K9wJkLOI0jGA3ibuq0YRfo74,605
|
4
|
+
quant_met/bdg/bdg_hamiltonian.py,sha256=6zKW_a7XVXYk61RFvJjp_av4Gh7KSMqLUV1Ir8iS1sY,2708
|
5
|
+
quant_met/bdg/gap_equation.py,sha256=VyGbQxNxjbUkp-NHzGs3-5vejc6CcBfvmtXREWRS3eI,3372
|
6
|
+
quant_met/bdg/sc_current.py,sha256=fRX4KH1J7IY1T8Oxrpd_0RJd8fvPDNeP3yCg-UwRLpI,1840
|
7
|
+
quant_met/bdg/superfluid_weight.py,sha256=rLS6fK41Pt8aXxPL0KNVvK0dMWwYdbZ0eAqBEoGvAQ8,4207
|
8
|
+
quant_met/cli/__init__.py,sha256=11q_R4KoAKZy2EOuUgnAn4GxbS9yyTA6nSjKpDl-UjI,175
|
9
|
+
quant_met/cli/crit_temp.py,sha256=l4jPXY07z75FD7xgACrj_C2B3t3xX-yQeWlcnkEGIAA,2179
|
10
|
+
quant_met/cli/main.py,sha256=DNgXguBfVpp-pddmN-RKePeO1R2Dsr_b97BKei1MMG0,2074
|
11
|
+
quant_met/cli/q_analysis.py,sha256=H-3o-of_xEv3c1uUqtREGKroY-pk8Yu7RWXmLxi0xpU,1986
|
12
|
+
quant_met/cli/q_loop.py,sha256=6T01sS65pzqOwLx5gymC-6kbEa3XJjGerujfkB4D1cQ,3524
|
13
|
+
quant_met/cli/scf.py,sha256=jpFoIpC0ghf48lK7SfNeTXXADEtyCzv6kzyMvdcBF1Y,3283
|
14
|
+
quant_met/parameters/__init__.py,sha256=d1XBoH8siW0fNRz5I8tpI2-JQfiSjadFBcmQANV97Zk,448
|
15
|
+
quant_met/parameters/control.py,sha256=ZxtAf35Gnb2LwooazcFrdb1d2b_sipGHIUtF5bZwTIg,1384
|
16
|
+
quant_met/parameters/main.py,sha256=P0o7f4o2woHNtLEqYJnO7dXdKEX3t_dsCky8-Sr_W88,977
|
17
|
+
quant_met/quantum_geometry/__init__.py,sha256=RMD7pNHPFAJuOtUfNiV4XssA1RjL6h1eZBsh76Fc-8Y,185
|
18
|
+
quant_met/quantum_geometry/qgt.py,sha256=jdYUxBOeKYYR96Zex2xIVOVCsT11HZ1NVrUBmmjTlLY,1358
|
19
|
+
quant_met/routines/__init__.py,sha256=a8xHRD6j4v8lkrwGSzwmj4BHUg2tgTN0Hp0Vpu4863Y,479
|
20
|
+
quant_met/routines/analyse_q_data.py,sha256=8q32GBB2ftYgdjWJ1_EpvcNJO9_Fn1kfKSaWLhIAJeY,8409
|
21
|
+
quant_met/routines/loop_over_q.py,sha256=3yYhCf_Xo7ziT5Pj4HmLDvvq8crbb7-MdJOjmyluYao,4460
|
22
|
+
quant_met/routines/search_crit_temp.py,sha256=phK2pJTibj8sgtxOghEJkurbG4xt2LRq23MTdfwygAE,9598
|
23
|
+
quant_met/routines/self_consistency.py,sha256=nb-gRzyEd24kc6ZU2O53ov07Zg3pN6wSz-9jjo68RCM,3071
|
24
|
+
quant_met-0.1.0.dist-info/METADATA,sha256=Eos9y8wuLVX9JdvRwf5QXAnD8XDgL22NpRd9MCSwDXo,1837
|
25
|
+
quant_met-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
26
|
+
quant_met-0.1.0.dist-info/entry_points.txt,sha256=1Al3Kt-cMeQxwMp84ZSNL0qFwlbOVBu1o8A19MH8lEU,48
|
27
|
+
quant_met-0.1.0.dist-info/licenses/LICENSE.txt,sha256=QO_duPQihSJlaxSLxPAXo52X3esROP5wBkhxqBd1Z4E,1104
|
28
|
+
quant_met-0.1.0.dist-info/RECORD,,
|
quant_met/cli/_utils.py
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
-
# SPDX-FileCopyrightText: 2025 Tjark Sievers
|
3
|
-
#
|
4
|
-
# SPDX-License-Identifier: MIT
|
5
|
-
|
6
|
-
from quant_met.mean_field.hamiltonians import BaseHamiltonian
|
7
|
-
from quant_met.parameters import HamiltonianParameters
|
8
|
-
|
9
|
-
|
10
|
-
def _hamiltonian_factory(
|
11
|
-
classname: str, parameters: HamiltonianParameters
|
12
|
-
) -> BaseHamiltonian[HamiltonianParameters]:
|
13
|
-
"""Create a Hamiltonian by its class name.
|
14
|
-
|
15
|
-
Parameters
|
16
|
-
----------
|
17
|
-
classname: str
|
18
|
-
The name of the Hamiltonian class to instantiate.
|
19
|
-
parameters: HamiltonianParameters
|
20
|
-
An instance of HamiltonianParameters containing all necessary
|
21
|
-
configuration for the specific Hamiltonian.
|
22
|
-
|
23
|
-
Returns
|
24
|
-
-------
|
25
|
-
BaseHamiltonian[HamiltonianParameters]
|
26
|
-
An instance of the specified Hamiltonian class.
|
27
|
-
"""
|
28
|
-
from quant_met.mean_field import hamiltonians
|
29
|
-
|
30
|
-
cls = getattr(hamiltonians, classname)
|
31
|
-
h: BaseHamiltonian[HamiltonianParameters] = cls(parameters)
|
32
|
-
return h
|
quant_met/geometry/__init__.py
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
-
# SPDX-FileCopyrightText: 2025 Tjark Sievers
|
3
|
-
#
|
4
|
-
# SPDX-License-Identifier: MIT
|
5
|
-
|
6
|
-
"""
|
7
|
-
Geometry
|
8
|
-
========
|
9
|
-
|
10
|
-
.. currentmodule:: quant_met.geometry
|
11
|
-
|
12
|
-
Functions
|
13
|
-
---------
|
14
|
-
|
15
|
-
.. autosummary::
|
16
|
-
:toctree: generated/
|
17
|
-
|
18
|
-
generate_bz_path
|
19
|
-
|
20
|
-
Classes
|
21
|
-
-------
|
22
|
-
|
23
|
-
.. autosummary::
|
24
|
-
:toctree: generated/
|
25
|
-
|
26
|
-
BaseLattice
|
27
|
-
GrapheneLattice
|
28
|
-
SquareLattice
|
29
|
-
""" # noqa: D205, D400
|
30
|
-
|
31
|
-
from .base_lattice import BaseLattice
|
32
|
-
from .bz_path import generate_bz_path
|
33
|
-
from .graphene import GrapheneLattice
|
34
|
-
from .square import SquareLattice
|
35
|
-
|
36
|
-
__all__ = ["BaseLattice", "GrapheneLattice", "SquareLattice", "generate_bz_path"]
|