quant-met 0.0.16__py3-none-any.whl → 0.0.18__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 (32) hide show
  1. quant_met/cli/scf.py +27 -3
  2. quant_met/geometry/__init__.py +1 -1
  3. quant_met/geometry/base_lattice.py +6 -6
  4. quant_met/geometry/bz_path.py +6 -6
  5. quant_met/geometry/graphene.py +3 -3
  6. quant_met/geometry/square.py +3 -3
  7. quant_met/mean_field/__init__.py +2 -4
  8. quant_met/mean_field/hamiltonians/__init__.py +1 -1
  9. quant_met/mean_field/hamiltonians/base_hamiltonian.py +288 -52
  10. quant_met/mean_field/hamiltonians/dressed_graphene.py +6 -6
  11. quant_met/mean_field/hamiltonians/graphene.py +6 -6
  12. quant_met/mean_field/hamiltonians/one_band_tight_binding.py +6 -6
  13. quant_met/mean_field/hamiltonians/three_band_tight_binding.py +6 -6
  14. quant_met/mean_field/hamiltonians/two_band_tight_binding.py +6 -6
  15. quant_met/mean_field/quantum_metric.py +3 -3
  16. quant_met/mean_field/search_crit_temp.py +3 -3
  17. quant_met/mean_field/self_consistency.py +13 -9
  18. quant_met/parameters/__init__.py +5 -5
  19. quant_met/parameters/hamiltonians.py +8 -8
  20. quant_met/parameters/main.py +1 -0
  21. quant_met/plotting/__init__.py +1 -1
  22. quant_met/plotting/plotting.py +9 -9
  23. quant_met/utils.py +27 -5
  24. {quant_met-0.0.16.dist-info → quant_met-0.0.18.dist-info}/METADATA +21 -23
  25. quant_met-0.0.18.dist-info/RECORD +34 -0
  26. {quant_met-0.0.16.dist-info → quant_met-0.0.18.dist-info}/WHEEL +1 -1
  27. quant_met-0.0.18.dist-info/entry_points.txt +2 -0
  28. quant_met/mean_field/superfluid_weight.py +0 -123
  29. quant_met-0.0.16.dist-info/LICENSES/MIT.txt +0 -9
  30. quant_met-0.0.16.dist-info/RECORD +0 -36
  31. quant_met-0.0.16.dist-info/entry_points.txt +0 -3
  32. {quant_met-0.0.16.dist-info → quant_met-0.0.18.dist-info/licenses}/LICENSE.txt +0 -0
@@ -12,10 +12,12 @@ import h5py
12
12
  import numpy as np
13
13
  import numpy.typing as npt
14
14
  import pandas as pd
15
+ from numba import jit
15
16
 
16
17
  from quant_met.geometry import BaseLattice
17
18
  from quant_met.mean_field._utils import _check_valid_array
18
19
  from quant_met.parameters.hamiltonians import GenericParameters, HamiltonianParameters
20
+ from quant_met.utils import fermi_dirac
19
21
 
20
22
  GenericHamiltonian = TypeVar("GenericHamiltonian", bound="BaseHamiltonian[HamiltonianParameters]")
21
23
 
@@ -64,7 +66,7 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
64
66
  self.lattice = self.setup_lattice(parameters)
65
67
  self.hubbard_int_orbital_basis = parameters.hubbard_int_orbital_basis
66
68
  self.number_of_bands = len(self.hubbard_int_orbital_basis)
67
- self.delta_orbital_basis = np.zeros(self.number_of_bands, dtype=np.complex64)
69
+ self.delta_orbital_basis = np.zeros(self.number_of_bands, dtype=np.complex128)
68
70
 
69
71
  @abstractmethod
70
72
  def setup_lattice(self, parameters: GenericParameters) -> BaseLattice: # pragma: no cover
@@ -97,8 +99,8 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
97
99
 
98
100
  @abstractmethod
99
101
  def hamiltonian(
100
- self, k: npt.NDArray[np.float64]
101
- ) -> npt.NDArray[np.complex64]: # pragma: no cover
102
+ self, k: npt.NDArray[np.floating]
103
+ ) -> npt.NDArray[np.complexfloating]: # pragma: no cover
102
104
  """Return the normal state Hamiltonian.
103
105
 
104
106
  Parameters
@@ -114,8 +116,8 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
114
116
 
115
117
  @abstractmethod
116
118
  def hamiltonian_derivative(
117
- self, k: npt.NDArray[np.float64], direction: str
118
- ) -> npt.NDArray[np.complex64]: # pragma: no cover
119
+ self, k: npt.NDArray[np.floating], direction: str
120
+ ) -> npt.NDArray[np.complexfloating]: # pragma: no cover
119
121
  """Calculate the spatial derivative of the Hamiltonian.
