sparse-ir 1.1.7__py3-none-any.whl → 2.0.0a2__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.
sparse_ir/__init__.py CHANGED
@@ -1,21 +1,39 @@
1
-
2
1
  """
3
- Intermediate representation (IR) for many-body propagators
4
- ==========================================================
5
-
6
- This library provides routines for constructing and working with the
7
- intermediate representation of correlation functions. It provides:
2
+ SparseIR Python bindings
8
3
 
9
- - on-the-fly computation of basis functions for arbitrary cutoff Λ
10
- - basis functions and singular values are accurate to full precision
11
- - routines for sparse sampling
4
+ This package provides Python bindings for the SparseIR C library.
12
5
  """
13
- __copyright__ = "2020-2025 Markus Wallerberger, Hiroshi Shinaoka, and others"
14
- __license__ = "MIT"
15
- __version__ = "1.1.7"
16
6
 
17
- from .kernel import RegularizedBoseKernel, LogisticKernel
18
- from .sve import compute as compute_sve, SVEResult
7
+ from .abstract import AbstractBasis
19
8
  from .basis import FiniteTempBasis, finite_temp_bases
20
- from .basis_set import FiniteTempBasisSet
21
9
  from .sampling import TauSampling, MatsubaraSampling
10
+ from .kernel import LogisticKernel, RegularizedBoseKernel
11
+ from .sve import SVEResult, compute
12
+ from .basis_set import FiniteTempBasisSet
13
+
14
+ # New augmented functionality
15
+ from .augment import (
16
+ AugmentedBasis, AugmentedTauFunction, AugmentedMatsubaraFunction,
17
+ AbstractAugmentation, TauConst, TauLinear, MatsubaraConst
18
+ )
19
+
20
+ # DLR functionality
21
+ from .dlr import (
22
+ DiscreteLehmannRepresentation
23
+ )
24
+
25
+ # Export list for better documentation
26
+ __all__ = [
27
+ # Core functionality
28
+ 'AbstractBasis', 'FiniteTempBasis', 'finite_temp_bases',
29
+ 'TauSampling', 'MatsubaraSampling', 'FiniteTempBasisSet',
30
+ 'LogisticKernel', 'RegularizedBoseKernel',
31
+ 'SVEResult', 'compute',
32
+
33
+ # Augmented functionality
34
+ 'AugmentedBasis', 'AugmentedTauFunction', 'AugmentedMatsubaraFunction',
35
+ 'AbstractAugmentation', 'TauConst', 'TauLinear', 'MatsubaraConst',
36
+
37
+ # DLR functionality
38
+ 'DiscreteLehmannRepresentation', 'TauPoles', 'MatsubaraPoles',
39
+ ]
sparse_ir/abstract.py CHANGED
@@ -1,184 +1,172 @@
1
- # Copyright (C) 2020-2022 Markus Wallerberger, Hiroshi Shinaoka, and others
2
- # SPDX-License-Identifier: MIT
1
+ """
2
+ Abstract base class for basis objects.
3
3
 
4
- class AbstractBasis:
4
+ This module provides the abstract interface that all basis types should implement.
5
+ """
6
+
7
+ from abc import ABC, abstractmethod
8
+
9
+ class AbstractKernel(ABC):
10
+ """Abstract base class for kernels."""
11
+ pass
12
+
13
+ class AbstractBasis(ABC):
5
14
  r"""Abstract base class for bases on the imaginary-time axis.
6
15
 
7
- This class stores a set of basis functions. We can then expand a two-point
8
- propagator `G(τ)`, where `τ` is imaginary time:
16
+ This class stores a set of basis functions. We can then expand a two-point
17
+ propagator G(τ), where τ is imaginary time:
9
18
 
10
- .. math:: G(\tau) \approx \sum_{l=0}^{L-1} g_l U_l(\tau)
19
+ G(τ) Σ_{l=0}^{L-1} g_l U_l(τ)
11
20
 
12
- where `U` is now the `l`-th basis function, stored in :py:attr:`u` and
13
- `g` denote the expansion coefficients. Similarly, the Fourier transform
14
- `Ĝ(n)`, where `n` is a reduced Matsubara frequency, can be expanded as
15
- follows:
21
+ where U is now the l-th basis function, stored in u and g denote the
22
+ expansion coefficients. Similarly, the Fourier transform Ĝ(n), where n
23
+ is a reduced Matsubara frequency, can be expanded as follows:
16
24
 
17
- .. math:: \hat G(n) \approx \sum_{l=0}^{L-1} g_l \hat U_l(n)
25
+ Ĝ(n) Σ_{l=0}^{L-1} g_l Û_l(n)
18
26
 
19
- where `Û` is the Fourier transform of the `l`-th basis function, stored
20
- in :py:attr:`uhat`.
27
+ where Û is the Fourier transform of the l-th basis function, stored
28
+ in uhat.
21
29
 
22
- Assuming that ``basis`` is an instance of some abstract basis, ``g``
23
- is a vector of expansion coefficients, ``tau`` is some imaginary time and
24
- ``n`` some frequency, we can write this in the library as follows::
30
+ Assuming that basis is an instance of some abstract basis, g is a vector
31
+ of expansion coefficients, tau is some imaginary time and n some frequency,
32
+ we can write this in the library as follows:
25
33
 
26
34
  G_tau = basis.u(tau).T @ gl
27
35
  G_n = basis.uhat(n).T @ gl
28
-
29
36
  """
