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.
Files changed (47) hide show
  1. quant_met/__init__.py +2 -7
  2. quant_met/bdg/__init__.py +26 -0
  3. quant_met/bdg/bdg_hamiltonian.py +97 -0
  4. quant_met/bdg/gap_equation.py +127 -0
  5. quant_met/bdg/sc_current.py +60 -0
  6. quant_met/bdg/superfluid_weight.py +110 -0
  7. quant_met/cli/__init__.py +0 -5
  8. quant_met/cli/crit_temp.py +18 -16
  9. quant_met/cli/main.py +8 -5
  10. quant_met/cli/q_analysis.py +60 -0
  11. quant_met/cli/q_loop.py +95 -0
  12. quant_met/cli/scf.py +44 -23
  13. quant_met/parameters/__init__.py +0 -26
  14. quant_met/parameters/control.py +57 -0
  15. quant_met/parameters/main.py +2 -55
  16. quant_met/quantum_geometry/__init__.py +13 -0
  17. quant_met/quantum_geometry/qgt.py +37 -0
  18. quant_met/routines/__init__.py +22 -0
  19. quant_met/routines/analyse_q_data.py +226 -0
  20. quant_met/routines/loop_over_q.py +154 -0
  21. quant_met/{mean_field → routines}/search_crit_temp.py +71 -48
  22. quant_met/{mean_field → routines}/self_consistency.py +32 -28
  23. quant_met/utils.py +1 -6
  24. {quant_met-0.0.27.dist-info → quant_met-0.1.1.dist-info}/METADATA +5 -11
  25. quant_met-0.1.1.dist-info/RECORD +28 -0
  26. quant_met/cli/_utils.py +0 -32
  27. quant_met/geometry/__init__.py +0 -36
  28. quant_met/geometry/base_lattice.py +0 -100
  29. quant_met/geometry/bz_path.py +0 -90
  30. quant_met/geometry/graphene.py +0 -48
  31. quant_met/geometry/square.py +0 -47
  32. quant_met/mean_field/__init__.py +0 -38
  33. quant_met/mean_field/_utils.py +0 -17
  34. quant_met/mean_field/hamiltonians/__init__.py +0 -34
  35. quant_met/mean_field/hamiltonians/base_hamiltonian.py +0 -793
  36. quant_met/mean_field/hamiltonians/dressed_graphene.py +0 -118
  37. quant_met/mean_field/hamiltonians/graphene.py +0 -95
  38. quant_met/mean_field/hamiltonians/one_band_tight_binding.py +0 -70
  39. quant_met/mean_field/hamiltonians/three_band_tight_binding.py +0 -85
  40. quant_met/mean_field/hamiltonians/two_band_tight_binding.py +0 -76
  41. quant_met/parameters/hamiltonians.py +0 -182
  42. quant_met/plotting/__init__.py +0 -31
  43. quant_met/plotting/plotting.py +0 -215
  44. quant_met-0.0.27.dist-info/RECORD +0 -33
  45. {quant_met-0.0.27.dist-info → quant_met-0.1.1.dist-info}/WHEEL +0 -0
  46. {quant_met-0.0.27.dist-info → quant_met-0.1.1.dist-info}/entry_points.txt +0 -0
  47. {quant_met-0.0.27.dist-info → quant_met-0.1.1.dist-info}/licenses/LICENSE.txt +0 -0
quant_met/cli/scf.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 mean_field
10
+ from quant_met import bdg, routines
14
11
  from quant_met.parameters import Parameters
15
-
16
- from ._utils import _hamiltonian_factory
12
+ from quant_met.parameters.control import SCF
17
13
 
18
14
  logger = logging.getLogger(__name__)
19
15
 
@@ -24,41 +20,66 @@ def scf(parameters: Parameters) -> None:
24
20
  Parameters
25
21
  ----------
26
22
  parameters: Parameters