120
122
 
121
123
  Parameters
@@ -174,7 +176,7 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
174
176
  parameters = parameters_model.model_validate(config_dict)
175
177
  return cls(parameters=parameters)
176
178
 
177
- def bdg_hamiltonian(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]:
179
+ def bdg_hamiltonian(self, k: npt.NDArray[np.floating]) -> npt.NDArray[np.complexfloating]:
178
180
  """Generate the Bogoliubov-de Gennes (BdG) Hamiltonian.
179
181
 
180
182
  The BdG Hamiltonian incorporates pairing interactions and is used to
@@ -197,7 +199,8 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
197
199
  k = np.expand_dims(k, axis=0)
198
200
 
199
201
  h = np.zeros(
200
- (k.shape[0], 2 * self.number_of_bands, 2 * self.number_of_bands), dtype=np.complex64
202
+ (k.shape[0], 2 * self.number_of_bands, 2 * self.number_of_bands),
203
+ dtype=np.complex128,
201
204
  )
202
205
 
203
206
  h[:, 0 : self.number_of_bands, 0 : self.number_of_bands] = self.hamiltonian(k)
@@ -219,8 +222,8 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
219
222
  return h.squeeze()
220
223
 
221
224
  def bdg_hamiltonian_derivative(
222
- self, k: npt.NDArray[np.float64], direction: str
223
- ) -> npt.NDArray[np.complex64]:
225
+ self, k: npt.NDArray[np.floating], direction: str
226
+ ) -> npt.NDArray[np.complexfloating]:
224
227
  """Calculate the derivative of the BdG Hamiltonian.
225
228
 
226
229
  This method computes the spatial derivative of the Bogoliubov-de Gennes
@@ -243,7 +246,8 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
243
246
  k = np.expand_dims(k, axis=0)
244
247
 
245
248
  h = np.zeros(
246
- (k.shape[0], 2 * self.number_of_bands, 2 * self.number_of_bands), dtype=np.complex64
249
+ (k.shape[0], 2 * self.number_of_bands, 2 * self.number_of_bands),
250
+ dtype=np.complex128,
247
251
  )
248
252
 
249
253
  h[:, 0 : self.number_of_bands, 0 : self.number_of_bands] = self.hamiltonian_derivative(
@@ -258,8 +262,8 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
258
262
  return h.squeeze()
259
263
 
260
264
  def diagonalize_nonint(
261
- self, k: npt.NDArray[np.float64]
262
- ) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]:
265
+ self, k: npt.NDArray[np.floating]
266
+ ) -> tuple[npt.NDArray[np.floating], npt.NDArray[np.floating]]:
263
267
  """Diagonalizes the normal state Hamiltonian.
264
268
 
265
269
  This method computes the eigenvalues and eigenvectors of the normal state
@@ -296,8 +300,8 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
296
300
 
297
301
  def diagonalize_bdg(
298
302
  self,
299
- k: npt.NDArray[np.float64],
300
- ) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.complex64]]:
303
+ k: npt.NDArray[np.floating],
304
+ ) -> tuple[npt.NDArray[np.floating], npt.NDArray[np.complexfloating]]:
301
305
  """Diagonalizes the BdG Hamiltonian.
302
306
 
303
307
  This method computes the eigenvalues and eigenvectors of the Bogoliubov-de
@@ -323,7 +327,7 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
323
327
 
324
328
  bdg_wavefunctions = np.zeros(
325
329
  (len(k), 2 * self.number_of_bands, 2 * self.number_of_bands),
326
- dtype=np.complex64,
330
+ dtype=np.complex128,
327
331
  )
328
332
  bdg_energies = np.zeros((len(k), 2 * self.number_of_bands))
329
333
 
@@ -332,10 +336,34 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
332
336
 
333
337
  return bdg_energies.squeeze(), bdg_wavefunctions.squeeze()
334
338
 