37
+
30
38
  @property
39
+ @abstractmethod
31
40
  def u(self):
32
41
  r"""Basis functions on the imaginary time axis.
33
42
 
34
43
  Set of IR basis functions on the imaginary time (tau) axis, where tau
35
- is a real number between zero and :py:attr:`beta`. To get the ``l``-th
36
- basis function at imaginary time ``tau`` of some basis ``basis``, use::
44
+ is a real number between zero and beta. To get the l-th basis function
45
+ at imaginary time tau of some basis, use:
37
46
 
38
47
  ultau = basis.u[l](tau) # l-th basis function at time tau
39
48
 
40
- Note that ``u`` supports vectorization both over ``l`` and ``tau``.
41
- In particular, omitting the subscript yields a vector with all basis
42
- functions, evaluated at that position::
43
-
44
- basis.u(tau) == [basis.u[l](tau) for l in range(basis.size)]
45
-
46
- Similarly, supplying a vector of `tau` points yields a matrix ``A``,
47
- where ``A[l,n]`` corresponds to the ``l``-th basis function evaluated
48
- at ``tau[n]``::
49
-
50
- tau = [0.5, 1.0]
51
- basis.u(tau) == \
52
- [[basis.u[l](t) for t in tau] for l in range(basis.size)]
49
+ Note that u supports vectorization both over l and tau.
53
50
  """
54
51
  raise NotImplementedError()
55
52
 
56
53
  @property
54
+ @abstractmethod
57
55
  def uhat(self):
58
- r"""Basis functions on the reduced Matsubara frequency (``wn``) axis.
56
+ r"""Basis functions on the reduced Matsubara frequency (wn) axis.
59
57
 
60
58
  Set of IR basis functions reduced Matsubara frequency (wn) axis, where
61
- wn is an integer. These are related to :py:attr:`u` by the following
62
- Fourier transform:
63
-
64
- .. math::
59
+ wn is an integer. These are related to u by the following Fourier transform:
65
60
 
66
- \hat u(n) = \int_0^\beta d\tau \exp(i\pi n \tau/\beta) u(\tau)
61
+ û(n) = ∫₀^β dτ exp(iπnτ/β) u(τ)
67
62
 
68
- To get the ``l``-th basis function at some reduced frequency ``wn`` of
69
- some basis ``basis``, use::
63
+ To get the l-th basis function at some reduced frequency wn of
64
+ some basis, use:
70
65
 
71
66
  uln = basis.uhat[l](wn) # l-th basis function at freq wn
72
67
 
73
- ``uhat`` supports vectorization both over ``l`` and ``wn``.
74
- In particular, omitting the subscript yields a vector with all basis
75
- functions, evaluated at that position::
76
-
77
- basis.uhat(wn) == [basis.uhat[l](wn) for l in range(basis.size)]
78
-
79
- Similarly, supplying a vector of `wn` points yields a matrix ``A``,
80
- where ``A[l,n]`` corresponds to the ``l``-th basis function evaluated
81
- at ``wn[n]``::
82
-
83
- wn = [1, 3]
84
- basis.uhat(wn) == \\
85
- [[basis.uhat[l](wi) for wi in wn] for l in range(basis.size)]
86
-
87
68
  Note:
88
69
  Instead of the value of the Matsubara frequency, these functions
89
70
  expect integers corresponding to the prefactor of pi over beta.
90
71
  For example, the first few positive fermionic frequencies would
91
- be specified as ``[1, 3, 5, 7]``, and the first bosonic frequencies
92
- are ``[0, 2, 4, 6]``. This is also distinct to an index!
72
+ be specified as [1, 3, 5, 7], and the first bosonic frequencies
73
+ are [0, 2, 4, 6]. This is also distinct to an index!
93
74
  """
94
75
  raise NotImplementedError()
95
76
 
96
77
  @property
78
+ @abstractmethod
97
79
  def statistics(self):
98
- """Quantum statistic (`"F"` for fermionic, `"B"` for bosonic)"""
80
+ """Quantum statistic ("F" for fermionic, "B" for bosonic)"""
99
81
  raise NotImplementedError()
100
82
 
101
83
  def __getitem__(self, index):
102
84
  """Return basis functions/singular values for given index/indices.
