sparse-ir 2.1.4__tar.gz → 2.1.6__tar.gz
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-2.1.4/src/sparse_ir.egg-info → sparse_ir-2.1.6}/PKG-INFO +32 -19
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/README.rst +30 -17
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/pyproject.toml +10 -2
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir/_util.py +117 -10
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir/abstract.py +62 -30
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir/augment.py +118 -78
- sparse_ir-2.1.6/src/sparse_ir/basis.py +484 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir/basis_set.py +15 -14
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir/dlr.py +89 -17
- sparse_ir-2.1.6/src/sparse_ir/kernel.py +151 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir/poly.py +196 -103
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir/sampling.py +137 -55
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir/sve.py +45 -23
- {sparse_ir-2.1.4 → sparse_ir-2.1.6/src/sparse_ir.egg-info}/PKG-INFO +32 -19
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir.egg-info/SOURCES.txt +4 -0
- sparse_ir-2.1.6/src/sparse_ir.egg-info/requires.txt +3 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_advanced_features.py +16 -7
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_augment.py +108 -47
- sparse_ir-2.1.6/tests/test_basis.py +189 -0
- sparse_ir-2.1.6/tests/test_boundary.py +423 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_core.py +35 -44
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_dlr.py +16 -11
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_ffi_boundary.py +38 -2
- sparse_ir-2.1.6/tests/test_integration.py +115 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_kernel.py +16 -14
- sparse_ir-2.1.6/tests/test_oracle.py +292 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_poly.py +18 -0
- sparse_ir-2.1.6/tests/test_public_surface.py +235 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_sampling.py +22 -9
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_sampling_advanced.py +7 -12
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_sve.py +14 -23
- sparse_ir-2.1.4/src/sparse_ir/basis.py +0 -326
- sparse_ir-2.1.4/src/sparse_ir/kernel.py +0 -108
- sparse_ir-2.1.4/src/sparse_ir.egg-info/requires.txt +0 -3
- sparse_ir-2.1.4/tests/test_basis.py +0 -150
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/LICENSE.txt +0 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/MANIFEST.in +0 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/setup.cfg +0 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir/__init__.py +0 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir/_gauss.py +0 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir.egg-info/dependency_links.txt +0 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/src/sparse_ir.egg-info/top_level.txt +0 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_basis_set.py +0 -0
- {sparse_ir-2.1.4 → sparse_ir-2.1.6}/tests/test_sve_advanced.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sparse-ir
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.6
|
|
4
4
|
Summary: Python bindings for the libsparseir library, providing efficient sparse intermediate representation for many-body physics calculations
|
|
5
5
|
Author: SpM-lab
|
|
6
6
|
License-Expression: MIT
|
|
@@ -20,7 +20,7 @@ Description-Content-Type: text/x-rst
|
|
|
20
20
|
License-File: LICENSE.txt
|
|
21
21
|
Requires-Dist: numpy
|
|
22
22
|
Requires-Dist: scipy
|
|
23
|
-
Requires-Dist: pylibsparseir<0.
|
|
23
|
+
Requires-Dist: pylibsparseir<0.13.0,>=0.8.3
|
|
24
24
|
Dynamic: license-file
|
|
25
25
|
|
|
26
26
|
sparse-ir - A library for the intermediate representation of propagators
|
|
@@ -45,7 +45,7 @@ Install via `conda <https://anaconda.org/spm-lab/sparse-ir>`_::
|
|
|
45
45
|
|
|
46
46
|
sparse-ir requires `numpy <https://numpy.org/>`_, `scipy <https://scipy.org/>`_,
|
|
47
47
|
and `pylibsparseir <https://pypi.org/project/pylibsparseir>`_ (a thin Python wrapper
|
|
48
|
-
for the
|
|
48
|
+
for the libsparseir C API from `sparse-ir-rs <https://github.com/SpM-lab/sparse-ir-rs>`_).
|
|
49
49
|
|
|
50
50
|
To manually install the current development version, you can use the following::
|
|
51
51
|
|
|
@@ -78,13 +78,21 @@ Lichtenstein formula, FLEX, ... - are presented.
|
|
|
78
78
|
Refer to the `API documentation`_ for more details on how to work
|
|
79
79
|
with the python library.
|
|
80
80
|
|
|
81
|
+
The symbols and conventions are defined on the `notation page`_, shared with
|
|
82
|
+
the tutorial and the Julia and C libraries. In short: G(τ) = -⟨T c(τ) c†(0)⟩
|
|
83
|
+
for both statistics; Matsubara frequencies iν are passed as the reduced
|
|
84
|
+
frequency n, an integer with ν = nπ/β (odd for fermions, even for bosons);
|
|
85
|
+
G(iν) = ∫₀^β dτ e^{iντ} G(τ); and G(τ) is evaluated for τ in [-β, β], where
|
|
86
|
+
``-0.0`` stands for 0⁻.
|
|
87
|
+
|
|
81
88
|
There is also a `Julia library`_ and (currently somewhat restricted)
|
|
82
89
|
`C library with Fortran bindings`_ available for the IR basis and sparse sampling.
|
|
83
90
|
|
|
84
|
-
.. _comprehensive tutorial: https://spm-lab.github.io/sparse-ir-tutorial
|
|
91
|
+
.. _comprehensive tutorial: https://spm-lab.github.io/sparse-ir-tutorial-v2/
|
|
85
92
|
.. _API documentation: https://sparse-ir.readthedocs.io
|
|
93
|
+
.. _notation page: https://spm-lab.github.io/sparse-ir-doc/src/notation.html
|
|
86
94
|
.. _Julia library: https://github.com/SpM-lab/SparseIR.jl
|
|
87
|
-
.. _C library with Fortran bindings: https://github.com/SpM-lab/
|
|
95
|
+
.. _C library with Fortran bindings: https://github.com/SpM-lab/sparse-ir-rs
|
|
88
96
|
|
|
89
97
|
Getting started
|
|
90
98
|
---------------
|
|
@@ -95,15 +103,16 @@ lines of Python code::
|
|
|
95
103
|
import sparse_ir, numpy as np
|
|
96
104
|
basis = sparse_ir.FiniteTempBasis('F', beta=10, wmax=8, eps=1e-6)
|
|
97
105
|
stau = sparse_ir.TauSampling(basis)
|
|
98
|
-
|
|
106
|
+
siv = sparse_ir.MatsubaraSampling(basis, positive_only=True)
|
|
99
107
|
|
|
100
108
|
# Solve the single impurity Anderson model coupled to a bath with a
|
|
101
|
-
# semicircular states with unit half bandwidth.
|
|
109
|
+
# semicircular density of states with unit half bandwidth.
|
|
102
110
|
U = 1.2
|
|
103
111
|
def rho0w(w):
|
|
104
112
|
return np.sqrt(1-w.clip(-1,1)**2) * 2/np.pi
|
|
105
113
|
|
|
106
|
-
# Compute the IR basis coefficients
|
|
114
|
+
# Compute the IR basis coefficients G0_l = -S_l rho0_l for the
|
|
115
|
+
# non-interacting propagator
|
|
107
116
|
rho0l = basis.v.overlap(rho0w)
|
|
108
117
|
G0l = -basis.s * rho0l
|
|
109
118
|
|
|
@@ -116,23 +125,27 @@ lines of Python code::
|
|
|
116
125
|
Gtau = stau.evaluate(Gl)
|
|
117
126
|
Sigmatau = U**2 * Gtau**3
|
|
118
127
|
Sigmal = stau.fit(Sigmatau)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
Gl =
|
|
128
|
+
Sigmaiv = siv.evaluate(Sigmal)
|
|
129
|
+
G0iv = siv.evaluate(G0l)
|
|
130
|
+
Giv = 1/(1/G0iv - Sigmaiv)
|
|
131
|
+
Gl = siv.fit(Giv)
|
|
123
132
|
|
|
124
133
|
You may want to start with reading up on the `intermediate representation`_.
|
|
125
134
|
It is tied to the analytic continuation of bosonic/fermionic spectral
|
|
126
135
|
functions from (real) frequencies to imaginary time, a transformation mediated
|
|
127
|
-
by
|
|
128
|
-
|
|
129
|
-
|
|
136
|
+
by the kernel K(τ, ω) = e^{-τω}/(1 + e^{-βω}). The basis depends on the
|
|
137
|
+
inverse temperature ``beta`` and on the frequency cutoff ``wmax``, which you
|
|
138
|
+
should choose so that the spectral function vanishes outside [-wmax, wmax].
|
|
139
|
+
In the dimensionless variables x = 2τ/β - 1 and y = ω/wmax, the kernel, and
|
|
140
|
+
hence its singular value expansion, depends on them only through the cutoff
|
|
141
|
+
Λ = ``beta * wmax`` (``basis.lambda_``).
|
|
130
142
|
|
|
131
143
|
One can now perform a `singular value expansion`_ on this kernel, which
|
|
132
|
-
generates two sets of orthonormal basis functions, one set
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
144
|
+
generates two sets of orthonormal basis functions, one set V_l(ω),
|
|
145
|
+
``basis.v[l](w)``, on the real-frequency axis, orthonormal on
|
|
146
|
+
[-wmax, wmax], and one set U_l(τ), ``basis.u[l](tau)``, for the same object in
|
|
147
|
+
imaginary (Euclidean) time, orthonormal on [0, beta], together with the
|
|
148
|
+
singular values S_l, ``basis.s[l]``, which couple the two sides.
|
|
136
149
|
|
|
137
150
|
By this construction, the imaginary time basis can be shown to be *optimal* in
|
|
138
151
|
terms of compactness.
|
|
@@ -20,7 +20,7 @@ Install via `conda <https://anaconda.org/spm-lab/sparse-ir>`_::
|
|
|
20
20
|
|
|
21
21
|
sparse-ir requires `numpy <https://numpy.org/>`_, `scipy <https://scipy.org/>`_,
|
|
22
22
|
and `pylibsparseir <https://pypi.org/project/pylibsparseir>`_ (a thin Python wrapper
|
|
23
|
-
for the
|
|
23
|
+
for the libsparseir C API from `sparse-ir-rs <https://github.com/SpM-lab/sparse-ir-rs>`_).
|
|
24
24
|
|
|
25
25
|
To manually install the current development version, you can use the following::
|
|
26
26
|
|
|
@@ -53,13 +53,21 @@ Lichtenstein formula, FLEX, ... - are presented.
|
|
|
53
53
|
Refer to the `API documentation`_ for more details on how to work
|
|
54
54
|
with the python library.
|
|
55
55
|
|
|
56
|
+
The symbols and conventions are defined on the `notation page`_, shared with
|
|
57
|
+
the tutorial and the Julia and C libraries. In short: G(τ) = -⟨T c(τ) c†(0)⟩
|
|
58
|
+
for both statistics; Matsubara frequencies iν are passed as the reduced
|
|
59
|
+
frequency n, an integer with ν = nπ/β (odd for fermions, even for bosons);
|
|
60
|
+
G(iν) = ∫₀^β dτ e^{iντ} G(τ); and G(τ) is evaluated for τ in [-β, β], where
|
|
61
|
+
``-0.0`` stands for 0⁻.
|
|
62
|
+
|
|
56
63
|
There is also a `Julia library`_ and (currently somewhat restricted)
|
|
57
64
|
`C library with Fortran bindings`_ available for the IR basis and sparse sampling.
|
|
58
65
|
|
|
59
|
-
.. _comprehensive tutorial: https://spm-lab.github.io/sparse-ir-tutorial
|
|
66
|
+
.. _comprehensive tutorial: https://spm-lab.github.io/sparse-ir-tutorial-v2/
|
|
60
67
|
.. _API documentation: https://sparse-ir.readthedocs.io
|
|
68
|
+
.. _notation page: https://spm-lab.github.io/sparse-ir-doc/src/notation.html
|
|
61
69
|
.. _Julia library: https://github.com/SpM-lab/SparseIR.jl
|
|
62
|
-
.. _C library with Fortran bindings: https://github.com/SpM-lab/
|
|
70
|
+
.. _C library with Fortran bindings: https://github.com/SpM-lab/sparse-ir-rs
|
|
63
71
|
|
|
64
72
|
Getting started
|
|
65
73
|
---------------
|
|
@@ -70,15 +78,16 @@ lines of Python code::
|
|
|
70
78
|
import sparse_ir, numpy as np
|
|
71
79
|
basis = sparse_ir.FiniteTempBasis('F', beta=10, wmax=8, eps=1e-6)
|
|
72
80
|
stau = sparse_ir.TauSampling(basis)
|
|
73
|
-
|
|
81
|
+
siv = sparse_ir.MatsubaraSampling(basis, positive_only=True)
|
|
74
82
|
|
|
75
83
|
# Solve the single impurity Anderson model coupled to a bath with a
|
|
76
|
-
# semicircular states with unit half bandwidth.
|
|
84
|
+
# semicircular density of states with unit half bandwidth.
|
|
77
85
|
U = 1.2
|
|
78
86
|
def rho0w(w):
|
|
79
87
|
return np.sqrt(1-w.clip(-1,1)**2) * 2/np.pi
|
|
80
88
|
|
|
81
|
-
# Compute the IR basis coefficients
|
|
89
|
+
# Compute the IR basis coefficients G0_l = -S_l rho0_l for the
|
|
90
|
+
# non-interacting propagator
|
|
82
91
|
rho0l = basis.v.overlap(rho0w)
|
|
83
92
|
G0l = -basis.s * rho0l
|
|
84
93
|
|
|
@@ -91,23 +100,27 @@ lines of Python code::
|
|
|
91
100
|
Gtau = stau.evaluate(Gl)
|
|
92
101
|
Sigmatau = U**2 * Gtau**3
|
|
93
102
|
Sigmal = stau.fit(Sigmatau)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Gl =
|
|
103
|
+
Sigmaiv = siv.evaluate(Sigmal)
|
|
104
|
+
G0iv = siv.evaluate(G0l)
|
|
105
|
+
Giv = 1/(1/G0iv - Sigmaiv)
|
|
106
|
+
Gl = siv.fit(Giv)
|
|
98
107
|
|
|
99
108
|
You may want to start with reading up on the `intermediate representation`_.
|
|
100
109
|
It is tied to the analytic continuation of bosonic/fermionic spectral
|
|
101
110
|
functions from (real) frequencies to imaginary time, a transformation mediated
|
|
102
|
-
by
|
|
103
|
-
|
|
104
|
-
|
|
111
|
+
by the kernel K(τ, ω) = e^{-τω}/(1 + e^{-βω}). The basis depends on the
|
|
112
|
+
inverse temperature ``beta`` and on the frequency cutoff ``wmax``, which you
|
|
113
|
+
should choose so that the spectral function vanishes outside [-wmax, wmax].
|
|
114
|
+
In the dimensionless variables x = 2τ/β - 1 and y = ω/wmax, the kernel, and
|
|
115
|
+
hence its singular value expansion, depends on them only through the cutoff
|
|
116
|
+
Λ = ``beta * wmax`` (``basis.lambda_``).
|
|
105
117
|
|
|
106
118
|
One can now perform a `singular value expansion`_ on this kernel, which
|
|
107
|
-
generates two sets of orthonormal basis functions, one set
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
119
|
+
generates two sets of orthonormal basis functions, one set V_l(ω),
|
|
120
|
+
``basis.v[l](w)``, on the real-frequency axis, orthonormal on
|
|
121
|
+
[-wmax, wmax], and one set U_l(τ), ``basis.u[l](tau)``, for the same object in
|
|
122
|
+
imaginary (Euclidean) time, orthonormal on [0, beta], together with the
|
|
123
|
+
singular values S_l, ``basis.s[l]``, which couple the two sides.
|
|
111
124
|
|
|
112
125
|
By this construction, the imaginary time basis can be shown to be *optimal* in
|
|
113
126
|
terms of compactness.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sparse-ir"
|
|
3
|
-
version = "2.1.
|
|
3
|
+
version = "2.1.6"
|
|
4
4
|
description = "Python bindings for the libsparseir library, providing efficient sparse intermediate representation for many-body physics calculations"
|
|
5
5
|
readme = "README.rst"
|
|
6
6
|
requires-python = ">=3.10"
|
|
7
7
|
dependencies = [
|
|
8
8
|
"numpy",
|
|
9
9
|
"scipy",
|
|
10
|
-
"pylibsparseir>=0.8.3,<0.
|
|
10
|
+
"pylibsparseir>=0.8.3,<0.13.0",
|
|
11
11
|
]
|
|
12
12
|
authors = [
|
|
13
13
|
{name = "SpM-lab"}
|
|
@@ -56,6 +56,14 @@ doc = [
|
|
|
56
56
|
|
|
57
57
|
[tool.pytest.ini_options]
|
|
58
58
|
testpaths = ["tests"]
|
|
59
|
+
# RegularizedBoseKernel is deprecated but still tested; test_kernel.py asserts
|
|
60
|
+
# the warning itself (pytest.warns records it regardless of this filter).
|
|
61
|
+
# An exception in a finalizer (__del__) must fail the suite, not be reported
|
|
62
|
+
# as a warning (SpM-lab/sparse-ir-rs#282).
|
|
63
|
+
filterwarnings = [
|
|
64
|
+
"ignore:RegularizedBoseKernel is deprecated:DeprecationWarning",
|
|
65
|
+
"error::pytest.PytestUnraisableExceptionWarning",
|
|
66
|
+
]
|
|
59
67
|
python_files = ["test_*.py", "*_tests.py"]
|
|
60
68
|
python_classes = ["Test*"]
|
|
61
69
|
python_functions = ["test_*"]
|
|
@@ -1,9 +1,41 @@
|
|
|
1
1
|
# Copyright (C) 2020-2025 Satoshi Terasaki, Markus Wallerberger, Hiroshi Shinaoka, and others
|
|
2
2
|
# SPDX-License-Identifier: MIT
|
|
3
3
|
import functools
|
|
4
|
+
import inspect
|
|
4
5
|
import numpy as np
|
|
5
6
|
|
|
6
7
|
|
|
8
|
+
def release_handle(handle, release):
|
|
9
|
+
"""Release a C handle obtained from pylibsparseir or its ``_lib``.
|
|
10
|
+
|
|
11
|
+
pylibsparseir >= 0.10 returns handles that own their C object and are
|
|
12
|
+
released with ``close()``; its raw ``_lib.spir_*_release`` entry points
|
|
13
|
+
refuse them (SpM-lab/sparse-ir-rs#282). Earlier releases, and direct
|
|
14
|
+
``_lib`` calls in any release, return raw pointers that must be passed to
|
|
15
|
+
``release``.
|
|
16
|
+
"""
|
|
17
|
+
close = getattr(handle, "close", None)
|
|
18
|
+
if close is not None:
|
|
19
|
+
close()
|
|
20
|
+
else:
|
|
21
|
+
release(handle)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def has_basis_size_argument(fn):
|
|
25
|
+
"""True if the pylibsparseir function ``fn`` takes ``basis_size``.
|
|
26
|
+
|
|
27
|
+
pylibsparseir >= 0.10 changed ``basis_get_default_matsus_ext`` from
|
|
28
|
+
``(basis, positive_only, points)`` to
|
|
29
|
+
``(basis, basis_size, positive_only, fence=False)``, returning the points
|
|
30
|
+
(SpM-lab/sparse-ir-rs#274). The signature is checked rather than the
|
|
31
|
+
version, since development builds may report an older version.
|
|
32
|
+
"""
|
|
33
|
+
try:
|
|
34
|
+
return "basis_size" in inspect.signature(fn).parameters
|
|
35
|
+
except (TypeError, ValueError):
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
|
|
7
39
|
def ravel_argument(last_dim=False):
|
|
8
40
|
"""Wrap function operating on 1-D numpy array to allow arbitrary shapes.
|
|
9
41
|
|
|
@@ -46,10 +78,12 @@ _REAL_KINDS = "biuf"
|
|
|
46
78
|
def check_reduced_matsubara(n, zeta=None):
|
|
47
79
|
"""Checks that ``n`` is a reduced Matsubara frequency.
|
|
48
80
|
|
|
49
|
-
Check that the argument is a reduced Matsubara frequency, which is
|
|
50
|
-
integer obtained by scaling the
|
|
81
|
+
Check that the argument is a reduced Matsubara frequency, which is the
|
|
82
|
+
integer ``n`` obtained by scaling the frequency ``nu`` as follows::
|
|
83
|
+
|
|
84
|
+
beta / np.pi * nu == n == 2 * m + zeta
|
|
51
85
|
|
|
52
|
-
|
|
86
|
+
where ``m`` is the ordinary Matsubara index.
|
|
53
87
|
|
|
54
88
|
Note that this means that instead of a fermionic frequency (``zeta == 1``),
|
|
55
89
|
we expect an odd integer, while for a bosonic frequency (``zeta == 0``),
|
|
@@ -74,6 +108,11 @@ def check_reduced_matsubara(n, zeta=None):
|
|
|
74
108
|
raise ValueError(
|
|
75
109
|
"reduced Matsubara frequency must be finite, got "
|
|
76
110
|
f"{nfloat[~np.isfinite(nfloat)][0]!r}")
|
|
111
|
+
beyond = np.abs(nfloat) >= 2.0**63
|
|
112
|
+
if beyond.any():
|
|
113
|
+
raise ValueError(
|
|
114
|
+
"reduced Matsubara frequency is out of the int64 range, got "
|
|
115
|
+
f"{np.atleast_1d(nfloat)[np.atleast_1d(beyond)][0]!r}")
|
|
77
116
|
n = np.rint(nfloat).astype(np.int64)
|
|
78
117
|
bad = n != nfloat
|
|
79
118
|
if bad.any():
|
|
@@ -142,11 +181,52 @@ def as_boundary_complex(a, name="array", check_finite=True):
|
|
|
142
181
|
return out
|
|
143
182
|
|
|
144
183
|
|
|
184
|
+
def check_domain(x, xmin, xmax, name="evaluation points"):
|
|
185
|
+
"""Check that every element of ``x`` is real, finite and in ``[xmin, xmax]``.
|
|
186
|
+
|
|
187
|
+
Returns ``x`` unchanged. Called before evaluation points are handed to
|
|
188
|
+
the C library, which would otherwise panic on an out-of-domain point
|
|
189
|
+
(SpM-lab/sparse-ir-rs#266) and report an internal error.
|
|
190
|
+
|
|
191
|
+
Raises:
|
|
192
|
+
TypeError: if ``x`` is complex or of a non-numeric element type.
|
|
193
|
+
ValueError: naming the first offending value otherwise.
|
|
194
|
+
"""
|
|
195
|
+
arr = np.asarray(x)
|
|
196
|
+
if arr.dtype.kind == 'c':
|
|
197
|
+
raise TypeError(f"{name} must be real-valued, got dtype {arr.dtype}")
|
|
198
|
+
if arr.dtype.kind not in _REAL_KINDS:
|
|
199
|
+
raise TypeError(f"{name} has unsupported dtype {arr.dtype}")
|
|
200
|
+
xf = np.asarray(arr, dtype=np.float64)
|
|
201
|
+
bad = ~np.isfinite(xf) | (xf < xmin) | (xf > xmax)
|
|
202
|
+
if bad.any():
|
|
203
|
+
offending = np.atleast_1d(xf)[np.atleast_1d(bad)][0]
|
|
204
|
+
raise ValueError(f"{name} must be finite and lie in [{xmin}, {xmax}], "
|
|
205
|
+
f"got {offending!r}")
|
|
206
|
+
return x
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def check_unique(points, name="sampling_points"):
|
|
210
|
+
"""Raise ValueError if the one-dimensional ``points`` contain a duplicate.
|
|
211
|
+
|
|
212
|
+
Duplicated sampling points make the sampling matrix rank-deficient, which
|
|
213
|
+
the C library accepts silently.
|
|
214
|
+
"""
|
|
215
|
+
arr = np.asarray(points)
|
|
216
|
+
values, counts = np.unique(arr, return_counts=True)
|
|
217
|
+
if (counts > 1).any():
|
|
218
|
+
dup = values[counts > 1][0]
|
|
219
|
+
first, second = np.flatnonzero(arr == dup)[:2]
|
|
220
|
+
raise ValueError(f"{name} contains the duplicate value {dup!r} at "
|
|
221
|
+
f"indices {first} and {second}; sampling points must "
|
|
222
|
+
"be pairwise distinct")
|
|
223
|
+
|
|
224
|
+
|
|
145
225
|
def as_boundary_matsubara(n, name="Matsubara indices", zeta=None):
|
|
146
|
-
"""Normalize reduced Matsubara
|
|
226
|
+
"""Normalize reduced Matsubara frequencies into a C-contiguous ``int64`` array.
|
|
147
227
|
|
|
148
228
|
Validates integrality (and, if ``zeta`` is given, parity) *before* the
|
|
149
|
-
conversion, so a non-integral
|
|
229
|
+
conversion, so a non-integral value raises instead of being truncated.
|
|
150
230
|
"""
|
|
151
231
|
checked = check_reduced_matsubara(n, zeta=zeta)
|
|
152
232
|
return np.ascontiguousarray(checked, dtype=np.int64)
|
|
@@ -242,11 +322,14 @@ def normalize_tau(statistics, tau, beta):
|
|
|
242
322
|
Raises:
|
|
243
323
|
ValueError: If tau is outside [-β, β] or statistics is invalid.
|
|
244
324
|
|
|
245
|
-
Special cases:
|
|
246
|
-
-
|
|
247
|
-
|
|
248
|
-
-
|
|
249
|
-
|
|
325
|
+
Special cases, with (-1)^ζ = -1 for fermions and +1 for bosons:
|
|
326
|
+
- For τ = +0.0 and τ in (0, β]: returns (τ, +1); +0.0 is read as 0⁺
|
|
327
|
+
and β as β⁻
|
|
328
|
+
- Negative zero (τ = -0.0) is read as 0⁻: returns (β, (-1)^ζ), since
|
|
329
|
+
f(0⁻) = (-1)^ζ f(β⁻)
|
|
330
|
+
- For τ in [-β, 0): returns (τ + β, (-1)^ζ); in particular -β, read
|
|
331
|
+
as (-β)⁺, gives (0, (-1)^ζ)
|
|
332
|
+
|
|
250
333
|
.. versionadded:: 1.2
|
|
251
334
|
"""
|
|
252
335
|
tau = np.asarray(tau, dtype=np.float64)
|
|
@@ -296,3 +379,27 @@ def check_svd_result(svd_result, matrix_shape=None):
|
|
|
296
379
|
raise ValueError(f"shape mismatch between SVD ({m_u}, {n_v}) "
|
|
297
380
|
f"and matrix ({m}, {n})")
|
|
298
381
|
return u, s, vH
|
|
382
|
+
|
|
383
|
+
def slice_to_size(index, size):
|
|
384
|
+
"""Return the number of basis functions selected by ``index``.
|
|
385
|
+
|
|
386
|
+
Only ``basis[:stop]``-style truncation is supported, mirroring
|
|
387
|
+
:py:meth:`FiniteTempBasis.__getitem__`.
|
|
388
|
+
"""
|
|
389
|
+
if not isinstance(index, slice):
|
|
390
|
+
raise TypeError(
|
|
391
|
+
f"only slice truncation is supported, got {index!r}")
|
|
392
|
+
if index.start not in (None, 0):
|
|
393
|
+
raise ValueError(
|
|
394
|
+
f"basis truncation must start at 0, got {index.start!r}")
|
|
395
|
+
if index.step not in (None, 1):
|
|
396
|
+
raise ValueError(
|
|
397
|
+
f"basis truncation must have unit step, got {index.step!r}")
|
|
398
|
+
if index.stop is None:
|
|
399
|
+
return size
|
|
400
|
+
stop = int(index.stop)
|
|
401
|
+
if not 0 < stop <= size:
|
|
402
|
+
raise IndexError(
|
|
403
|
+
f"truncation to {stop} functions is out of range for a basis of "
|
|
404
|
+
f"size {size}")
|
|
405
|
+
return stop
|
|
@@ -9,7 +9,12 @@ This module provides the abstract interface that all basis types should implemen
|
|
|
9
9
|
from abc import ABC, abstractmethod
|
|
10
10
|
|
|
11
11
|
class AbstractKernel(ABC):
|
|
12
|
-
"""Abstract base class for kernels.
|
|
12
|
+
"""Abstract base class for kernels.
|
|
13
|
+
|
|
14
|
+
It defines no interface of its own: the supported kernels are
|
|
15
|
+
:class:`~sparse_ir.LogisticKernel` and the deprecated
|
|
16
|
+
:class:`~sparse_ir.RegularizedBoseKernel`.
|
|
17
|
+
"""
|
|
13
18
|
pass
|
|
14
19
|
|
|
15
20
|
class AbstractBasis(ABC):
|
|
@@ -18,20 +23,34 @@ class AbstractBasis(ABC):
|
|
|
18
23
|
This class stores a set of basis functions. We can then expand a two-point
|
|
19
24
|
propagator G(τ), where τ is imaginary time:
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
.. math::
|
|
27
|
+
|
|
28
|
+
G(\tau) \approx \sum_{l=0}^{L-1} G_l U_l(\tau),
|
|
29
|
+
|
|
30
|
+
where :math:`U_l` is the l-th basis function, stored in :py:attr:`u`, and
|
|
31
|
+
the :math:`G_l` are the expansion coefficients. Similarly, the Fourier
|
|
32
|
+
transform G(iν) at the Matsubara frequency ν = nπ/β, where n is a reduced
|
|
33
|
+
Matsubara frequency, can be expanded as follows:
|
|
22
34
|
|
|
23
|
-
|
|
24
|
-
expansion coefficients. Similarly, the Fourier transform Ĝ(n), where n
|
|
25
|
-
is a reduced Matsubara frequency, can be expanded as follows:
|
|
35
|
+
.. math::
|
|
26
36
|
|
|
27
|
-
|
|
37
|
+
G(\mathrm{i}\nu) \approx \sum_{l=0}^{L-1} G_l \hat U_l(\mathrm{i}\nu),
|
|
28
38
|
|
|
29
|
-
where
|
|
30
|
-
in uhat
|
|
39
|
+
where :math:`\hat U_l` is the Fourier transform of the l-th basis
|
|
40
|
+
function, stored in :py:attr:`uhat`. The Fourier transform and its
|
|
41
|
+
inverse are
|
|
31
42
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
.. math::
|
|
44
|
+
|
|
45
|
+
G(\mathrm{i}\nu) = \int_0^\beta d\tau\, e^{\mathrm{i}\nu\tau} G(\tau),
|
|
46
|
+
\qquad
|
|
47
|
+
G(\tau) = \frac{1}{\beta} \sum_\nu e^{-\mathrm{i}\nu\tau}
|
|
48
|
+
G(\mathrm{i}\nu).
|
|
49
|
+
|
|
50
|
+
Assuming that ``basis`` is an instance of some abstract basis, ``gl`` is
|
|
51
|
+
a vector of expansion coefficients G_l, ``tau`` is some imaginary time and
|
|
52
|
+
``n`` some reduced frequency, we can write this in the library as
|
|
53
|
+
follows::
|
|
35
54
|
|
|
36
55
|
G_tau = basis.u(tau).T @ gl
|
|
37
56
|
G_n = basis.uhat(n).T @ gl
|
|
@@ -42,9 +61,13 @@ class AbstractBasis(ABC):
|
|
|
42
61
|
def u(self):
|
|
43
62
|
r"""Basis functions on the imaginary time axis.
|
|
44
63
|
|
|
45
|
-
Set of
|
|
46
|
-
is a real number
|
|
47
|
-
|
|
64
|
+
Set of basis functions :math:`U_l(\tau)` on the imaginary time (tau)
|
|
65
|
+
axis, where tau is a real number in [-beta, beta]. Negative times
|
|
66
|
+
follow :math:`U_l(\tau) = (-1)^\zeta U_l(\tau + \beta)`, where
|
|
67
|
+
:math:`(-1)^\zeta` is -1 for fermions and +1 for bosons, and the
|
|
68
|
+
endpoints are one-sided limits: ``+0.0`` is 0⁺, ``beta`` is β⁻,
|
|
69
|
+
``-0.0`` is 0⁻ and ``-beta`` is (-β)⁺. To get the l-th basis function
|
|
70
|
+
at imaginary time tau of some basis, use::
|
|
48
71
|
|
|
49
72
|
ultau = basis.u[l](tau) # l-th basis function at time tau
|
|
50
73
|
|
|
@@ -55,24 +78,30 @@ class AbstractBasis(ABC):
|
|
|
55
78
|
@property
|
|
56
79
|
@abstractmethod
|
|
57
80
|
def uhat(self):
|
|
58
|
-
r"""Basis functions on the reduced Matsubara frequency
|
|
81
|
+
r"""Basis functions on the reduced Matsubara frequency axis.
|
|
82
|
+
|
|
83
|
+
Set of basis functions :math:`\hat U_l(\mathrm{i}\nu)` at the
|
|
84
|
+
Matsubara frequencies ν = nπ/β, where the reduced frequency n is an
|
|
85
|
+
integer. These are related to u by the following Fourier transform:
|
|
59
86
|
|
|
60
|
-
|
|
61
|
-
wn is an integer. These are related to u by the following Fourier transform:
|
|
87
|
+
.. math::
|
|
62
88
|
|
|
63
|
-
|
|
89
|
+
\hat U_l(\mathrm{i}\nu) = \int_0^\beta d\tau\,
|
|
90
|
+
e^{\mathrm{i}\nu\tau} U_l(\tau).
|
|
64
91
|
|
|
65
|
-
To get the l-th basis function at some reduced frequency
|
|
66
|
-
some basis, use
|
|
92
|
+
To get the l-th basis function at some reduced frequency n of
|
|
93
|
+
some basis, use::
|
|
67
94
|
|
|
68
|
-
uln = basis.uhat[l](
|
|
95
|
+
uln = basis.uhat[l](n) # l-th basis function at iν, ν = nπ/β
|
|
69
96
|
|
|
70
97
|
Note:
|
|
71
98
|
Instead of the value of the Matsubara frequency, these functions
|
|
72
|
-
expect
|
|
73
|
-
For example, the first few positive fermionic frequencies
|
|
74
|
-
be specified as [1, 3, 5, 7], and the first bosonic
|
|
75
|
-
are [0, 2, 4, 6]
|
|
99
|
+
expect the reduced frequency n = βν/π, the integer prefactor of
|
|
100
|
+
π/β. For example, the first few positive fermionic frequencies
|
|
101
|
+
would be specified as [1, 3, 5, 7], and the first bosonic
|
|
102
|
+
frequencies are [0, 2, 4, 6]: n is odd for fermions and even for
|
|
103
|
+
bosons. It is not the ordinary Matsubara index m, which gives
|
|
104
|
+
n = 2m + ζ (ζ = 1 for fermions, 0 for bosons).
|
|
76
105
|
"""
|
|
77
106
|
raise NotImplementedError()
|
|
78
107
|
|
|
@@ -117,7 +146,11 @@ class AbstractBasis(ABC):
|
|
|
117
146
|
"""Accuracy of the basis.
|
|
118
147
|
|
|
119
148
|
Upper bound to the relative error of representing a propagator with
|
|
120
|
-
the given number of basis functions (number between 0 and 1).
|
|
149
|
+
the given number of basis functions (number between 0 and 1). This
|
|
150
|
+
default returns the smallest significance, ``significance[-1]``;
|
|
151
|
+
:class:`~sparse_ir.FiniteTempBasis` overrides it with S_L/S_0 of the
|
|
152
|
+
first discarded singular value, and the DLR and augmented bases
|
|
153
|
+
return the accuracy of their underlying basis.
|
|
121
154
|
"""
|
|
122
155
|
return self.significance[-1]
|
|
123
156
|
|
|
@@ -161,10 +194,9 @@ class AbstractBasis(ABC):
|
|
|
161
194
|
npoints : int, optional
|
|
162
195
|
Minimum number of sampling points to return.
|
|
163
196
|
positive_only : bool
|
|
164
|
-
Only return non-negative frequencies. This is useful if
|
|
165
|
-
object to be fitted is symmetric in Matsubara frequency,
|
|
166
|
-
|
|
167
|
-
imaginary time.
|
|
197
|
+
Only return non-negative frequencies, n >= 0. This is useful if
|
|
198
|
+
the object to be fitted is symmetric in Matsubara frequency,
|
|
199
|
+
G(-iν) = G(iν)*, or, equivalently, real in imaginary time.
|
|
168
200
|
"""
|
|
169
201
|
raise NotImplementedError()
|
|
170
202
|
|