27
- An instance of Parameters containing control settings, the model,
28
- and k-point specifications for the self-consistency calculation.
23
+ An instance of Parameters containing control settings.
29
24
  """
25
+ if not isinstance(parameters.control, SCF):
26
+ err_msg = "Wrong parameters for scf."
27
+ raise TypeError(err_msg)
28
+
30
29
  result_path = Path(parameters.control.outdir)
31
30
  result_path.mkdir(exist_ok=True, parents=True)
31
+ result_file = result_path / f"{parameters.control.prefix}.hdf5"
32
32
 
33
- h = _hamiltonian_factory(parameters=parameters.model, classname=parameters.model.name)
34
- k_space_grid = h.lattice.generate_bz_grid(
35
- ncols=parameters.k_points.nk1, nrows=parameters.k_points.nk2
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],
36
37
  )
37
38
 
38
- solved_h = mean_field.self_consistency_loop(
39
- h=h,
40
- k_space_grid=k_space_grid,
39
+ solved_gap = routines.self_consistency_loop(
40
+ hamiltonian=hamiltonian,
41
+ kgrid=k_grid_obj,
42
+ beta=parameters.control.beta,
43
+ hubbard_int_orbital_basis=np.array(parameters.control.hubbard_int_orbital_basis),
41
44
  epsilon=parameters.control.conv_treshold,
42
45
  max_iter=parameters.control.max_iter,
46
+ q=np.array(parameters.control.q),
43
47
  )
44
48
 
45
49
  logger.info("Self-consistency loop completed successfully.")
46
- logger.debug("Obtained delta values: %s", solved_h.delta_orbital_basis)
50
+ logger.debug("Obtained delta values: %s", solved_gap)
47
51
 
48
- result_file = result_path / f"{parameters.control.prefix}.hdf5"
49
- solved_h.save(filename=result_file)
52
+ with h5py.File(result_file, "a") as f:
53
+ f.create_dataset("delta", data=solved_gap)
50
54
  logger.info("Results saved to %s", result_file)
51
55
 
52
56
  if parameters.control.calculate_additional is True:
53
57
  logger.info("Calculating additional things.")
54
- current = solved_h.calculate_current_density(k=k_space_grid)
55
- free_energy = solved_h.calculate_free_energy(k=k_space_grid)
56
- sf_weight_conv, sf_weight_geom = solved_h.calculate_superfluid_weight(k=k_space_grid)
58
+
59
+ bdg_energies, bdg_wavefunctions = bdg.diagonalize_bdg(
60
+ hamiltonian=hamiltonian,
61
+ kgrid=k_grid_obj,
62
+ delta_orbital_basis=solved_gap,
63
+ q=np.array(parameters.control.q),
64
+ )
65
+
66
+ current = bdg.calculate_current_density(
67
+ hamiltonian=hamiltonian,
68
+ k=k_grid_obj,
69
+ bdg_energies=bdg_energies,
70
+ bdg_wavefunctions=bdg_wavefunctions,
71
+ beta=parameters.control.beta,
72
+ )
73
+ sf_weight_conv, sf_weight_geom = bdg.calculate_superfluid_weight(
74
+ hamiltonian=hamiltonian,
75
+ kgrid=k_grid_obj,
76
+ beta=parameters.control.beta,
77
+ delta_orbital_basis=solved_gap,
78
+ )
57
79
 
58
80
  with h5py.File(result_file, "a") as f:
59
81
  f.attrs["current_x"] = current[0]
60
82
  f.attrs["current_y"] = current[1]
61
- f.attrs["free_energy"] = free_energy
62
83
  f.attrs["sf_weight_conv_xx"] = sf_weight_conv[0, 0]
63
84
  f.attrs["sf_weight_conv_xy"] = sf_weight_conv[0, 1]
64
85
  f.attrs["sf_weight_conv_yx"] = sf_weight_conv[1, 0]
@@ -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
  Parameter Classes
8
3
  =================
@@ -11,11 +6,6 @@ Main class holding all the parameters for the calculation.
11
6
 
12
7
  Classes holding the configuration for the Hamiltonians.
13
8
 
14
- .. autosummary::
15
- :toctree: generated/parameters/hamiltonians
16
-
17
- hamiltonians
18
-
19
9
  .. autosummary::
20
10
  :toctree: generated/parameters/
21
11
  :template: autosummary/pydantic.rst
@@ -25,26 +15,10 @@ Classes holding the configuration for the Hamiltonians.
25
15
  KPoints # noqa
26
16
  """ # noqa: D205, D400