103
85
 
104
86
  This can be used to truncate the basis to the n most significant
105
- singular values: `basis[:3]`.
87
+ singular values: basis[:3].
106
88
  """
107
89
  raise NotImplementedError()
108
90
 
109
91
  @property
110
92
  def shape(self):
111
93
  """Shape of the basis function set"""
112
- raise NotImplementedError()
94
+ return (self.size,)
113
95
 
114
96
  @property
97
+ @abstractmethod
115
98
  def size(self):
116
99
  """Number of basis functions / singular values"""
117
100
  raise NotImplementedError()
118
101
 
119
102
  @property
103
+ @abstractmethod
120
104
  def significance(self):
121
105
  """Significances of the basis functions
122
106
 
123
- Vector of significance values, one for each basis function. Each
124
- value is a number between 0 and 1 which is a a-priori bound on the
107
+ Vector of significance values, one for each basis function. Each
108
+ value is a number between 0 and 1 which is an a-priori bound on the
125
109
  (relative) error made by discarding the associated coefficient.
126
110
  """
127
- return NotImplementedError()
111
+ raise NotImplementedError()
128
112
 
129
113
  @property
130
114
  def accuracy(self):
131
115
  """Accuracy of the basis.
132
116
 
133
- Upper bound to the relative error of reprensenting a propagator with
117
+ Upper bound to the relative error of representing a propagator with
134
118
  the given number of basis functions (number between 0 and 1).
