sparse-ir 1.1.6__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 +33 -15
- sparse_ir/abstract.py +70 -82
- sparse_ir/augment.py +27 -17
- sparse_ir/basis.py +130 -239
- sparse_ir/basis_set.py +99 -57
- sparse_ir/dlr.py +131 -88
- sparse_ir/kernel.py +54 -477
- sparse_ir/poly.py +221 -476
- sparse_ir/sampling.py +260 -371
- sparse_ir/sve.py +56 -358
- sparse_ir-2.0.0a2.dist-info/METADATA +23 -0
- sparse_ir-2.0.0a2.dist-info/RECORD +16 -0
- {sparse_ir-1.1.6.dist-info → sparse_ir-2.0.0a2.dist-info}/WHEEL +1 -1
- sparse_ir/_gauss.py +0 -260
- sparse_ir/_roots.py +0 -140
- sparse_ir/adapter.py +0 -267
- sparse_ir/svd.py +0 -102
- sparse_ir-1.1.6.dist-info/METADATA +0 -155
- sparse_ir-1.1.6.dist-info/RECORD +0 -20
- {sparse_ir-1.1.6.dist-info → sparse_ir-2.0.0a2.dist-info/licenses}/LICENSE.txt +0 -0
- {sparse_ir-1.1.6.dist-info → sparse_ir-2.0.0a2.dist-info}/top_level.txt +0 -0
sparse_ir/__init__.py
CHANGED
@@ -1,21 +1,39 @@
|
|
1
|
-
|
2
1
|
"""
|
3
|
-
|
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
|
-
|
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.6"
|
16
6
|
|
17
|
-
from .
|
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
|
-
|
2
|
-
|
1
|
+
"""
|
2
|
+
Abstract base class for basis objects.
|
3
3
|
|
4
|
-
|
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.
|
8
|
-
propagator
|
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
|
-
|
19
|
+
G(τ) ≈ Σ_{l=0}^{L-1} g_l U_l(τ)
|
11
20
|
|
12
|
-
where
|
13
|
-
|
14
|
-
|
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
|
-
|
25
|
+
Ĝ(n) ≈ Σ_{l=0}^{L-1} g_l Û_l(n)
|
18
26
|
|
19
|
-
where
|
20
|
-
in
|
27
|
+
where Û is the Fourier transform of the l-th basis function, stored
|
28
|
+
in uhat.
|
21
29
|
|
22
|
-
Assuming that
|
23
|
-
|
24
|
-
|
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
|
36
|
-
|
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
|
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 (
|
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.
|
62
|
-
Fourier transform:
|
63
|
-
|
64
|
-
.. math::
|
59
|
+
wn is an integer. These are related to u by the following Fourier transform:
|
65
60
|
|
66
|
-
|
61
|
+
û(n) = ∫₀^β dτ exp(iπnτ/β) u(τ)
|
67
62
|
|
68
|
-
To get the
|
69
|
-
some basis
|
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
|
92
|
-
are
|
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 (
|
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:
|
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
|
-
|
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.
|
124
|
-
value is a number between 0 and 1 which is
|
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
|
-
|
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
|
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,
|
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
|
151
|
-
|
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
|
-
|
157
|
-
|
158
|
-
|
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
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
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
|
-
|
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
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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
|
-
|
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,
|
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,
|
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,
|
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")
|