27
17
 
28
- from .hamiltonians import (
29
- DressedGrapheneParameters,
30
- GenericParameters,
31
- GrapheneParameters,
32
- HamiltonianParameters,
33
- OneBandParameters,
34
- ThreeBandParameters,
35
- TwoBandParameters,
36
- )
37
18
  from .main import Control, KPoints, Parameters
38
19
 
39
20
  __all__ = [
40
21
  "Control",
41
- "DressedGrapheneParameters",
42
- "GenericParameters",
43
- "GrapheneParameters",
44
- "HamiltonianParameters",
45
22
  "KPoints",
46
- "OneBandParameters",
47
23
  "Parameters",
48
- "ThreeBandParameters",
49
- "TwoBandParameters",
50
24
  ]
@@ -0,0 +1,57 @@
1
+ """Control parameters."""
2
+
3
+ import pathlib
4
+ from typing import Annotated, Literal, TypeAlias
5
+
6
+ from pydantic import BaseModel, Field
7
+
8
+ FloatList: TypeAlias = list[float]
9
+
10
+
11
+ class ControlBase(BaseModel):
12
+ """Base class for control parameters."""
13
+
14
+ prefix: str
15
+ hamiltonian_file: pathlib.Path
16
+ outdir: pathlib.Path
17
+ conv_treshold: float
18
+ hubbard_int_orbital_basis: FloatList = Field(..., min_length=1)
19
+ max_iter: int = 1000
20
+
21
+
22
+ class SCF(ControlBase):
23
+ """Parameters for the scf calculation."""
24
+
25
+ calculation: Literal["scf"]
26
+ beta: float
27
+ calculate_additional: bool = False
28
+ q: FloatList | None = Field(..., min_length=2, max_length=2)
29
+
30
+
31
+ class CritTemp(ControlBase):
32
+ """Parameters for the critical temperature calculation."""
33
+
34
+ calculation: Literal["crit-temp"]
35
+ n_temp_points: int = 50
36
+ q: FloatList | None = Field(..., min_length=2, max_length=2)
37
+
38
+
39
+ class QLoop(ControlBase):
40
+ """Parameters for the q-loop calculation."""
41
+
42
+ calculation: Literal["q-loop"]
43
+ n_q_points: int = 50
44
+ crit_temp: CritTemp | pathlib.Path
45
+
46
+
47
+ class QAnalysis(BaseModel):
48
+ """Parameters for the q-analysis calculation."""
49
+
50
+ calculation: Literal["q-analysis"]
51
+ q_data: pathlib.Path
52
+ hamiltonian_file: pathlib.Path
53
+ prefix: str
54
+ outdir: pathlib.Path
55
+
56
+
57
+ Control = Annotated[SCF | CritTemp | QLoop | QAnalysis, Field(discriminator="calculation")]
@@ -1,54 +1,8 @@
1
- # SPDX-FileCopyrightText: 2024 Tjark Sievers
2
- # SPDX-FileCopyrightText: 2025 Tjark Sievers
3
- #
4
- # SPDX-License-Identifier: MIT
5
-
6
1
  """Pydantic models to hold parameters to run a simulation."""
7
2
 