335
- def gap_equation(
336
- self,
337
- k: npt.NDArray[np.float64],
338
- ) -> npt.NDArray[np.complex64]:
339
+ def gap_equation(self, k: npt.NDArray[np.floating]) -> npt.NDArray[np.complexfloating]:
340
+ """Gap equation.
341
+
342
+ Parameters
343
+ ----------
344
+ k : :class:`numpy.ndarray`
345
+ k grid
346
+
347
+ Returns
348
+ -------
349
+ New delta
350
+ """
351
+ bdg_energies, bdg_wavefunctions = self.diagonalize_bdg(k=k)
352
+ delta = np.zeros(self.number_of_bands, dtype=np.complex128)
353
+ return self.gap_equation_loop(
354
+ bdg_energies, bdg_wavefunctions, delta, self.beta, self.hubbard_int_orbital_basis, k
355
+ )
356
+
357
+ @staticmethod
358
+ @jit
359
+ def gap_equation_loop(
360
+ bdg_energies: npt.NDArray[np.float64],
361
+ bdg_wavefunctions: npt.NDArray[np.complex128],
362
+ delta: npt.NDArray[np.float64],
363
+ beta: float,
364
+ hubbard_int_orbital_basis: npt.NDArray[np.float64],
365
+ k: npt.NDArray[np.floating],
366
+ ) -> npt.NDArray[np.complexfloating]:
339
367
  """Calculate the gap equation.
340
368
 
341
369
  The gap equation determines the order parameter for superconductivity by
@@ -343,6 +371,16 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
343
371
 
344
372
  Parameters
345
373
  ----------
374
+ bdg_energies : :class:`numpy.ndarray`
375
+ BdG energies
376
+ bdg_wavefunctions : :class:`numpy.ndarray`
377
+ BdG wavefunctions
378
+ delta : :class:`numpy.ndarray`
379
+ Delta
380
+ beta : :class:`float`
381
+ Beta
382
+ hubbard_int_orbital_basis : :class:`numpy.ndarray`
383
+ Hubard interaction in orbital basis
346
384
  k : :class:`numpy.ndarray`
347
385
  List of k points in reciprocal space.
348
386
 
@@ -351,29 +389,27 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
351
389
  :class:`numpy.ndarray`
352
390
  New pairing gap in orbital basis, adjusted to remove global phase.
353
391
  """
354
- bdg_energies, bdg_wavefunctions = self.diagonalize_bdg(k=k)
355
- delta = np.zeros(self.number_of_bands, dtype=np.complex64)
356
-
357
- for i in range(self.number_of_bands):
392
+ number_of_bands = len(delta)
393
+ for i in range(number_of_bands):
358
394
  sum_tmp = 0
359
- for j in range(2 * self.number_of_bands):
395
+ for j in range(2 * number_of_bands):
360
396
  for k_index in range(len(k)):
361
397
  sum_tmp += (
362
398
  np.conjugate(bdg_wavefunctions[k_index, i, j])
363
- * bdg_wavefunctions[k_index, i + self.number_of_bands, j]
364
- * _fermi_dirac(bdg_energies[k_index, j].item(), self.beta)
399
+ * bdg_wavefunctions[k_index, i + number_of_bands, j]
400
+ * fermi_dirac(bdg_energies[k_index, j].item(), beta)
365
401
  )
366
- delta[i] = (-self.hubbard_int_orbital_basis[i] * sum_tmp / len(k)).conjugate()
402
+ delta[i] = (-hubbard_int_orbital_basis[i] * sum_tmp / len(k)).conjugate()
367
403
 
368
- delta_without_phase: npt.NDArray[np.complex64] = delta * np.exp(
404
+ delta_without_phase: npt.NDArray[np.complexfloating] = delta * np.exp(
369
405
  -1j * np.angle(delta[np.argmax(np.abs(delta))])
370
406
  )
371
407
  return delta_without_phase
372
408
 
373
409
  def calculate_bandstructure(
374
410
  self,
375
- k: npt.NDArray[np.float64],
376
- overlaps: tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]] | None = None,
411
+ k: npt.NDArray[np.floating],
412
+ overlaps: tuple[npt.NDArray[np.floating], npt.NDArray[np.floating]] | None = None,
377
413
  ) -> pd.DataFrame:
