quant-met 0.0.26__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.
Files changed (51) hide show
  1. quant_met/__init__.py +4 -4
  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 -4
  8. quant_met/cli/crit_temp.py +18 -15
  9. quant_met/cli/main.py +8 -8
  10. quant_met/cli/q_analysis.py +60 -0
  11. quant_met/cli/q_loop.py +91 -0
  12. quant_met/cli/scf.py +44 -22
  13. quant_met/parameters/__init__.py +0 -25
  14. quant_met/parameters/control.py +57 -0
  15. quant_met/parameters/main.py +2 -54
  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 -47
  22. quant_met/{mean_field → routines}/self_consistency.py +32 -27
  23. quant_met/utils.py +1 -5
  24. {quant_met-0.0.26.dist-info → quant_met-0.1.0.dist-info}/METADATA +7 -11
  25. quant_met-0.1.0.dist-info/RECORD +28 -0
  26. quant_met/cli/_utils.py +0 -66
  27. quant_met/cli/dmft.py +0 -96
  28. quant_met/dmft/__init__.py +0 -5
  29. quant_met/dmft/dmft_loop.py +0 -178
  30. quant_met/dmft/utils.py +0 -207
  31. quant_met/geometry/__init__.py +0 -35
  32. quant_met/geometry/base_lattice.py +0 -99
  33. quant_met/geometry/bz_path.py +0 -89
  34. quant_met/geometry/graphene.py +0 -47
  35. quant_met/geometry/square.py +0 -46
  36. quant_met/mean_field/__init__.py +0 -39
  37. quant_met/mean_field/_utils.py +0 -16
  38. quant_met/mean_field/hamiltonians/__init__.py +0 -33
  39. quant_met/mean_field/hamiltonians/base_hamiltonian.py +0 -792
  40. quant_met/mean_field/hamiltonians/dressed_graphene.py +0 -117
  41. quant_met/mean_field/hamiltonians/graphene.py +0 -94
  42. quant_met/mean_field/hamiltonians/one_band_tight_binding.py +0 -69
  43. quant_met/mean_field/hamiltonians/three_band_tight_binding.py +0 -84
  44. quant_met/mean_field/hamiltonians/two_band_tight_binding.py +0 -75
  45. quant_met/parameters/hamiltonians.py +0 -181
  46. quant_met/plotting/__init__.py +0 -30
  47. quant_met/plotting/plotting.py +0 -214
  48. quant_met-0.0.26.dist-info/RECORD +0 -37
  49. {quant_met-0.0.26.dist-info → quant_met-0.1.0.dist-info}/WHEEL +0 -0
  50. {quant_met-0.0.26.dist-info → quant_met-0.1.0.dist-info}/entry_points.txt +0 -0
  51. {quant_met-0.0.26.dist-info → quant_met-0.1.0.dist-info}/licenses/LICENSE.txt +0 -0
quant_met/cli/scf.py CHANGED
@@ -1,18 +1,15 @@
1
- # SPDX-FileCopyrightText: 2024 Tjark Sievers
2
- #
3
- # SPDX-License-Identifier: MIT
4
-
5
1
  """Functions to run self-consistent calculation for the order parameter."""
6
2
 
7
3
  import logging
8
4
  from pathlib import Path
9
5
 
10
6
  import h5py
7
+ import numpy as np
8
+ import sisl
11
9
 
12
- from quant_met import mean_field
10
+ from quant_met import bdg, routines
13
11
  from quant_met.parameters import Parameters
14
-
15
- from ._utils import _hamiltonian_factory
12
+ from quant_met.parameters.control import SCF
16
13
 
17
14
  logger = logging.getLogger(__name__)
18
15
 
@@ -23,41 +20,66 @@ def scf(parameters: Parameters) -> None:
23
20
  Parameters
24
21
  ----------
25
22
  parameters: Parameters