8
- import pathlib
9
-
10
- from pydantic import BaseModel, Field
11
-
12
- from .hamiltonians import (
13
- DressedGrapheneParameters,
14
- GrapheneParameters,
15
- OneBandParameters,
16
- ThreeBandParameters,
17
- TwoBandParameters,
18
- )
19
-
20
-
21
- class Control(BaseModel):
22
- """Control for the calculation.
23
-
24
- Attributes
25
- ----------
26
- calculation : str
27
- Specifies the type of calculation to be performed.
28
- prefix : str
29
- A string used as a prefix for naming output files generated by the simulation.
30
- outdir : :class:`pathlib.Path`
31
- A path indicating the output directory where results will be saved.
32
- conv_treshold : float
33
- A float value representing the convergence threshold.
34
- The calculation will stop when changes in the results drop below this threshold.
35
- """
36
-
37
- calculation: str
38
- prefix: str
39
- outdir: pathlib.Path
40
- conv_treshold: float
41
- max_iter: int = 1000
42
- n_temp_points: int = 50
43
- calculate_additional: bool = False
3
+ from pydantic import BaseModel
44
4
 
45
- n_spin: int = 1
46
- n_success: int = 1
47
- wmixing: float = 0.5
48
- n_bath: int = 2
49
- n_iw: int = 1024
50
- n_w: int = 4000
51
- broadening: float = 0.005
5
+ from .control import Control
52
6
 
53
7
 
54
8
  class KPoints(BaseModel):