135
119
  """
136
120
  return self.significance[-1]
137
121
 
138
122
  @property
123
+ @abstractmethod
139
124
  def lambda_(self):
140
- """Basis cutoff parameter, == β * wmax`, or None if not present"""
125
+ """Basis cutoff parameter, Λ = β * wmax, or None if not present"""
141
126
  raise NotImplementedError()
142
127
 
143
128
  @property
129
+ @abstractmethod
144
130
  def beta(self):
145
131
  """Inverse temperature"""
146
132
  raise NotImplementedError()
147
133
 
148
134
  @property
149
135
  def wmax(self):
150
- """Real frequency cutoff or `None` if not present"""
151
- raise NotImplementedError()
136
+ """Real frequency cutoff or None if not present"""
137
+ if self.lambda_ is None or self.beta is None:
138
+ return None
139
+ return self.lambda_ / self.beta
152
140
 
141
+ @abstractmethod
153
142
  def default_tau_sampling_points(self, *, npoints=None):
154
143
  """Default sampling points on the imaginary time axis
155
144
 
156
- Arguments:
157
- npoints (int):
158
- Minimum number of sampling points to return.
159
-
160
- .. versionadded: 1.1
145
+ Parameters
146
+ ----------
147
+ npoints : int, optional
148
+ Minimum number of sampling points to return.
161
149
  """
162
150
  raise NotImplementedError()
163
151
 
152
+ @abstractmethod
164
153
  def default_matsubara_sampling_points(self, *, npoints=None,
165
154
  positive_only=False):
166
155
  """Default sampling points on the imaginary frequency axis
167
156
 
168
- Arguments:
169
- npoints (int):
170
- Minimum number of sampling points to return.
171
-
172
- .. versionadded: 1.1
173
- positive_only (bool):
174
- Only return non-negative frequencies. This is useful if the
175
- object to be fitted is symmetric in Matsubura frequency,
176
- ``ghat(w) == ghat(-w).conj()``, or, equivalently, real in
177
- imaginary time.
157
+ Parameters
158
+ ----------
159
+ npoints : int, optional
160
+ Minimum number of sampling points to return.
161
+ positive_only : bool
162
+ Only return non-negative frequencies. This is useful if the
163
+ object to be fitted is symmetric in Matsubara frequency,
164
+ ghat(w) == ghat(-w).conj(), or, equivalently, real in
165
+ imaginary time.
178
166
  """
179
167
  raise NotImplementedError()
180
168
 
181
169
  @property
182
170
  def is_well_conditioned(self):
183
171
  """Returns True if the sampling is expected to be well-conditioned"""
184
- return True
172
+ return True
sparse_ir/augment.py CHANGED
@@ -1,11 +1,12 @@
1
1
  # Copyright (C) 2020-2021 Markus Wallerberger, Hiroshi Shinaoka, and others
2
2
  # SPDX-License-Identifier: MIT
3
- import numpy as np
4
-
5
3
  from . import _util
4
+ import numpy as np
5
+ from ctypes import c_int, byref
6
6
  from . import abstract
7
7
  from . import basis
8
-
8
+ from pylibsparseir.core import basis_get_default_tau_sampling_points_ext, basis_get_n_default_matsus_ext, basis_get_default_matsus_ext
9
+ from pylibsparseir.core import COMPUTATION_SUCCESS
9
10
 
10
11
  class AugmentedBasis(abstract.AbstractBasis):
11
12
  """Augmented basis on the imaginary-time/frequency axis.
@@ -59,6 +60,10 @@ class AugmentedBasis(abstract.AbstractBasis):
59
60
  self._uhat = AugmentedMatsubaraFunction(
60
61
  self._basis.uhat, [aug.hat for aug in augmentations])
61
62
 
63
+ @property
64
+ def basis(self):
65
+ return self._basis
66
+
62
67
  @property
63
68
  def u(self):
64
69
  return self._u
@@ -69,7 +74,7 @@ class AugmentedBasis(abstract.AbstractBasis):
69
74
 
70
75
  @property
71
76
  def statistics(self):
72
- raise self._basis.statistics
77
+ return self._basis.statistics
73
78
 
74
79
  def __getitem__(self, index):
75
80
  stop = basis._slice_to_size(index)
@@ -113,14 +118,19 @@ class AugmentedBasis(abstract.AbstractBasis):
113
118
  # Return the sampling points of the underlying basis, but since we
114
119
  # use the size of self, we add two further points. One then has to
115
120
  # hope that these give good sampling points.
116
- return self._basis.default_tau_sampling_points(npoints=npoints)
117
121
 
118
- def default_matsubara_sampling_points(self, *, npoints=None,
119
- positive_only=False):
120
- if npoints is None:
121
- npoints = self.size
122
- return self._basis.default_matsubara_sampling_points(
123
- npoints=npoints, positive_only=positive_only)
122
+ return basis_get_default_tau_sampling_points_ext(self._basis._ptr, npoints)
123
+
124
+ def default_matsubara_sampling_points(self, *, positive_only=False):
125
+ """Get default Matsubara sampling points for augmented basis.
126
+
127
+ This method provides default sampling points for Matsubara frequencies
128
+ when using an augmented basis.
129
+ """
130
+ n_points_returned = basis_get_n_default_matsus_ext(self._basis._ptr, self.size, positive_only)
131
+ points = np.zeros(n_points_returned, dtype=np.int64)
132
+ basis_get_default_matsus_ext(self._basis._ptr, positive_only, points)
133
+ return points
124
134
 
125
135
  @property
126
136
  def is_well_conditioned(self):
@@ -132,8 +142,8 @@ class AugmentedBasis(abstract.AbstractBasis):
132
142
 
133
143
  class _AugmentedFunction:
134
144
  def __init__(self, fbasis, faug):
135
- if fbasis.ndim != 1:
136
- raise ValueError("must have vector of functions as fbasis")
145
+ #if fbasis.ndim != 1:
146
+ # raise ValueError("must have vector of functions as fbasis")
137
147
  self._fbasis = fbasis
138
148
  self._faug = faug
139
149
  self._naug = len(faug)
@@ -236,7 +246,7 @@ class TauConst(AbstractAugmentation):
236
246
  self._beta = beta
237
247
 
238
248
  def __call__(self, tau):
239
- tau = _util.check_range(tau, 0, self._beta)
249
+ tau = _util.check_range(tau, -self._beta, self._beta)
240
250
  return np.broadcast_to(1 / np.sqrt(self._beta), tau.shape)
241
251
 
242
252
  def deriv(self, n=1):
@@ -264,7 +274,7 @@ class TauLinear(AbstractAugmentation):
264
274
  self._norm = np.sqrt(3/beta)
265
275
 
266
276
  def __call__(self, tau):
267
- tau = _util.check_range(tau, 0, self._beta)
277
+ tau = _util.check_range(tau, -self._beta, self._beta)
268
278
  x = 2/self._beta * tau - 1
269
279
  return self._norm * x
270
280
 
@@ -296,7 +306,7 @@ class MatsubaraConst(AbstractAugmentation):
296
306
  self._beta = beta
297
307
 
298
308
  def __call__(self, tau):
299
- tau = _util.check_range(tau, 0, self._beta)
309
+ tau = _util.check_range(tau, -self._beta, self._beta)
300
310
  return np.broadcast_to(np.nan, tau.shape)
301
311
 
302
312
  def deriv(self, n=1):
@@ -321,4 +331,4 @@ def _check_bosonic_statistics(statistics):
321
331
  elif statistics == 'F':
322
332
  raise ValueError("term only allowed for bosonic basis")
323
333
  else:
324
- raise ValueError("invalid statistics")
334
+ raise ValueError("invalid statistics")