quant-met 0.0.27__py3-none-any.whl → 0.1.1__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 +95 -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.1.dist-info}/METADATA +5 -11
- quant_met-0.1.1.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.1.dist-info}/WHEEL +0 -0
- {quant_met-0.0.27.dist-info → quant_met-0.1.1.dist-info}/entry_points.txt +0 -0
- {quant_met-0.0.27.dist-info → quant_met-0.1.1.dist-info}/licenses/LICENSE.txt +0 -0
quant_met/__init__.py
CHANGED
@@ -1,10 +1,5 @@
|
|
1
|
-
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
-
# SPDX-FileCopyrightText: 2025 Tjark Sievers
|
3
|
-
#
|
4
|
-
# SPDX-License-Identifier: MIT
|
5
|
-
|
6
1
|
"""quant-met, a package to treat superconductivity in flat-band systems."""
|
7
2
|
|
8
|
-
from . import
|
3
|
+
from . import bdg, cli, quantum_geometry, routines
|
9
4
|
|
10
|
-
__all__ = ["
|
5
|
+
__all__ = ["bdg", "cli", "quantum_geometry", "routines"]
|
@@ -0,0 +1,26 @@
|
|
1
|
+
"""
|
2
|
+
Bogoliubov-de Gennes (BdG)
|
3
|
+
==========================
|
4
|
+
|
5
|
+
.. autosummary::
|
6
|
+
:toctree: generated/
|
7
|
+
|
8
|
+
bdg_hamiltonian
|
9
|
+
diagonalize_bdg
|
10
|
+
gap_equation
|
11
|
+
calculate_superfluid_weight
|
12
|
+
calculate_current_density
|
13
|
+
""" # noqa: D205, D400
|
14
|
+
|
15
|
+
from .bdg_hamiltonian import bdg_hamiltonian, diagonalize_bdg
|
16
|
+
from .gap_equation import gap_equation
|
17
|
+
from .sc_current import calculate_current_density
|
18
|
+
from .superfluid_weight import calculate_superfluid_weight
|
19
|
+
|
20
|
+
__all__ = [
|
21
|
+
"bdg_hamiltonian",
|
22
|
+
"calculate_current_density",
|
23
|
+
"calculate_superfluid_weight",
|
24
|
+
"diagonalize_bdg",
|
25
|
+
"gap_equation",
|
26
|
+
]
|
@@ -0,0 +1,97 @@
|
|
1
|
+
"""BdG Hamiltonian."""
|
2
|
+
|
3
|
+
import numpy as np
|
4
|
+
import numpy.typing as npt
|
5
|
+
import sisl
|
6
|
+
|
7
|
+
|
8
|
+
def bdg_hamiltonian(
|
9
|
+
hamiltonian: sisl.Hamiltonian,
|
10
|
+
k: npt.NDArray[np.floating],
|
11
|
+
delta_orbital_basis: npt.NDArray[np.complexfloating],
|
12
|
+
q: npt.NDArray[np.floating] | None = None,
|
13
|
+
) -> npt.NDArray[np.complexfloating]:
|
14
|
+
"""
|
15
|
+
Construct the BdG Hamiltonian at momentum k.
|
16
|
+
|
17
|
+
Parameters
|
18
|
+
----------
|
19
|
+
hamiltonian : sisl.Hamiltonian
|
20
|
+
The normal-state tight-binding Hamiltonian.
|
21
|
+
k : np.ndarray
|
22
|
+
k-point(s) in reduced coordinates. Shape: (3,) or (N_k, 3).
|
23
|
+
delta_orbital_basis : np.ndarray
|
24
|
+
Pairing amplitudes in the orbital basis. Shape: (N_orbitals,)
|
25
|
+
q : np.ndarray, optional
|
26
|
+
Pairing momentum (e.g. for FFLO). Default is 0.
|
27
|
+
|
28
|
+
Returns
|
29
|
+
-------
|
30
|
+
np.ndarray
|
31
|
+
The BdG Hamiltonian. Shape: (2N, 2N) or (N_k, 2N, 2N)
|
32
|
+
"""
|
33
|
+
k = np.atleast_2d(k)
|
34
|
+
n_k_points = k.shape[0]
|
35
|
+
n_orbitals = hamiltonian.no
|
36
|
+
|
37
|
+
if q is None:
|
38
|
+
q = np.zeros(3)
|
39
|
+
|
40
|
+
h_bdg = np.zeros((n_k_points, 2 * n_orbitals, 2 * n_orbitals), dtype=np.complex128)
|
41
|
+
|
42
|
+
for i, kpt in enumerate(k):
|
43
|
+
h_k = hamiltonian.Hk(kpt).toarray()
|
44
|
+
h_mkq = hamiltonian.Hk(q - kpt).toarray()
|
45
|
+
|
46
|
+
h_bdg[i, :n_orbitals, :n_orbitals] = h_k
|
47
|
+
h_bdg[i, n_orbitals:, n_orbitals:] = -h_mkq.conj()
|
48
|
+
|
49
|
+
for j in range(n_orbitals):
|
50
|
+
h_bdg[i, n_orbitals + j, j] = delta_orbital_basis[j]
|
51
|
+
|
52
|
+
h_bdg[i, :n_orbitals, n_orbitals:] = h_bdg[i, n_orbitals:, :n_orbitals].conj().T
|
53
|
+
|
54
|
+
return h_bdg.squeeze()
|
55
|
+
|
56
|
+
|
57
|
+
def diagonalize_bdg(
|
58
|
+
hamiltonian: sisl.Hamiltonian,
|
59
|
+
kgrid: sisl.MonkhorstPack,
|
60
|
+
delta_orbital_basis: np.ndarray,
|
61
|
+
q: npt.NDArray[np.floating] | None,
|
62
|
+
) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.complex128]]:
|
63
|
+
"""Diagonalizes the BdG Hamiltonian.
|
64
|
+
|
65
|
+
This method computes the eigenvalues and eigenvectors of the Bogoliubov-de
|
66
|
+
Gennes Hamiltonian, providing insight into the quasiparticle excitations in
|
67
|
+
superconducting states.
|
68
|
+
|
69
|
+
Parameters
|
70
|
+
----------
|
71
|
+
q
|
72
|
+
kgrid
|
73
|
+
delta_orbital_basis
|
74
|
+
hamiltonian
|
75
|
+
|
76
|
+
Returns
|
77
|
+
-------
|
78
|
+
tuple
|
79
|
+
- :class:`numpy.ndarray`: Eigenvalues of the BdG Hamiltonian.
|
80
|
+
- :class:`numpy.ndarray`: Eigenvectors corresponding to the eigenvalues of the
|
81
|
+
BdG Hamiltonian.
|
82
|
+
"""
|
83
|
+
energies = []
|
84
|
+
wavefunctions = []
|
85
|
+
|
86
|
+
for kpt in kgrid:
|
87
|
+
bdg = bdg_hamiltonian(
|
88
|
+
hamiltonian=hamiltonian,
|
89
|
+
delta_orbital_basis=delta_orbital_basis,
|
90
|
+
k=kpt,
|
91
|
+
q=q,
|
92
|
+
)
|
93
|
+
e, v = np.linalg.eigh(bdg)
|
94
|
+
energies.append(e)
|
95
|
+
wavefunctions.append(v)
|
96
|
+
|
97
|
+
return np.array(energies), np.array(wavefunctions)
|
@@ -0,0 +1,127 @@
|
|
1
|
+
"""Gap equation."""
|
2
|
+
|
3
|
+
import numpy as np
|
4
|
+
import numpy.typing as npt
|
5
|
+
import sisl
|
6
|
+
from numba import jit
|
7
|
+
|
8
|
+
from .bdg_hamiltonian import diagonalize_bdg
|
9
|
+
|
10
|
+
|
11
|
+
def gap_equation( # noqa: PLR0913
|
12
|
+
hamiltonian: sisl.Hamiltonian,
|
13
|
+
beta: float,
|
14
|
+
hubbard_int_orbital_basis: npt.NDArray[np.float64],
|
15
|
+
delta_orbital_basis: npt.NDArray[np.complex128],
|
16
|
+
kgrid: sisl.MonkhorstPack,
|
17
|
+
q: npt.NDArray[np.float64] | None,
|
18
|
+
) -> npt.NDArray[np.complexfloating]:
|
19
|
+
"""Gap equation.
|
20
|
+
|
21
|
+
Parameters
|
22
|
+
----------
|
23
|
+
q
|
24
|
+
kgrid
|
25
|
+
delta_orbital_basis
|
26
|
+
hubbard_int_orbital_basis
|
27
|
+
beta
|
28
|
+
hamiltonian
|
29
|
+
|
30
|
+
Returns
|
31
|
+
-------
|
32
|
+
New delta
|
33
|
+
"""
|
34
|
+
bdg_energies, bdg_wavefunctions = diagonalize_bdg(
|
35
|
+
hamiltonian=hamiltonian,
|
36
|
+
kgrid=kgrid,
|
37
|
+
q=q,
|
38
|
+
delta_orbital_basis=delta_orbital_basis,
|
39
|
+
)
|
40
|
+
delta = np.zeros(hamiltonian.no, dtype=np.complex128)
|
41
|
+
return gap_equation_loop(
|
42
|
+
bdg_energies=bdg_energies,
|
43
|
+
bdg_wavefunctions=bdg_wavefunctions,
|
44
|
+
delta=delta,
|
45
|
+
beta=beta,
|
46
|
+
hubbard_int_orbital_basis=hubbard_int_orbital_basis,
|
47
|
+
kgrid=kgrid.k,
|
48
|
+
weights=kgrid.weight,
|
49
|
+
)
|
50
|
+
|
51
|
+
|
52
|
+
@jit
|
53
|
+
def gap_equation_loop( # noqa: PLR0913
|
54
|
+
bdg_energies: npt.NDArray[np.float64],
|
55
|
+
bdg_wavefunctions: npt.NDArray[np.complex128],
|
56
|
+
delta: npt.NDArray[np.complex128],
|
57
|
+
beta: float,
|
58
|
+
hubbard_int_orbital_basis: npt.NDArray[np.float64],
|
59
|
+
kgrid: npt.NDArray[np.float64],
|
60
|
+
weights: npt.NDArray[np.float64],
|
61
|
+
) -> npt.NDArray[np.complexfloating]:
|
62
|
+
"""Calculate the gap equation.
|
63
|
+
|
64
|
+
The gap equation determines the order parameter for superconductivity by
|
65
|
+
relating the pairings to the spectral properties of the BdG Hamiltonian.
|
66
|
+
|
67
|
+
Parameters
|
68
|
+
----------
|
69
|
+
kgrid
|
70
|
+
bdg_energies : :class:`numpy.ndarray`
|
71
|
+
BdG energies
|
72
|
+
bdg_wavefunctions : :class:`numpy.ndarray`
|
73
|
+
BdG wavefunctions
|
74
|
+
delta : :class:`numpy.ndarray`
|
75
|
+
Delta
|
76
|
+
beta : :class:`float`
|
77
|
+
Beta
|
78
|
+
hubbard_int_orbital_basis : :class:`numpy.ndarray`
|
79
|
+
Hubard interaction in orbital basis
|
80
|
+
k : :class:`numpy.ndarray`
|
81
|
+
List of k points in reciprocal space.
|
82
|
+
|
83
|
+
Returns
|
84
|
+
-------
|
85
|
+
:class:`numpy.ndarray`
|
86
|
+
New pairing gap in orbital basis, adjusted to remove global phase.
|
87
|
+
"""
|
88
|
+
number_of_bands = len(delta)
|
89
|
+
new_delta = np.zeros_like(delta)
|
90
|
+
|
91
|
+
for i in range(number_of_bands):
|
92
|
+
sum_tmp = 0
|
93
|
+
for k_index in range(len(kgrid)):
|
94
|
+
weight = weights[k_index]
|
95
|
+
|
96
|
+
for j in range(2 * number_of_bands):
|
97
|
+
sum_tmp += (
|
98
|
+
np.conj(bdg_wavefunctions[k_index, i, j])
|
99
|
+
* bdg_wavefunctions[k_index, i + number_of_bands, j]
|
100
|
+
* fermi_dirac(bdg_energies[k_index, j], beta)
|
101
|
+
* weight
|
102
|
+
)
|
103
|
+
new_delta[i] = (-hubbard_int_orbital_basis[i] * sum_tmp).conjugate()
|
104
|
+
|
105
|
+
new_delta *= np.exp(-1j * np.angle(new_delta[np.argmax(np.abs(new_delta))]))
|
106
|
+
return new_delta
|
107
|
+
|
108
|
+
|
109
|
+
@jit
|
110
|
+
def fermi_dirac(energy: npt.NDArray[np.floating], beta: float) -> npt.NDArray[np.floating]:
|
111
|
+
"""Fermi dirac distribution.
|
112
|
+
|
113
|
+
Parameters
|
114
|
+
----------
|
115
|
+
energy
|
116
|
+
beta
|
117
|
+
|
118
|
+
Returns
|
119
|
+
-------
|
120
|
+
fermi_dirac
|
121
|
+
|
122
|
+
"""
|
123
|
+
return (
|
124
|
+
np.where(energy < 0, 1.0, 0.0)
|
125
|
+
if np.isinf(beta)
|
126
|
+
else np.asarray(1 / (1 + np.exp(beta * energy)))
|
127
|
+
)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
"""Calculate supercurrent."""
|
2
|
+
|
3
|
+
import numpy as np
|
4
|
+
import sisl
|
5
|
+
from numpy.typing import NDArray
|
6
|
+
|
7
|
+
|
8
|
+
def calculate_current_density(
|
9
|
+
hamiltonian: sisl.Hamiltonian,
|
10
|
+
k: sisl.MonkhorstPack,
|
11
|
+
bdg_energies: NDArray[np.floating],
|
12
|
+
bdg_wavefunctions: NDArray[np.complexfloating],
|
13
|
+
beta: float,
|
14
|
+
) -> NDArray[np.floating]:
|
15
|
+
"""Calculate current density from BdG wavefunctions and normal-state Hamiltonian derivatives.
|
16
|
+
|
17
|
+
Parameters
|
18
|
+
----------
|
19
|
+
hamiltonian : sisl.Hamiltonian
|
20
|
+
The normal-state Hamiltonian.
|
21
|
+
k : np.ndarray
|
22
|
+
Array of k-points in the Brillouin zone.
|
23
|
+
bdg_energies : np.ndarray
|
24
|
+
BdG eigenvalues for each k-point.
|
25
|
+
bdg_wavefunctions : np.ndarray
|
26
|
+
BdG eigenvectors for each k-point.
|
27
|
+
beta : float
|
28
|
+
Inverse temperature (1 / k_B T).
|
29
|
+
|
30
|
+
Returns
|
31
|
+
-------
|
32
|
+
np.ndarray
|
33
|
+
Real current density vector (2D).
|
34
|
+
"""
|
35
|
+
|
36
|
+
def fermi_dirac(e: float, beta: float) -> float:
|
37
|
+
return 1.0 / (np.exp(beta * e) + 1)
|
38
|
+
|
39
|
+
num_bands = hamiltonian.no
|
40
|
+
current = np.zeros(2, dtype=np.complex128)
|
41
|
+
|
42
|
+
for dir_idx, _direction in enumerate(["x", "y"]):
|
43
|
+
matrix = np.zeros((num_bands, num_bands), dtype=np.complex128)
|
44
|
+
|
45
|
+
for k_index, kpt in enumerate(k):
|
46
|
+
dhk = hamiltonian.dHk(kpt, format="array")[dir_idx]
|
47
|
+
|
48
|
+
for i in range(num_bands):
|
49
|
+
for j in range(num_bands):
|
50
|
+
for n in range(2 * num_bands):
|
51
|
+
matrix[i, j] += (
|
52
|
+
dhk[i, j]
|
53
|
+
* np.conj(bdg_wavefunctions[k_index, i, n])
|
54
|
+
* bdg_wavefunctions[k_index, j, n]
|
55
|
+
* fermi_dirac(bdg_energies[k_index, n], beta)
|
56
|
+
)
|
57
|
+
|
58
|
+
current[dir_idx] = np.sum(matrix)
|
59
|
+
|
60
|
+
return (2 * np.real(current)) / len(k)
|
@@ -0,0 +1,110 @@
|
|
1
|
+
"""Function to calculate superfluid weight."""
|
2
|
+
|
3
|
+
import numpy as np
|
4
|
+
import numpy.typing as npt
|
5
|
+
import sisl
|
6
|
+
|
7
|
+
from .bdg_hamiltonian import bdg_hamiltonian
|
8
|
+
|
9
|
+
|
10
|
+
def calculate_superfluid_weight(
|
11
|
+
hamiltonian: sisl.Hamiltonian,
|
12
|
+
kgrid: sisl.MonkhorstPack,
|
13
|
+
beta: float,
|
14
|
+
delta_orbital_basis: npt.NDArray[np.complexfloating],
|
15
|
+
) -> tuple[npt.NDArray[np.complexfloating], npt.NDArray[np.complexfloating]]:
|
16
|
+
"""Calculate superfluid weight (conventional + geometric)."""
|
17
|
+
s_weight_conv = np.zeros((2, 2), dtype=np.complex128)
|
18
|
+
s_weight_geom = np.zeros((2, 2), dtype=np.complex128)
|
19
|
+
c_mnpq_cache = {}
|
20
|
+
|
21
|
+
for i, _dir1 in enumerate(["x", "y"]):
|
22
|
+
for j, _dir2 in enumerate(["x", "y"]):
|
23
|
+
for k_point in kgrid:
|
24
|
+
k_tuple = tuple(k_point)
|
25
|
+
|
26
|
+
# Solve BdG problem
|
27
|
+
bdg_h = bdg_hamiltonian(hamiltonian, k_point, delta_orbital_basis)
|
28
|
+
energies, wavefuncs = np.linalg.eigh(bdg_h)
|
29
|
+
|
30
|
+
# Cache coefficient tensor
|
31
|
+
if k_tuple not in c_mnpq_cache:
|
32
|
+
c_mnpq_cache[k_tuple] = _c_factor(energies, wavefuncs, beta)
|
33
|
+
c_mnpq = c_mnpq_cache[k_tuple]
|
34
|
+
|
35
|
+
bdg_h_deriv_1 = np.zeros(
|
36
|
+
(2 * hamiltonian.no, 2 * hamiltonian.no),
|
37
|
+
dtype=np.complex128,
|
38
|
+
)
|
39
|
+
bdg_h_deriv_2 = np.zeros(
|
40
|
+
(2 * hamiltonian.no, 2 * hamiltonian.no),
|
41
|
+
dtype=np.complex128,
|
42
|
+
)
|
43
|
+
|
44
|
+
bdg_h_deriv_1[0 : hamiltonian.no, 0 : hamiltonian.no] = hamiltonian.dHk(
|
45
|
+
k=k_point,
|
46
|
+
format="array",
|
47
|
+
)[i]
|
48
|
+
bdg_h_deriv_1[
|
49
|
+
hamiltonian.no : 2 * hamiltonian.no,
|
50
|
+
hamiltonian.no : 2 * hamiltonian.no,
|
51
|
+
] = hamiltonian.dHk(k=-k_point, format="array")[i]
|
52
|
+
|
53
|
+
bdg_h_deriv_2[0 : hamiltonian.no, 0 : hamiltonian.no] = hamiltonian.dHk(
|
54
|
+
k=k_point,
|
55
|
+
format="array",
|
56
|
+
)[j]
|
57
|
+
bdg_h_deriv_2[
|
58
|
+
hamiltonian.no : 2 * hamiltonian.no,
|
59
|
+
hamiltonian.no : 2 * hamiltonian.no,
|
60
|
+
] = hamiltonian.dHk(k=-k_point, format="array")[j]
|
61
|
+
|
62
|
+
j_op_1 = _current_operator(bdg_h_deriv_1, wavefuncs)
|
63
|
+
j_op_2 = _current_operator(bdg_h_deriv_2, wavefuncs)
|
64
|
+
|
65
|
+
for m in range(len(wavefuncs)):
|
66
|
+
for n in range(len(wavefuncs)):
|
67
|
+
for p in range(len(wavefuncs)):
|
68
|
+
for q in range(len(wavefuncs)):
|
69
|
+
s_w = c_mnpq[m, n, p, q] * j_op_1[m, n] * j_op_2[q, p]
|
70
|
+
if m == n and p == q:
|
71
|
+
s_weight_conv[i, j] += s_w
|
72
|
+
else:
|
73
|
+
s_weight_geom[i, j] += s_w
|
74
|
+
|
75
|
+
return s_weight_conv, s_weight_geom
|
76
|
+
|
77
|
+
|
78
|
+
def _c_factor(e: npt.NDArray, psi: npt.NDArray, beta: float) -> npt.NDArray:
|
79
|
+
n = len(e)
|
80
|
+
c = np.zeros((n, n, n, n), dtype=np.complex128)
|
81
|
+
for i in range(n):
|
82
|
+
for j in range(n):
|
83
|
+
if np.isclose(e[i], e[j]):
|
84
|
+
f_term = -_fermi_dirac_derivative(e[i], beta)
|
85
|
+
else:
|
86
|
+
f_term = (_fermi_dirac(e[i], beta) - _fermi_dirac(e[j], beta)) / (e[i] - e[j])
|
87
|
+
for m in range(n):
|
88
|
+
for n_ in range(n):
|
89
|
+
for p in range(n):
|
90
|
+
for q in range(n):
|
91
|
+
c[m, n_, p, q] += f_term * (
|
92
|
+
psi[:, i].conj()[m]
|
93
|
+
* psi[:, j][n_]
|
94
|
+
* psi[:, j].conj()[p]
|
95
|
+
* psi[:, i][q]
|
96
|
+
)
|
97
|
+
return 2 * c
|
98
|
+
|
99
|
+
|
100
|
+
def _current_operator(h_deriv: npt.NDArray, psi: npt.NDArray) -> npt.NDArray:
|
101
|
+
return psi.conj().T @ h_deriv @ psi
|
102
|
+
|
103
|
+
|
104
|
+
def _fermi_dirac(energy: float, beta: float) -> float:
|
105
|
+
return 1.0 / (np.exp(beta * energy) + 1.0)
|
106
|
+
|
107
|
+
|
108
|
+
def _fermi_dirac_derivative(energy: float, beta: float) -> float:
|
109
|
+
f = _fermi_dirac(energy, beta)
|
110
|
+
return -beta * f * (1 - f)
|
quant_met/cli/__init__.py
CHANGED
quant_met/cli/crit_temp.py
CHANGED
@@ -1,19 +1,15 @@
|
|
1
|
-
# SPDX-FileCopyrightText: 2024 Tjark Sievers
|
2
|
-
# SPDX-FileCopyrightText: 2025 Tjark Sievers
|
3
|
-
#
|
4
|
-
# SPDX-License-Identifier: MIT
|
5
|
-
|
6
1
|
"""Functions to run self-consistent calculation for the order parameter."""
|
7
2
|
|
8
3
|
import logging
|
9
4
|
from pathlib import Path
|
10
5
|
|
11
6
|
import h5py
|
7
|
+
import numpy as np
|
8
|
+
import sisl
|
12
9
|
|
13
|
-
from quant_met import
|
10
|
+
from quant_met import routines
|
14
11
|
from quant_met.parameters import Parameters
|
15
|
-
|
16
|
-
from ._utils import _hamiltonian_factory
|
12
|
+
from quant_met.parameters.control import CritTemp
|
17
13
|
|
18
14
|
logger = logging.getLogger(__name__)
|
19
15
|
|
@@ -27,18 +23,26 @@ def crit_temp(parameters: Parameters) -> None:
|
|
27
23
|
An instance of Parameters containing control settings, the model,
|
28
24
|
and k-point specifications for the T_C calculation.
|
29
25
|
"""
|
26
|
+
if not isinstance(parameters.control, CritTemp):
|
27
|
+
err_msg = "Wrong parameters for crit-temp."
|
28
|
+
raise TypeError(err_msg)
|
29
|
+
|
30
30
|
result_path = Path(parameters.control.outdir)
|
31
31
|
result_path.mkdir(exist_ok=True, parents=True)
|
32
32
|
|
33
|
-
|
33
|
+
hamiltonian = sisl.get_sile(parameters.control.hamiltonian_file).read_hamiltonian()
|
34
|
+
k_grid_obj = sisl.MonkhorstPack(
|
35
|
+
hamiltonian.geometry,
|
36
|
+
[parameters.k_points.nk1, parameters.k_points.nk2, 1],
|
37
|
+
)
|
34
38
|
|
35
|
-
delta_vs_temp, critical_temperatures, fit_fig =
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
),
|
39
|
+
delta_vs_temp, critical_temperatures, fit_fig = routines.search_crit_temp(
|
40
|
+
hamiltonian=hamiltonian,
|
41
|
+
kgrid=k_grid_obj,
|
42
|
+
hubbard_int_orbital_basis=np.array(parameters.control.hubbard_int_orbital_basis),
|
40
43
|
epsilon=parameters.control.conv_treshold,
|
41
44
|
max_iter=parameters.control.max_iter,
|
45
|
+
q=np.array(parameters.control.q),
|
42
46
|
n_temp_points=parameters.control.n_temp_points,
|
43
47
|
)
|
44
48
|
|
@@ -55,7 +59,5 @@ def crit_temp(parameters: Parameters) -> None:
|
|
55
59
|
with h5py.File(result_file, mode="a") as file:
|
56
60
|
for orbital, crit_temp_orbital in enumerate(critical_temperatures):
|
57
61
|
file.attrs[f"T_C_{orbital}"] = crit_temp_orbital
|
58
|
-
hamiltonian_file = result_path / f"{parameters.control.prefix}_sample_hamiltonian.hdf5"
|
59
|
-
h.save(hamiltonian_file)
|
60
62
|
|
61
63
|
logger.info("Results saved to %s", result_file)
|
quant_met/cli/main.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
|
"""Command line interface."""
|
7
2
|
|
8
3
|
import logging
|
@@ -15,6 +10,8 @@ import yaml
|
|
15
10
|
from quant_met.parameters import Parameters
|
16
11
|
|
17
12
|
from .crit_temp import crit_temp
|
13
|
+
from .q_analysis import q_analysis
|
14
|
+
from .q_loop import q_loop
|
18
15
|
from .scf import scf
|
19
16
|
|
20
17
|
logger = logging.getLogger(__name__)
|
@@ -61,6 +58,12 @@ def cli(input_file: TextIO, *, debug: bool) -> None:
|
|
61
58
|
case "crit-temp":
|
62
59
|
logger.info("Starting T_C calculation.")
|
63
60
|
crit_temp(params)
|
61
|
+
case "q-loop":
|
62
|
+
logger.info("Starting q-loop calculation.")
|
63
|
+
q_loop(params)
|
64
|
+
case "q-analysis":
|
65
|
+
logger.info("Starting analysis of q data.")
|
66
|
+
q_analysis(params)
|
64
67
|
case _:
|
65
68
|
logger.error("Calculation %s not found.", params.control.calculation)
|
66
69
|
sys.exit(1)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
"""Functions to run self-consistent calculation for the order parameter."""
|
2
|
+
|
3
|
+
import logging
|
4
|
+
from pathlib import Path
|
5
|
+
|
6
|
+
import h5py
|
7
|
+
import pandas as pd
|
8
|
+
import sisl
|
9
|
+
|
10
|
+
from quant_met import routines
|
11
|
+
from quant_met.parameters import Parameters
|
12
|
+
from quant_met.parameters.control import QAnalysis
|
13
|
+
|
14
|
+
logger = logging.getLogger(__name__)
|
15
|
+
|
16
|
+
|
17
|
+
def q_analysis(parameters: Parameters) -> None:
|
18
|
+
"""Self-consistent calculation for the order parameter.
|
19
|
+
|
20
|
+
Parameters
|
21
|
+
----------
|
22
|
+
parameters: Parameters
|
23
|
+
An instance of Parameters containing control settings, the model,
|
24
|
+
and k-point specifications for the T_C calculation.
|
25
|
+
"""
|
26
|
+
if not isinstance(parameters.control, QAnalysis):
|
27
|
+
err_msg = "Wrong parameters for q-loop."
|
28
|
+
raise TypeError(err_msg)
|
29
|
+
|
30
|
+
q_data: dict[str, pd.DataFrame] = {}
|
31
|
+
with h5py.File(f"{parameters.control.q_data}") as f:
|
32
|
+
for key in f:
|
33
|
+
q_data.update({key: pd.DataFrame()})
|
34
|
+
|
35
|
+
for key in q_data:
|
36
|
+
data: pd.DataFrame = pd.read_hdf(f"{parameters.control.q_data}", key=key)
|
37
|
+
q_data[key] = data
|
38
|
+
|
39
|
+
hamiltonian = sisl.get_sile(parameters.control.hamiltonian_file).read_hamiltonian()
|
40
|
+
|
41
|
+
(
|
42
|
+
lengths_vs_temp,
|
43
|
+
gap_and_current_fig,
|
44
|
+
) = routines.get_lengths_vs_temp(q_data=q_data, hamiltonian=hamiltonian)
|
45
|
+
|
46
|
+
result_file = Path(f"{parameters.control.outdir}/{parameters.control.prefix}_sc_lengths.hdf5")
|
47
|
+
result_file.unlink()
|
48
|
+
lengths_vs_temp.to_hdf(result_file, key="lengths_vs_temp")
|
49
|
+
gap_and_current_fig.savefig(
|
50
|
+
f"{parameters.control.outdir}/{parameters.control.prefix}_gap_and_current_vs_q.pdf",
|
51
|
+
)
|
52
|
+
|
53
|
+
zero_temp_lengths, length_vs_temp_fig = routines.get_zero_temperature_values(
|
54
|
+
hamiltonian=hamiltonian,
|
55
|
+
lengths_vs_temp=lengths_vs_temp,
|
56
|
+
)
|
57
|
+
zero_temp_lengths.to_hdf(result_file, key="zero_temp_lengths")
|
58
|
+
length_vs_temp_fig.savefig(
|
59
|
+
f"{parameters.control.outdir}/{parameters.control.prefix}_lengths_vs_temperature.pdf",
|
60
|
+
)
|
quant_met/cli/q_loop.py
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
"""Functions to run self-consistent calculation for the order parameter."""
|
2
|
+
|
3
|
+
import logging
|
4
|
+
from pathlib import Path
|
5
|
+
|
6
|
+
import h5py
|
7
|
+
import numpy as np
|
8
|
+
import sisl
|
9
|
+
|
10
|
+
from quant_met import routines
|
11
|
+
from quant_met.parameters import Parameters
|
12
|
+
from quant_met.parameters.control import CritTemp, QLoop
|
13
|
+
|
14
|
+
logger = logging.getLogger(__name__)
|
15
|
+
|
16
|
+
|
17
|
+
def q_loop(parameters: Parameters) -> None:
|
18
|
+
"""Self-consistent calculation for the order parameter.
|
19
|
+
|
20
|
+
Parameters
|
21
|
+
----------
|
22
|
+
parameters: Parameters
|
23
|
+
An instance of Parameters containing control settings, the model,
|
24
|
+
and k-point specifications for the T_C calculation.
|
25
|
+
"""
|
26
|
+
if not isinstance(parameters.control, QLoop):
|
27
|
+
err_msg = "Wrong parameters for q-loop."
|
28
|
+
raise TypeError(err_msg)
|
29
|
+
|
30
|
+
result_path = Path(parameters.control.outdir)
|
31
|
+
result_path.mkdir(exist_ok=True, parents=True)
|
32
|
+
|
33
|
+
hamiltonian = sisl.get_sile(parameters.control.hamiltonian_file).read_hamiltonian()
|
34
|
+
k_grid_obj = sisl.MonkhorstPack(
|
35
|
+
hamiltonian.geometry,
|
36
|
+
[parameters.k_points.nk1, parameters.k_points.nk2, 1],
|
37
|
+
)
|
38
|
+
|
39
|
+
if isinstance(parameters.control.crit_temp, CritTemp):
|
40
|
+
delta_vs_temp, critical_temperatures, fit_fig = routines.search_crit_temp(
|
41
|
+
hamiltonian=hamiltonian,
|
42
|
+
kgrid=k_grid_obj,
|
43
|
+
hubbard_int_orbital_basis=np.array(parameters.control.crit_temp.hubbard_int_orbital_basis),
|
44
|
+
epsilon=parameters.control.crit_temp.conv_treshold,
|
45
|
+
max_iter=parameters.control.crit_temp.max_iter,
|
46
|
+
n_temp_points=20,
|
47
|
+
)
|
48
|
+
logger.info("Search for T_C completed successfully.")
|
49
|
+
logger.info("Obtained T_Cs: %s", critical_temperatures)
|
50
|
+
|
51
|
+
fit_fig.savefig(
|
52
|
+
result_path / f"{parameters.control.crit_temp.prefix}_critical_temperatures_fit.pdf",
|
53
|
+
bbox_inches="tight",
|
54
|
+
)
|
55
|
+
|
56
|
+
result_file_crit_temp = (
|
57
|
+
result_path / f"{parameters.control.crit_temp.prefix}_critical_temperatures.hdf5"
|
58
|
+
)
|
59
|
+
if result_file_crit_temp.exists():
|
60
|
+
result_file_crit_temp.exists()
|
61
|
+
delta_vs_temp.to_hdf(result_file_crit_temp, key="delta_vs_temp")
|
62
|
+
with h5py.File(result_file_crit_temp, mode="a") as file:
|
63
|
+
for orbital, crit_temp_orbital in enumerate(critical_temperatures):
|
64
|
+
file.attrs[f"T_C_{orbital}"] = crit_temp_orbital
|
65
|
+
|
66
|
+
logger.info("Results saved to %s", result_file_crit_temp)
|
67
|
+
else:
|
68
|
+
critical_temperatures = []
|
69
|
+
with h5py.File(f"{parameters.control.crit_temp}", mode="r") as file:
|
70
|
+
for key, critical_temperature in file.attrs.items():
|
71
|
+
if key.startswith("T_C"):
|
72
|
+
critical_temperatures.append(critical_temperature)
|
73
|
+
logger.info("Read critical temperatures from file.")
|
74
|
+
logger.info("Obtained T_Cs: %s", critical_temperatures)
|
75
|
+
|
76
|
+
delta_vs_q = routines.loop_over_q(
|
77
|
+
hamiltonian=hamiltonian,
|
78
|
+
kgrid=k_grid_obj,
|
79
|
+
hubbard_int_orbital_basis=np.array(parameters.control.hubbard_int_orbital_basis),
|
80
|
+
epsilon=parameters.control.conv_treshold,
|
81
|
+
max_iter=parameters.control.max_iter,
|
82
|
+
n_q_points=parameters.control.n_q_points,
|
83
|
+
crit_temps=np.array(critical_temperatures),
|
84
|
+
)
|
85
|
+
|
86
|
+
result_file_q = result_path / f"{parameters.control.prefix}_q.hdf5"
|
87
|
+
|
88
|
+
if result_file_q.exists():
|
89
|
+
result_file_q.unlink()
|
90
|
+
for key, df in delta_vs_q.items():
|
91
|
+
df.to_hdf(result_file_q, key=f"temp_{float(key):.6f}")
|
92
|
+
with h5py.File(result_file_q, "a") as f:
|
93
|
+
grp = f[f"temp_{float(key):.6f}"]
|
94
|
+
grp.attrs["crit_temp"] = critical_temperatures
|
95
|
+
grp.attrs["temp"] = float(key)
|