@@ -81,11 +35,4 @@ class Parameters(BaseModel):
81
35
  """
82
36
 
83
37
  control: Control
84
- model: (
85
- DressedGrapheneParameters
86
- | GrapheneParameters
87
- | OneBandParameters
88
- | TwoBandParameters
89
- | ThreeBandParameters
90
- ) = Field(..., discriminator="name")
91
38
  k_points: KPoints
@@ -0,0 +1,13 @@
1
+ """
2
+ Quantum Geometry
3
+ ================
4
+
5
+ .. autosummary::
6
+ :toctree: generated/
7
+
8
+ calculate_qgt
9
+ """ # noqa: D205, D400
10
+
11
+ from .qgt import calculate_qgt
12
+
13
+ __all__ = ["calculate_qgt"]
@@ -0,0 +1,37 @@
1
+ """Calculate the quantum geometric tensor."""
2
+
3
+ import numpy as np
4
+ import numpy.typing as npt
5
+ import sisl
6
+
7
+
8
+ def calculate_qgt(
9
+ hamiltonian: sisl.Hamiltonian,
10
+ k_grid: npt.NDArray[np.floating],
11
+ bands: list[int],
12
+ ) -> npt.NDArray[np.floating]:
13
+ """Calculate the quantum geometric tensor for selected bands."""
14
+ qgt = np.zeros((2, 2), dtype=np.complex128)
15
+
16
+ for k_point in k_grid:
17
+ # Diagonalize at this k-point
18
+ hk = hamiltonian.Hk(k=k_point, format="array")
19
+ energies, bloch = np.linalg.eigh(hk)
20
+
21
+ # Derivatives of H at this k-point
22
+ der_h_k = hamiltonian.dHk(k=k_point, format="array")
23
+
24
+ for band in bands:
25
+ for i, der_h_i in enumerate(der_h_k): # i: x=0, y=1
26
+ for j, der_h_j in enumerate(der_h_k): # j: x=0, y=1
27
+ for n in range(len(energies)):
28
+ if n == band:
29
+ continue
30
+ denom = (energies[band] - energies[n]) ** 2
31
+ if np.isclose(denom, 0.0):
32
+ continue # avoid division by zero
33
+ mni = np.vdot(bloch[:, band], der_h_i @ bloch[:, n])
34
+ mnj = np.vdot(bloch[:, n], der_h_j @ bloch[:, band])
35
+ qgt[i, j] += mni * mnj / denom
36
+
37
+ return np.real(qgt) / len(k_grid)
@@ -0,0 +1,22 @@
1
+ """
2
+ Routines
3
+ ========
4
+
5
+ .. autosummary::
6
+ :toctree: generated/
7
+
8
+ self_consistency_loop
9
+ """ # noqa: D205, D400
10
+
11
+ from .analyse_q_data import get_lengths_vs_temp, get_zero_temperature_values
12
+ from .loop_over_q import loop_over_q
13
+ from .search_crit_temp import search_crit_temp
14
+ from .self_consistency import self_consistency_loop
15
+
16
+ __all__ = [
17
+ "get_lengths_vs_temp",
18
+ "get_zero_temperature_values",
19
+ "loop_over_q",
20
+ "search_crit_temp",
21
+ "self_consistency_loop",
22
+ ]
@@ -0,0 +1,226 @@
1
+ """Routine to analyse q data."""
2
+
3
+ import logging
4
+
5
+ import matplotlib.figure
6
+ import matplotlib.pyplot as plt
7
+ import numpy as np
8
+ import numpy.typing as npt
9
+ import pandas as pd
10
+ import sisl
11
+ from scipy.interpolate import CubicSpline
12
+ from scipy.optimize import curve_fit, minimize_scalar, root_scalar
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ MIN_LENGTH_FIT = 5
18
+ FIT_CUTOFF = 0.01
19
+
20
+
21
+ def _lambda_from_xi(xi: float, jdp: float) -> float:
22
+ return np.sqrt(2 / (3 * np.sqrt(3) * xi * jdp))
23
+
24
+
25
+ def _correl_length_temp_dependence(
26
+ temp: npt.NDArray[np.floating], xi_0: float, crit_temp: float
27
+ ) -> npt.NDArray[np.floating]:
28
+ return xi_0 / np.sqrt(1 - temp / crit_temp)
29
+
30
+
31
+ def _london_depth_temp_dependence(
32
+ temp: npt.NDArray[np.floating], lambda_0: float, crit_temp: float
33
+ ) -> npt.NDArray[np.floating]:
34
+ return lambda_0 / np.sqrt(1 - (temp / crit_temp))
35
+
36
+
37
+ def get_lengths_vs_temp(
38
+ q_data: dict[str, pd.DataFrame],
39
+ hamiltonian: sisl.Hamiltonian,
40
+ ) -> tuple[pd.DataFrame, matplotlib.figure.Figure]:
41
+ """Calculate SC lengths vs temperature.
42
+
43
+ Args:
44
+ q_data (dict[str, pd.DataFrame]): Dataframe with q data.
45
+ hamiltonian (sisl.Hamiltonian): Hamiltonian
46
+
47
+ Returns
48
+ -------
49
+ tuple[pd.DataFrame, matplotlib.figure.Figure]: Results. Figure with fits.
50
+ """
51
+ lengths_row_list = []
52
+
53
+ for temperature, data in q_data.items():
54
+ lengths_dict = {
55
+ "T": float(temperature.split("_")[-1]),
56
+ }
57
+ results_fit = data[
58
+ np.abs(data["current_abs"]) / np.max(np.abs(data["current_abs"])) > FIT_CUTOFF
59
+ ]
60
+ results_fit.reset_index(drop=True, inplace=True)
61
+
62
+ if len(results_fit) > MIN_LENGTH_FIT:
63
+ j_spl = CubicSpline(x=results_fit["q_fraction"], y=results_fit["current_abs"])
64
+ res = minimize_scalar(
65
+ lambda x, spline=j_spl: -spline(x),
66
+ bounds=(0, results_fit["q_fraction"].tail(1).item()),
67
+ )
68
+ q_j_max = float(res.x)
69
+ j_dp = float(j_spl(q_j_max))
70
+ lengths_dict.update({"q_j_max": q_j_max, "j_dp": j_dp})
71
+ for orbital in range(hamiltonian.no):
72
+ delta_spl = CubicSpline(
73
+ x=results_fit["q_fraction"],
74
+ y=np.abs(results_fit[f"delta_{orbital}"])
75
+ / np.abs(data.at[0, f"delta_{orbital}"]),
76
+ )
77
+ try:
78
+ res = root_scalar(
79
+ lambda x, spline=delta_spl: spline(x) - 1 / np.sqrt(2),
80
+ bracket=(0, results_fit["q_fraction"].tail(1)),
81
+ )
82
+
83
+ xi = 1 / (np.sqrt(2) * res.root * np.linalg.norm(hamiltonian.geometry.rcell[0]))
84
+ lengths_dict.update(
85
+ {
86
+ f"Q_{orbital}": res.root,
87
+ f"delta_{orbital}": delta_spl(res.root)
88
+ * np.abs(data.at[0, f"delta_{orbital}"]),
89
+ f"xi_{orbital}": xi,
90
+ },
91
+ )
92
+ if j_dp is not None:
93
+ lambda_london = _lambda_from_xi(xi, j_dp)
94
+ lengths_dict.update({f"lambda_{orbital}": lambda_london})
95
+ except ValueError:
96
+ logger.exception("Value error.")
97
+ lengths_row_list.append(lengths_dict)
98
+
99
+ lengths_vs_temp = pd.DataFrame(lengths_row_list).sort_values("T").reset_index(drop=True)
100
+
101
+ gap_and_current_fig, gap_and_current_axs = plt.subplots(
102
+ ncols=hamiltonian.no + 1,
103
+ figsize=(7 * hamiltonian.no, 5),
104
+ )
105
+
106
+ for temperature, data in q_data.items():
107
+ for orbital in range(hamiltonian.no):
108
+ gap_ax = gap_and_current_axs[orbital]
109
+ gap_ax.plot(
110
+ data["q_fraction"],
111
+ data[f"delta_{orbital}"],
112
+ "x--",
113
+ label=f"{float(temperature.split('_')[-1]):.2f}",
114
+ )
115
+ gap_ax.plot(lengths_vs_temp[f"Q_{orbital}"], lengths_vs_temp[f"delta_{orbital}"], "o--")
116
+ gap_ax.legend()
117
+ current_ax = gap_and_current_axs[hamiltonian.no]
118
+ current_ax.plot(
119
+ data["q_fraction"],
120
+ data["current_abs"],
121
+ "x--",
122
+ label=f"{float(temperature.split('_')[-1]):.2f}",
123
+ )
124
+ current_ax.legend()
125
+
126
+ current_ax = gap_and_current_axs[hamiltonian.no]
127
+ current_ax.plot(lengths_vs_temp["q_j_max"], lengths_vs_temp["j_dp"], "o--")
128
+
129
+ return lengths_vs_temp, gap_and_current_fig
130
+
131
+
132
+ def get_zero_temperature_values(
133
+ hamiltonian: sisl.Hamiltonian, lengths_vs_temp: pd.DataFrame
134
+ ) -> tuple[pd.DataFrame, matplotlib.figure.Figure]:
135
+ """Get zero temperature values for the SC length scales.
136
+
137
+ Args:
138
+ hamiltonian (sisl.Hamiltonian): Hamiltonian.
139
+ lengths_vs_temp (pd.DataFrame): SC lengths against temperature.
140
+
141
+ Returns
142
+ -------
143
+ tuple[pd.DataFrame, matplotlib.figure.Figure]: Results, Figure with fits.
144
+ """
145
+ length_vs_temp_fig, length_vs_temp_axs = plt.subplots(
146
+ nrows=2,
147
+ ncols=hamiltonian.no,
148
+ figsize=(7 * hamiltonian.no, 2 * 5),
149
+ )
150
+ zero_temp_length_row_list = []
151
+ zero_temp_length_dict = {}
152
+ for orbital in range(hamiltonian.no):
153
+ xi_ax = length_vs_temp_axs[0, orbital]
154
+ lambda_ax = length_vs_temp_axs[1, orbital]
155
+
156
+ if f"xi_{orbital}" in lengths_vs_temp:
157
+ xi_ax.plot(lengths_vs_temp["T"], lengths_vs_temp[f"xi_{orbital}"], "x--")
158
+
159
+ xi_fit = lengths_vs_temp[["T", f"xi_{orbital}"]].dropna().reset_index(drop=True)
160
+ xi_fit.reset_index(drop=True, inplace=True)
161
+
162
+ if len(xi_fit) > MIN_LENGTH_FIT:
163
+ p0, p0cov = curve_fit(
164
+ _correl_length_temp_dependence,
165
+ xi_fit["T"],
166
+ xi_fit[f"xi_{orbital}"],
167
+ bounds=([0.0, 0.0], [np.inf, np.inf]),
168
+ p0=[2.0, 2.0],
169
+ )
170
+ xi_0 = p0[0]
171
+ crit_temp_xi = p0[1]
172
+ temp_points_interpolate = np.linspace(
173
+ xi_fit.at[0, "T"],
174
+ xi_fit.at[len(xi_fit) - 1, "T"],
175
+ num=500,
176
+ )
177
+ xi_ax.plot(
178
+ temp_points_interpolate,
179
+ _correl_length_temp_dependence(temp_points_interpolate, xi_0, crit_temp_xi),
180
+ )
181
+ xi_ax.axvline(x=crit_temp_xi, ls="--")
182
+ xi_ax.axhline(y=xi_0, ls="--")
183
+ xi_ax.set_ylim(bottom=0)
184
+ zero_temp_length_dict.update(
185
+ {f"xi0_{orbital}": xi_0, f"T_C_{orbital}_xi": crit_temp_xi},
186
+ )
187
+ if f"lambda_{orbital}" in lengths_vs_temp:
188
+ lambda_ax.plot(lengths_vs_temp["T"], lengths_vs_temp[f"lambda_{orbital}"], "x--")
189
+ lambda_fit = lengths_vs_temp[["T", f"lambda_{orbital}"]].dropna().reset_index(drop=True)
190
+
191
+ if len(lambda_fit) > MIN_LENGTH_FIT:
192
+ p0, p0cov = curve_fit(
193
+ _london_depth_temp_dependence,
194
+ lambda_fit["T"],
195
+ lambda_fit[f"lambda_{orbital}"],
196
+ bounds=([0.0, 0.0], [np.inf, np.inf]),
197
+ p0=[2.0, 2.0],
198
+ )
199
+
200
+ lambda_0 = p0[0]
201
+ crit_temp_lambda = p0[1]
202
+ temp_points_interpolate = np.linspace(
203
+ lambda_fit.at[0, "T"],
204
+ lambda_fit.at[len(lambda_fit) - 1, "T"],
205
+ num=500,
206
+ )
207
+ lambda_ax.plot(
208
+ temp_points_interpolate,
209
+ _london_depth_temp_dependence(
210
+ temp_points_interpolate, lambda_0, crit_temp_lambda
211
+ ),
212
+ )
213
+ lambda_ax.axvline(x=crit_temp_lambda, ls="--")
214
+ lambda_ax.axhline(y=lambda_0, ls="--")
215
+ lambda_ax.set_ylim(bottom=0)
216
+ zero_temp_length_dict.update(
217
+ {
218
+ f"lambda0_{orbital}": lambda_0,
219
+ f"T_C_lambda0_{orbital}": crit_temp_lambda,
220
+ },
221
+ )
222
+
223
+ zero_temp_length_row_list.append(zero_temp_length_dict)
224
+ zero_temp_lengths = pd.DataFrame(zero_temp_length_row_list)
225
+
226
+ return zero_temp_lengths, length_vs_temp_fig