378
414
  """Calculate the band structure.
379
415
 
@@ -401,24 +437,24 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
401
437
  energies, wavefunctions = self.diagonalize_nonint(k)
402
438
 
403
439
  for i, (energy_k, wavefunction_k) in enumerate(zip(energies, wavefunctions, strict=False)):
404
- if self.number_of_bands == 1:
440
+ if np.ndim(energy_k) == 0:
405
441
  results.loc[i, "band"] = energy_k
406
442
  else:
407
443
  for band_index in range(self.number_of_bands):
408
- results.loc[i, f"band_{band_index}"] = energy_k[band_index]
444
+ results.loc[i, f"band_{band_index}"] = energy_k[band_index] # type: ignore[index]
409
445
 
410
446
  if overlaps is not None:
411
447
  results.loc[i, f"wx_{band_index}"] = (
412
- np.abs(np.dot(wavefunction_k[:, band_index], overlaps[0])) ** 2
413
- - np.abs(np.dot(wavefunction_k[:, band_index], overlaps[1])) ** 2
448
+ np.abs(np.dot(wavefunction_k[:, band_index], overlaps[0])) ** 2 # type: ignore[index]
449
+ - np.abs(np.dot(wavefunction_k[:, band_index], overlaps[1])) ** 2 # type: ignore[index]
414
450
  )
415
451
 
416
452
  return results
417
453
 
418
454
  def calculate_density_of_states(
419
455
  self,
420
- k: npt.NDArray[np.float64],
421
- ) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]:
456
+ k: npt.NDArray[np.floating],
457
+ ) -> tuple[npt.NDArray[np.floating], npt.NDArray[np.floating]]:
422
458
  """Calculate the density of states (DOS).
423
459
 
424
460
  This method computes the density of states by evaluating the eigenvalues
@@ -437,16 +473,35 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
437
473
  - numpy.ndarray: The density of states corresponding to each energy level.
438
474
  """
439
475
  bands, _ = self.diagonalize_bdg(k=k)
440
- energies = np.linspace(start=np.min(bands), stop=np.max(bands), num=5000)
476
+ gap_fraction = 10
477
+ energies = np.concatenate(
478
+ [
479
+ np.linspace(
480
+ start=np.min(bands),
481
+ stop=-gap_fraction * np.max(np.abs(self.delta_orbital_basis)),
482
+ num=100,
483
+ ),
484
+ np.linspace(
485
+ start=-gap_fraction * np.max(np.abs(self.delta_orbital_basis)),
486
+ stop=gap_fraction * np.max(np.abs(self.delta_orbital_basis)),
487
+ num=200,
488
+ ),
489
+ np.linspace(
490
+ start=gap_fraction * np.max(np.abs(self.delta_orbital_basis)),
491
+ stop=np.max(bands),
492
+ num=100,
493
+ ),
494
+ ]
495
+ )
441
496
  density_of_states = np.zeros(shape=energies.shape, dtype=np.float64)
442
497
 
443
498
  for i, energy in enumerate(energies):
444
499
  density_of_states[i] = np.sum(
445
- _gaussian(x=(energy - bands.flatten()), sigma=1e-2)
500
+ _gaussian(x=(energy - bands.flatten()), sigma=0.01)
446
501
  ) / len(k)
447
502
  return energies, density_of_states
448
503
 
449
- def calculate_spectral_gap(self, k: npt.NDArray[np.float64]) -> float:
504
+ def calculate_spectral_gap(self, k: npt.NDArray[np.floating]) -> float:
450
505
  """Calculate the spectral gap.
451
506
 
452
507
  This method evaluates the spectral gap of the system by examining the
@@ -466,13 +521,15 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
466
521
  """
467
522
  energies, density_of_states = self.calculate_density_of_states(k=k)
468
523
 
469
- coherence_peaks = np.where(np.isclose(density_of_states, np.max(density_of_states)))[0]
524
+ coherence_peaks = np.where(
525
+ np.isclose(density_of_states, np.max(density_of_states), rtol=1e-2)
526
+ )[0]
470
527
 
471
- gap_region = density_of_states[coherence_peaks[0] : coherence_peaks[1] + 1] / np.max(
528
+ gap_region = density_of_states[coherence_peaks[0] : coherence_peaks[-1] + 1] / np.max(
472
529
  density_of_states
473
530
  )
474
- energies_gap_region = energies[coherence_peaks[0] : coherence_peaks[1] + 1]
475
- zero_indeces = np.where(gap_region <= 1e-10)[0]
531
+ energies_gap_region = energies[coherence_peaks[0] : coherence_peaks[-1] + 1]
532
+ zero_indeces = np.where(gap_region <= 1e-6)[0]
476
533
  if len(zero_indeces) == 0:
477
534
  gap = 0
478
535
  else:
@@ -482,16 +539,195 @@ class BaseHamiltonian(Generic[GenericParameters], ABC):
482
539
 
483
540
  return gap
484
541
 
542
+ def calculate_free_energy(self, k: npt.NDArray[np.floating]) -> float:
543
+ """Calculate the free energy for the Hamiltonian.
485
544
 