26
- An instance of Parameters containing control settings, the model,
27
- and k-point specifications for the self-consistency calculation.
23
+ An instance of Parameters containing control settings.
28
24
  """
25
+ if not isinstance(parameters.control, SCF):
26
+ err_msg = "Wrong parameters for scf."
27
+ raise TypeError(err_msg)
28
+
29
29
  result_path = Path(parameters.control.outdir)
30
30
  result_path.mkdir(exist_ok=True, parents=True)
31
+ result_file = result_path / f"{parameters.control.prefix}.hdf5"
31
32
 
32
- h = _hamiltonian_factory(parameters=parameters.model, classname=parameters.model.name)
33
- k_space_grid = h.lattice.generate_bz_grid(
34
- 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],
35
37
  )
36
38
 
37
- solved_h = mean_field.self_consistency_loop(
38
- h=h,
39
- 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),
40
44
  epsilon=parameters.control.conv_treshold,
41
45
  max_iter=parameters.control.max_iter,
46
+ q=np.array(parameters.control.q),
42
47
  )
43
48
 
44
49
  logger.info("Self-consistency loop completed successfully.")
45
- logger.debug("Obtained delta values: %s", solved_h.delta_orbital_basis)
50
+ logger.debug("Obtained delta values: %s", solved_gap)
46
51
 
47
- result_file = result_path / f"{parameters.control.prefix}.hdf5"
48
- solved_h.save(filename=result_file)
52
+ with h5py.File(result_file, "a") as f:
53
+ f.create_dataset("delta", data=solved_gap)
49
54
  logger.info("Results saved to %s", result_file)
50
55
 
51
56
  if parameters.control.calculate_additional is True:
52
57
  logger.info("Calculating additional things.")
53
- current = solved_h.calculate_current_density(k=k_space_grid)
54
- free_energy = solved_h.calculate_free_energy(k=k_space_grid)
55
- 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
+ )
56
79
 
57
80
  with h5py.File(result_file, "a") as f:
58
81
  f.attrs["current_x"] = current[0]
59
82
  f.attrs["current_y"] = current[1]
60
- f.attrs["free_energy"] = free_energy
61
83
  f.attrs["sf_weight_conv_xx"] = sf_weight_conv[0, 0]
62
84
  f.attrs["sf_weight_conv_xy"] = sf_weight_conv[0, 1]
63
85
  f.attrs["sf_weight_conv_yx"] = sf_weight_conv[1, 0]
@@ -1,7 +1,3 @@
1
- # SPDX-FileCopyrightText: 2024 Tjark Sievers
2
- #
3
- # SPDX-License-Identifier: MIT
4
-
5
1
  """
6
2
  Parameter Classes
7
3
  =================
@@ -10,11 +6,6 @@ Main class holding all the parameters for the calculation.
10
6
 
11
7
  Classes holding the configuration for the Hamiltonians.
12
8
 
13
- .. autosummary::
14
- :toctree: generated/parameters/hamiltonians
15
-
16
- hamiltonians
17
-
18
9
  .. autosummary::
19
10
  :toctree: generated/parameters/
20
11
  :template: autosummary/pydantic.rst
@@ -24,26 +15,10 @@ Classes holding the configuration for the Hamiltonians.
24
15
  KPoints # noqa
25
16
  """ # noqa: D205, D400
26
17
 
27
- from .hamiltonians import (
28
- DressedGrapheneParameters,
29
- GenericParameters,
30
- GrapheneParameters,
31
- HamiltonianParameters,
32
- OneBandParameters,
33
- ThreeBandParameters,
34
- TwoBandParameters,
35
- )
36
18
  from .main import Control, KPoints, Parameters
37
19
 
38
20
  __all__ = [
39
21
  "Control",
40
- "DressedGrapheneParameters",
41
- "GenericParameters",
42
- "GrapheneParameters",
43
- "HamiltonianParameters",
44
22
  "KPoints",
45
- "OneBandParameters",
46
23
  "Parameters",
47
- "ThreeBandParameters",
48
- "TwoBandParameters",
49
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,53 +1,8 @@
1
- # SPDX-FileCopyrightText: 2024 Tjark Sievers
2
- #
3
- # SPDX-License-Identifier: MIT
4
-
5
1
  """Pydantic models to hold parameters to run a simulation."""
6
2
 
7
- import pathlib
8
-
9
- from pydantic import BaseModel, Field
10
-
11
- from .hamiltonians import (
12
- DressedGrapheneParameters,
13
- GrapheneParameters,
14
- OneBandParameters,
15
- ThreeBandParameters,
16
- TwoBandParameters,
17
- )
18
-
19
-
20
- class Control(BaseModel):
21
- """Control for the calculation.
22
-
23
- Attributes
24
- ----------
25
- calculation : str
26
- Specifies the type of calculation to be performed.
27
- prefix : str
28
- A string used as a prefix for naming output files generated by the simulation.
29
- outdir : :class:`pathlib.Path`
30
- A path indicating the output directory where results will be saved.
31
- conv_treshold : float
32
- A float value representing the convergence threshold.
33
- The calculation will stop when changes in the results drop below this threshold.
34
- """
35
-
36
- calculation: str
37
- prefix: str
38
- outdir: pathlib.Path
39
- conv_treshold: float
40
- max_iter: int = 1000
41
- n_temp_points: int = 50
42
- calculate_additional: bool = False
3
+ from pydantic import BaseModel
43
4
 
44
- n_spin: int = 1
45
- n_success: int = 1
46
- wmixing: float = 0.5
47
- n_bath: int = 2
48
- n_iw: int = 1024
49
- n_w: int = 4000
50
- broadening: float = 0.005
5
+ from .control import Control
51
6
 
52
7
 
53
8
  class KPoints(BaseModel):
@@ -80,11 +35,4 @@ class Parameters(BaseModel):
80
35
  """
81
36
 
82
37
  control: Control
83
- model: (
84
- DressedGrapheneParameters
85
- | GrapheneParameters
86
- | OneBandParameters
87
- | TwoBandParameters
88
- | ThreeBandParameters
89
- ) = Field(..., discriminator="name")
90
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