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/dlr.py
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
import numpy as np
|
1
|
+
"""
|
2
|
+
Discrete Lehmann Representation (DLR) functionality for SparseIR.
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
from . import basis as _basis
|
9
|
-
from . import _util
|
10
|
-
from . import svd
|
4
|
+
This module implements DLR basis with poles at IR extrema, providing
|
5
|
+
an alternative representation that can be more efficient for certain calculations.
|
6
|
+
"""
|
11
7
|
|
8
|
+
import ctypes
|
9
|
+
import numpy as np
|
10
|
+
from .abstract import AbstractBasis
|
11
|
+
from pylibsparseir.core import basis_get_default_omega_sampling_points
|
12
|
+
from pylibsparseir.core import _lib, COMPUTATION_SUCCESS
|
13
|
+
from pylibsparseir.constants import SPIR_ORDER_ROW_MAJOR
|
12
14
|
|
13
|
-
class DiscreteLehmannRepresentation(
|
15
|
+
class DiscreteLehmannRepresentation(AbstractBasis):
|
14
16
|
"""Discrete Lehmann representation (DLR), with poles being extrema of IR.
|
15
17
|
|
16
18
|
This class implements a variant of the discrete Lehmann representation
|
@@ -32,38 +34,26 @@ class DiscreteLehmannRepresentation(abstract.AbstractBasis):
|
|
32
34
|
|
33
35
|
.. _DLR: https://doi.org/10.1103/PhysRevB.105.235115
|
34
36
|
"""
|
35
|
-
def __init__(self, basis: _basis.FiniteTempBasis, sampling_points=None):
|
36
|
-
if sampling_points is None:
|
37
|
-
sampling_points = basis.default_omega_sampling_points()
|
38
|
-
if not isinstance(basis.kernel, kernel.LogisticKernel):
|
39
|
-
raise ValueError("DLR supports only LogisticKernel")
|
40
37
|
|
38
|
+
def __init__(self, basis: AbstractBasis, poles=None):
|
39
|
+
status = ctypes.c_int()
|
40
|
+
if poles is None:
|
41
|
+
poles = basis_get_default_omega_sampling_points(basis._ptr)
|
41
42
|
self._basis = basis
|
42
|
-
self._poles =
|
43
|
-
self.
|
44
|
-
|
45
|
-
|
46
|
-
self._uhat = MatsubaraPoles(basis.statistics, basis.beta, self._poles)
|
47
|
-
|
48
|
-
# Fitting matrix from IR
|
49
|
-
F = -basis.s[:, None] * basis.v(self._poles)
|
50
|
-
|
51
|
-
# Now, here we *know* that F is ill-conditioned in very particular way:
|
52
|
-
# it is a product A * B * C, where B is well conditioned and A, C are
|
53
|
-
# scalings. This is handled with guaranteed relative accuracy by a
|
54
|
-
# Jacobi SVD, implied by the 'accurate' strategy.
|
55
|
-
uF, sF, vF = svd.compute(F, strategy='accurate')
|
56
|
-
self.matrix = sampling.DecomposedMatrix(F, svd_result=(uF, sF, vF.T))
|
43
|
+
self._poles = poles
|
44
|
+
self._ptr = _lib.spir_dlr_new_with_poles(basis._ptr, len(poles), poles.ctypes.data_as(ctypes.POINTER(ctypes.c_double)), status)
|
45
|
+
if status.value != COMPUTATION_SUCCESS:
|
46
|
+
raise RuntimeError(f"Failed to create DLR basis: {status.value}")
|
57
47
|
|
58
48
|
@property
|
59
|
-
def u(self): return self._u
|
49
|
+
def u(self): return self._basis._u
|
60
50
|
|
61
51
|
@property
|
62
|
-
def uhat(self): return self._uhat
|
52
|
+
def uhat(self): return self._basis._uhat
|
63
53
|
|
64
54
|
@property
|
65
55
|
def statistics(self):
|
66
|
-
return self.
|
56
|
+
return self._basis.statistics
|
67
57
|
|
68
58
|
@property
|
69
59
|
def sampling_points(self):
|
@@ -73,24 +63,24 @@ class DiscreteLehmannRepresentation(abstract.AbstractBasis):
|
|
73
63
|
def shape(self): return self.size,
|
74
64
|
|
75
65
|
@property
|
76
|
-
def size(self): return self._poles
|
66
|
+
def size(self): return len(self._poles)
|
77
67
|
|
78
68
|
@property
|
79
|
-
def basis(self) ->
|
69
|
+
def basis(self) -> AbstractBasis:
|
80
70
|
""" Underlying basis """
|
81
71
|
return self._basis
|
82
72
|
|
83
73
|
@property
|
84
74
|
def lambda_(self):
|
85
|
-
return self.
|
75
|
+
return self._basis.lambda_
|
86
76
|
|
87
77
|
@property
|
88
78
|
def beta(self):
|
89
|
-
return self.
|
79
|
+
return self._basis.beta
|
90
80
|
|
91
81
|
@property
|
92
82
|
def wmax(self):
|
93
|
-
return self.
|
83
|
+
return self._basis.wmax
|
94
84
|
|
95
85
|
@property
|
96
86
|
def significance(self):
|
@@ -98,71 +88,124 @@ class DiscreteLehmannRepresentation(abstract.AbstractBasis):
|
|
98
88
|
|
99
89
|
@property
|
100
90
|
def accuracy(self):
|
101
|
-
return self.
|
91
|
+
return self._basis.accuracy
|
102
92
|
|
103
93
|
def from_IR(self, gl: np.ndarray, axis=0) -> np.ndarray:
|
104
|
-
"""
|
105
|
-
|
94
|
+
"""From IR to DLR
|
95
|
+
|
96
|
+
Convert expansion coefficients from IR basis to DLR basis.
|
106
97
|
|
107
|
-
|
98
|
+
Parameters
|
99
|
+
----------
|
100
|
+
gl : array_like
|
108
101
|
Expansion coefficients in IR
|
102
|
+
axis : int, optional
|
103
|
+
Axis along which to convert
|
104
|
+
|
105
|
+
Returns
|
106
|
+
-------
|
107
|
+
array_like
|
108
|
+
Expansion coefficients in DLR
|
109
109
|
"""
|
110
|
-
|
110
|
+
if gl.shape[axis] != self.basis.size:
|
111
|
+
raise ValueError(f"Input array has wrong size along dimension {axis}")
|
112
|
+
|
113
|
+
output_dims = list(gl.shape)
|
114
|
+
output_dims[axis] = self.size
|
115
|
+
output = np.zeros(output_dims, dtype=gl.dtype)
|
116
|
+
|
117
|
+
ndim = len(gl.shape)
|
118
|
+
input_dims = np.asarray(gl.shape, dtype=np.int32)
|
119
|
+
target_dim = axis
|
120
|
+
order = SPIR_ORDER_ROW_MAJOR
|
121
|
+
|
122
|
+
if gl.dtype.kind == 'f':
|
123
|
+
ret = _lib.spir_ir2dlr_dd(
|
124
|
+
self._ptr,
|
125
|
+
order,
|
126
|
+
ndim,
|
127
|
+
input_dims.ctypes.data_as(ctypes.POINTER(ctypes.c_int32)),
|
128
|
+
target_dim,
|
129
|
+
gl.ctypes.data_as(ctypes.POINTER(ctypes.c_double)),
|
130
|
+
output.ctypes.data_as(ctypes.POINTER(ctypes.c_double)),
|
131
|
+
)
|
132
|
+
elif gl.dtype.kind == 'c':
|
133
|
+
ret = _lib.spir_ir2dlr_zz(
|
134
|
+
self._ptr,
|
135
|
+
order,
|
136
|
+
ndim,
|
137
|
+
input_dims.ctypes.data_as(ctypes.POINTER(ctypes.c_int32)),
|
138
|
+
target_dim,
|
139
|
+
# TODO: use complex data
|
140
|
+
gl.ctypes.data_as(ctypes.POINTER(ctypes.c_double)),
|
141
|
+
output.ctypes.data_as(ctypes.POINTER(ctypes.c_double)),
|
142
|
+
)
|
143
|
+
else:
|
144
|
+
raise ValueError(f"Unsupported dtype: {gl.dtype}")
|
145
|
+
if ret != COMPUTATION_SUCCESS:
|
146
|
+
raise RuntimeError(f"Failed to convert IR to DLR: {ret}")
|
147
|
+
return output
|
111
148
|
|
112
149
|
def to_IR(self, g_dlr: np.ndarray, axis=0) -> np.ndarray:
|
113
|
-
"""
|
114
|
-
|
150
|
+
"""From DLR to IR
|
151
|
+
|
152
|
+
Convert expansion coefficients from DLR basis to IR basis.
|
115
153
|
|
116
|
-
|
154
|
+
Parameters
|
155
|
+
----------
|
156
|
+
g_dlr : array_like
|
117
157
|
Expansion coefficients in DLR
|
158
|
+
axis : int, optional
|
159
|
+
Axis along which to convert
|
160
|
+
|
161
|
+
Returns
|
162
|
+
-------
|
163
|
+
array_like
|
164
|
+
Expansion coefficients in IR
|
118
165
|
"""
|
119
|
-
|
166
|
+
if g_dlr.shape[axis] != self.size:
|
167
|
+
raise ValueError(f"Input array has wrong size along dimension {axis}")
|
168
|
+
output_dims = np.asarray(g_dlr.shape, dtype=np.int32)
|
169
|
+
output_dims[axis] = self.basis.size
|
170
|
+
output = np.zeros(output_dims, dtype=g_dlr.dtype)
|
171
|
+
ndim = len(g_dlr.shape)
|
172
|
+
input_dims = np.asarray(g_dlr.shape, dtype=np.int32)
|
173
|
+
target_dim = axis
|
174
|
+
order = SPIR_ORDER_ROW_MAJOR
|
175
|
+
|
176
|
+
if g_dlr.dtype.kind == 'f':
|
177
|
+
ret = _lib.spir_dlr2ir_dd(
|
178
|
+
self._ptr,
|
179
|
+
order,
|
180
|
+
ndim,
|
181
|
+
input_dims.ctypes.data_as(ctypes.POINTER(ctypes.c_int)),
|
182
|
+
target_dim,
|
183
|
+
g_dlr.ctypes.data_as(ctypes.POINTER(ctypes.c_double)),
|
184
|
+
output.ctypes.data_as(ctypes.POINTER(ctypes.c_double)),
|
185
|
+
)
|
186
|
+
elif g_dlr.dtype.kind == 'c':
|
187
|
+
ret = _lib.spir_dlr2ir_zz(
|
188
|
+
self._ptr,
|
189
|
+
order,
|
190
|
+
ndim,
|
191
|
+
input_dims.ctypes.data_as(ctypes.POINTER(ctypes.c_int)),
|
192
|
+
target_dim,
|
193
|
+
# TODO: use complex data
|
194
|
+
g_dlr.ctypes.data_as(ctypes.POINTER(ctypes.c_double)),
|
195
|
+
output.ctypes.data_as(ctypes.POINTER(ctypes.c_double)),
|
196
|
+
)
|
197
|
+
else:
|
198
|
+
raise ValueError(f"Unsupported dtype: {g_dlr.dtype}")
|
199
|
+
if ret != COMPUTATION_SUCCESS:
|
200
|
+
raise RuntimeError(f"Failed to convert DLR to IR: {ret}")
|
201
|
+
return output
|
120
202
|
|
121
203
|
def default_tau_sampling_points(self):
|
122
|
-
return self.
|
204
|
+
return self._basis.default_tau_sampling_points()
|
123
205
|
|
124
206
|
def default_matsubara_sampling_points(self, **kwargs):
|
125
|
-
return self.
|
207
|
+
return self._basis.default_matsubara_sampling_points(**kwargs)
|
126
208
|
|
127
209
|
@property
|
128
210
|
def is_well_conditioned(self):
|
129
211
|
return False
|
130
|
-
|
131
|
-
|
132
|
-
class MatsubaraPoles:
|
133
|
-
def __init__(self, statistics: str, beta: float, poles: np.ndarray):
|
134
|
-
self._statistics = statistics
|
135
|
-
self._beta = beta
|
136
|
-
self._poles = np.array(poles)
|
137
|
-
|
138
|
-
@_util.ravel_argument(last_dim=True)
|
139
|
-
def __call__(self, n):
|
140
|
-
"""Evaluate basis functions at given frequency n"""
|
141
|
-
iv = 1j*n * np.pi/self._beta
|
142
|
-
if self._statistics == 'F':
|
143
|
-
return 1 /(iv[None, :] - self._poles[:, None])
|
144
|
-
else:
|
145
|
-
return np.tanh(0.5 * self._beta * self._poles)[:, None]\
|
146
|
-
/(iv[None, :] - self._poles[:, None])
|
147
|
-
|
148
|
-
|
149
|
-
class TauPoles:
|
150
|
-
def __init__(self, statistics: str, beta: float, poles: np.ndarray):
|
151
|
-
self._beta = beta
|
152
|
-
self._statistics = statistics
|
153
|
-
self._poles = np.array(poles)
|
154
|
-
self._wmax = np.abs(poles).max()
|
155
|
-
|
156
|
-
@_util.ravel_argument(last_dim=True)
|
157
|
-
def __call__(self, tau):
|
158
|
-
""" Evaluate basis functions at tau """
|
159
|
-
tau = np.asarray(tau)
|
160
|
-
if (tau < 0).any() or (tau > self._beta).any():
|
161
|
-
raise RuntimeError("tau must be in [0, beta]!")
|
162
|
-
|
163
|
-
x = 2 * tau/self._beta - 1
|
164
|
-
y = self._poles/self._wmax
|
165
|
-
lambda_ = self._beta * self._wmax
|
166
|
-
|
167
|
-
res = -kernel.LogisticKernel(lambda_)(x[:, None], y[None, :])
|
168
|
-
return res.T
|