486
- def _gaussian(x: npt.NDArray[np.float64], sigma: float) -> npt.NDArray[np.float64]:
487
- gaussian: npt.NDArray[np.float64] = np.exp(-(x**2) / (2 * sigma**2)) / np.sqrt(
488
- 2 * np.pi * sigma**2
489
- )
490
- return gaussian
545
+ Parameters
546
+ ----------
547
+ k
548
+
549
+ Returns
550
+ -------
551
+ free_energy
552
+
553
+ """
554
+ number_k_points = len(k)
555
+ bdg_energies, _ = self.diagonalize_bdg(k)
556
+ integral: float = 0
557
+
558
+ k_array = (
559
+ 1
560
+ / self.beta
561
+ * np.array(
562
+ [
563
+ np.sum(np.log(1 + np.exp(-self.beta * bdg_energies[k_index])))
564
+ for k_index in range(number_k_points)
565
+ ]
566
+ )
567
+ )
568
+
569
+ integral += -np.sum(k_array, axis=-1) / number_k_points + 0.5 * np.sum(
570
+ np.power(np.abs(self.delta_orbital_basis), 2) / self.hubbard_int_orbital_basis
571
+ )
572
+
573
+ return integral
574
+
575
+ def calculate_current_density(self, k: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
576
+ """Calculate the current density.
577
+
578
+ Parameters
579
+ ----------
580
+ k
581
+
582
+ Returns
583
+ -------
584
+ current_density
585
+
586
+ """
587
+ bdg_energies, bdg_wavefunctions = self.diagonalize_bdg(k=k)
588
+ h_der_x = self.hamiltonian_derivative(k=k, direction="x")
589
+ h_der_y = self.hamiltonian_derivative(k=k, direction="y")
590
+
591
+ current = np.zeros(2, dtype=np.complex128)
592
+
593
+ matrix_x = np.zeros((3, 3), dtype=np.complex128)
594
+ matrix_y = np.zeros((3, 3), dtype=np.complex128)
595
+
596
+ for k_index in range(len(k)):
597
+ for i in range(self.number_of_bands):
598
+ for j in range(self.number_of_bands):
599
+ for n in range(2 * self.number_of_bands):
600
+ matrix_x[i, j] += (
601
+ h_der_x[k_index, i, j]
602
+ * np.conjugate(bdg_wavefunctions[k_index, i, n])
603
+ * bdg_wavefunctions[k_index, j, n]
604
+ * fermi_dirac(bdg_energies[k_index, n].item(), self.beta)
605
+ )
606
+ matrix_y[i, j] *= (
607
+ h_der_y[k_index, i, j]
608
+ * np.conjugate(bdg_wavefunctions[k_index, i, n])
609
+ * bdg_wavefunctions[k_index, j, n]
610
+ * fermi_dirac(bdg_energies[k_index, n].item(), self.beta)
611
+ )
491
612
 
613
+ current[0] = np.sum(matrix_x, axis=None)
614
+ current[1] = np.sum(matrix_y, axis=None)
615
+ assert np.allclose(np.imag(current), 0, atol=1e-12)
492
616
 
493
- def _fermi_dirac(energy: float, beta: float | None) -> float:
494
- fermi_dirac: float = (
495
- (1 if energy < 0 else 0) if beta is None else 1 / (1 + np.exp(beta * energy))
617
+ return (2 * np.real(current)) / len(k)
618
+
619
+ def calculate_superfluid_weight(
620
+ self,
621
+ k: npt.NDArray[np.floating],
622
+ ) -> tuple[npt.NDArray[np.complexfloating], npt.NDArray[np.complexfloating]]:
623
+ """Calculate the superfluid weight.
624
+
625
+ Parameters
626
+ ----------
627
+ h : :class:`~quant_met.mean_field.Hamiltonian`
628
+ Hamiltonian.
629
+ k : :class:`numpy.ndarray`
630
+ List of k points.
631
+
632
+ Returns
633
+ -------
634
+ :class:`numpy.ndarray`
635
+ Conventional contribution to the superfluid weight.
636
+ :class:`numpy.ndarray`
637
+ Geometric contribution to the superfluid weight.
638
+
639
+ """
640
+ s_weight_conv = np.zeros(shape=(2, 2), dtype=np.complex128)
641
+ s_weight_geom = np.zeros(shape=(2, 2), dtype=np.complex128)
642
+
643
+ c_mnpq_cache = {}
644
+
645
+ for i, direction_1 in enumerate(["x", "y"]):
646
+ for j, direction_2 in enumerate(["x", "y"]):
647
+ for k_point in k:
648
+ k_tuple = tuple(k_point)
649
+
650
+ if k_tuple not in c_mnpq_cache:
651
+ c_mnpq_cache[k_tuple] = self._c_factor(k_point)
652
+ c_mnpq = c_mnpq_cache[k_tuple]
653
+
654
+ j_up = self._current_operator(direction_1, k_point)
655
+ j_down = self._current_operator(direction_2, -k_point)
656
+
657
+ for m in range(self.number_of_bands):
658
+ for n in range(self.number_of_bands):
659
+ for p in range(self.number_of_bands):
660
+ for q in range(self.number_of_bands):
661
+ s_weight = c_mnpq[m, n, p, q] * j_up[m, n] * j_down[q, p]
662
+ if m == n and p == q:
663
+ s_weight_conv[i, j] += s_weight
664
+ else:
665
+ s_weight_geom[i, j] += s_weight
666
+
667
+ return s_weight_conv, s_weight_geom
668
+
669
+ def _current_operator(
670
+ self, direction: str, k: npt.NDArray[np.floating]
671
+ ) -> npt.NDArray[np.complexfloating]:
672
+ j = np.zeros(shape=(self.number_of_bands, self.number_of_bands), dtype=np.complex128)
673
+
674
+ _, bloch = self.diagonalize_nonint(k=k)
675
+
676
+ for m in range(self.number_of_bands):
677
+ for n in range(self.number_of_bands):
678
+ j[m, n] = (
679
+ bloch[:, m].conjugate()
680
+ @ self.hamiltonian_derivative(direction=direction, k=k)
681
+ @ bloch[:, n]
682
+ )
683
+
684
+ return j
685
+
686
+ def _c_factor(self, k: npt.NDArray[np.floating]) -> npt.NDArray[np.complexfloating]:
687
+ bdg_energies, bdg_functions = self.diagonalize_bdg(k)
688
+ c_mnpq = np.zeros(
689
+ shape=(
690
+ self.number_of_bands,
691
+ self.number_of_bands,
692
+ self.number_of_bands,
693
+ self.number_of_bands,
694
+ ),
695
+ dtype=np.complex128,
696
+ )
697
+
698
+ for m in range(self.number_of_bands):
699
+ for n in range(self.number_of_bands):
700
+ for p in range(self.number_of_bands):
701
+ for q in range(self.number_of_bands):
702
+ c_tmp: float = 0
703
+ for i in range(2 * self.number_of_bands):
704
+ for j in range(2 * self.number_of_bands):
705
+ if bdg_energies[i] != bdg_energies[j]:
706
+ c_tmp += (
707
+ fermi_dirac(bdg_energies[i], self.beta)
708
+ - fermi_dirac(bdg_energies[j], self.beta)
709
+ ) / (bdg_energies[i] - bdg_energies[j])
710
+ else:
711
+ c_tmp -= _fermi_dirac_derivative()
712
+
713
+ c_tmp *= (
714
+ bdg_functions[i, m].conjugate()
715
+ * bdg_functions[j, n]
716
+ * bdg_functions[j, p].conjugate()
717
+ * bdg_functions[i, q].conjugate()
718
+ )
719
+
720
+ c_mnpq[m, n, p, q] = 2 * c_tmp
721
+
722
+ return c_mnpq
723
+
724
+
725
+ def _fermi_dirac_derivative() -> float:
726
+ return 0
727
+
728
+
729
+ def _gaussian(x: npt.NDArray[np.floating], sigma: float) -> npt.NDArray[np.floating]:
730
+ gaussian: npt.NDArray[np.floating] = np.exp(-(x**2) / (2 * sigma**2)) / np.sqrt(
731
+ 2 * np.pi * sigma**2
496
732
  )
497
- return fermi_dirac
733
+ return gaussian
@@ -26,7 +26,7 @@ class DressedGraphene(BaseHamiltonian[DressedGrapheneParameters]):
26
26
  self.hubbard_int_orbital_basis = parameters.hubbard_int_orbital_basis
27
27
  self.chemical_potential = parameters.chemical_potential
28
28
  if parameters.delta is not None:
29
- self.delta_orbital_basis = np.astype(parameters.delta, np.complex64)
29
+ self.delta_orbital_basis = parameters.delta.astype(np.complex128)
30
30
 
31
31
  def setup_lattice(self, parameters: DressedGrapheneParameters) -> BaseLattice: # noqa: D102
32
32
  return GrapheneLattice(lattice_constant=parameters.lattice_constant)
@@ -35,7 +35,7 @@ class DressedGraphene(BaseHamiltonian[DressedGrapheneParameters]):
35
35
  def get_parameters_model(cls) -> type[DressedGrapheneParameters]: # noqa: D102
36
36
  return DressedGrapheneParameters
37
37
 
38
- def hamiltonian(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]: # noqa: D102
38
+ def hamiltonian(self, k: npt.NDArray[np.floating]) -> npt.NDArray[np.complexfloating]: # noqa: D102
39
39
  assert _check_valid_array(k)
40
40
 
41
41
  t_gr = self.hopping_gr
@@ -46,7 +46,7 @@ class DressedGraphene(BaseHamiltonian[DressedGrapheneParameters]):
46
46
  if k.ndim == 1:
47
47
  k = np.expand_dims(k, axis=0)
48
48
 
49
- h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex64)
49
+ h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex128)
50
50
 
51
51
  h[:, 0, 1] = -t_gr * (
52
52
  np.exp(1j * k[:, 1] * a / np.sqrt(3))
@@ -73,8 +73,8 @@ class DressedGraphene(BaseHamiltonian[DressedGrapheneParameters]):
73
73
  return h.squeeze()
74
74
 
75
75
  def hamiltonian_derivative( # noqa: D102
76
- self, k: npt.NDArray[np.float64], direction: str
77
- ) -> npt.NDArray[np.complex64]:
76
+ self, k: npt.NDArray[np.floating], direction: str
77
+ ) -> npt.NDArray[np.complexfloating]:
78
78
  assert _check_valid_array(k)
79
79
  assert direction in ["x", "y"]
80
80
 
@@ -84,7 +84,7 @@ class DressedGraphene(BaseHamiltonian[DressedGrapheneParameters]):
84
84
  if k.ndim == 1:
85
85
  k = np.expand_dims(k, axis=0)
86
86
 
87
- h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex64)
87
+ h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex128)
88
88
 
89
89
  if direction == "x":
90
90
  h[:, 0, 1] = (
@@ -25,7 +25,7 @@ class Graphene(BaseHamiltonian[GrapheneParameters]):
25
25
  self.hopping = parameters.hopping
26
26
  self.chemical_potential = parameters.chemical_potential
27
27
  if parameters.delta is not None:
28
- self.delta_orbital_basis = np.astype(parameters.delta, np.complex64)
28
+ self.delta_orbital_basis = parameters.delta.astype(np.complex128)
29
29
 
30
30
  def setup_lattice(self, parameters: GrapheneParameters) -> GrapheneLattice: # noqa: D102
31
31
  return GrapheneLattice(lattice_constant=parameters.lattice_constant)
@@ -34,7 +34,7 @@ class Graphene(BaseHamiltonian[GrapheneParameters]):
34
34
  def get_parameters_model(cls) -> type[GrapheneParameters]: # noqa: D102
35
35
  return GrapheneParameters
36
36
 
37
- def hamiltonian(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]: # noqa: D102
37
+ def hamiltonian(self, k: npt.NDArray[np.floating]) -> npt.NDArray[np.complexfloating]: # noqa: D102
38
38
  assert _check_valid_array(k)
39
39
  hopping = self.hopping
40
40
  lattice_constant = self.lattice.lattice_constant
@@ -42,7 +42,7 @@ class Graphene(BaseHamiltonian[GrapheneParameters]):
42
42
  if k.ndim == 1:
43
43
  k = np.expand_dims(k, axis=0)
44
44
 
45
- h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex64)
45
+ h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex128)
46
46
 
47
47
  h[:, 0, 1] = -hopping * (
48
48
  np.exp(1j * k[:, 1] * lattice_constant / np.sqrt(3))
@@ -57,8 +57,8 @@ class Graphene(BaseHamiltonian[GrapheneParameters]):
57
57
  return h.squeeze()
58
58
 
59
59
  def hamiltonian_derivative( # noqa: D102
60
- self, k: npt.NDArray[np.float64], direction: str
61
- ) -> npt.NDArray[np.complex64]:
60
+ self, k: npt.NDArray[np.floating], direction: str
61
+ ) -> npt.NDArray[np.complexfloating]:
62
62
  assert _check_valid_array(k)
63
63
  assert direction in ["x", "y"]
64
64
 
@@ -67,7 +67,7 @@ class Graphene(BaseHamiltonian[GrapheneParameters]):
67
67
  if k.ndim == 1:
68
68
  k = np.expand_dims(k, axis=0)
69
69
 
70
- h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex64)
70
+ h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex128)
71
71
 
72
72
  if direction == "x":
73
73
  h[:, 0, 1] = (
@@ -22,7 +22,7 @@ class OneBand(BaseHamiltonian[OneBandParameters]):
22
22
  self.hopping = parameters.hopping
23
23
  self.chemical_potential = parameters.chemical_potential
24
24
  if parameters.delta is not None:
25
- self.delta_orbital_basis = np.astype(parameters.delta, np.complex64)
25
+ self.delta_orbital_basis = parameters.delta.astype(np.complex128)
26
26
 
27
27
  def setup_lattice(self, parameters: OneBandParameters) -> SquareLattice: # noqa: D102
28
28
  return SquareLattice(lattice_constant=parameters.lattice_constant)
@@ -31,7 +31,7 @@ class OneBand(BaseHamiltonian[OneBandParameters]):
31
31
  def get_parameters_model(cls) -> type[OneBandParameters]: # noqa: D102
32
32
  return OneBandParameters
33
33
 
34
- def hamiltonian(self, k: npt.NDArray[np.float64]) -> npt.NDArray[np.complex64]: # noqa: D102
34
+ def hamiltonian(self, k: npt.NDArray[np.floating]) -> npt.NDArray[np.complexfloating]: # noqa: D102
35
35
  assert _check_valid_array(k)
36
36
  hopping = self.hopping
37
37
  lattice_constant = self.lattice.lattice_constant
@@ -39,7 +39,7 @@ class OneBand(BaseHamiltonian[OneBandParameters]):
39
39
  if k.ndim == 1:
40
40
  k = np.expand_dims(k, axis=0)
41
41
 
42
- h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex64)
42
+ h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex128)
43
43
 
44
44
  h[:, 0, 0] = (
45
45
  -2 * hopping * (np.cos(k[:, 1] * lattice_constant) + np.cos(k[:, 0] * lattice_constant))
@@ -49,8 +49,8 @@ class OneBand(BaseHamiltonian[OneBandParameters]):
49
49
  return h
50
50
 
51
51
  def hamiltonian_derivative( # noqa: D102
52
- self, k: npt.NDArray[np.float64], direction: str
53
- ) -> npt.NDArray[np.complex64]:
52
+ self, k: npt.NDArray[np.floating], direction: str
53
+ ) -> npt.NDArray[np.complexfloating]:
54
54
  assert _check_valid_array(k)
55
55
  assert direction in ["x", "y"]
56
56
 
@@ -59,7 +59,7 @@ class OneBand(BaseHamiltonian[OneBandParameters]):
59
59
  if k.ndim == 1:
60
60
  k = np.expand_dims(k, axis=0)
61
61
 
62
- h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex64)
62
+ h = np.zeros((k.shape[0], self.number_of_bands, self.number_of_bands), dtype=np.complex128)
63
63
 
64
64
  if direction == "x":
65
65
  h[:, 0, 0] = -2 * hopping * lattice_constant * np.sin(lattice_constant * k[:, 0])