sparse-ir 2.1.0__tar.gz → 2.1.2__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.
Files changed (38) hide show
  1. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/MANIFEST.in +2 -2
  2. sparse_ir-2.1.2/PKG-INFO +249 -0
  3. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/pyproject.toml +6 -4
  4. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/basis.py +80 -17
  5. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/sampling.py +1 -1
  6. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/sve.py +71 -9
  7. sparse_ir-2.1.2/src/sparse_ir.egg-info/PKG-INFO +249 -0
  8. sparse_ir-2.1.2/src/sparse_ir.egg-info/requires.txt +3 -0
  9. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_sve.py +27 -6
  10. sparse_ir-2.1.0/PKG-INFO +0 -22
  11. sparse_ir-2.1.0/src/sparse_ir.egg-info/PKG-INFO +0 -22
  12. sparse_ir-2.1.0/src/sparse_ir.egg-info/requires.txt +0 -3
  13. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/LICENSE.txt +0 -0
  14. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/README.rst +0 -0
  15. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/setup.cfg +0 -0
  16. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/__init__.py +0 -0
  17. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/_gauss.py +0 -0
  18. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/_util.py +0 -0
  19. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/abstract.py +0 -0
  20. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/augment.py +0 -0
  21. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/basis_set.py +0 -0
  22. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/dlr.py +0 -0
  23. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/kernel.py +0 -0
  24. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir/poly.py +0 -0
  25. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir.egg-info/SOURCES.txt +0 -0
  26. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir.egg-info/dependency_links.txt +0 -0
  27. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/src/sparse_ir.egg-info/top_level.txt +0 -0
  28. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_advanced_features.py +0 -0
  29. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_augment.py +0 -0
  30. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_basis.py +0 -0
  31. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_basis_set.py +0 -0
  32. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_core.py +0 -0
  33. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_dlr.py +0 -0
  34. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_kernel.py +0 -0
  35. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_poly.py +0 -0
  36. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_sampling.py +0 -0
  37. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_sampling_advanced.py +0 -0
  38. {sparse_ir-2.1.0 → sparse_ir-2.1.2}/tests/test_sve_advanced.py +0 -0
@@ -1,4 +1,4 @@
1
- include README.md
1
+ include README.rst
2
2
  recursive-include src/sparse_ir *.py
3
3
  global-exclude *.pyc
4
- global-exclude __pycache__
4
+ global-exclude __pycache__
@@ -0,0 +1,249 @@
1
+ Metadata-Version: 2.4
2
+ Name: sparse-ir
3
+ Version: 2.1.2
4
+ Summary: Python bindings for the libsparseir library, providing efficient sparse intermediate representation for many-body physics calculations
5
+ Author: SpM-lab
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/SpM-lab/sparse-r
8
+ Project-URL: Repository, https://github.com/SpM-lab/sparse-r
9
+ Project-URL: Bug Tracker, https://github.com/SpM-lab/sparse-r/issues
10
+ Keywords: physics,many-body,green-functions,sparse-ir
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Topic :: Scientific/Engineering :: Physics
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/x-rst
20
+ License-File: LICENSE.txt
21
+ Requires-Dist: numpy
22
+ Requires-Dist: scipy
23
+ Requires-Dist: pylibsparseir<0.10.0,>=0.8.3
24
+ Dynamic: license-file
25
+
26
+ sparse-ir - A library for the intermediate representation of propagators
27
+ ========================================================================
28
+ This library provides routines for constructing and working with the
29
+ intermediate representation of correlation functions. It provides:
30
+
31
+ - on-the-fly computation of basis functions for arbitrary cutoff Λ
32
+ - basis functions and singular values are accurate to full precision
33
+ - routines for sparse sampling
34
+
35
+
36
+ Installation
37
+ ------------
38
+ Install via `pip <https://pypi.org/project/sparse-ir>`_::
39
+
40
+ pip install sparse-ir
41
+
42
+ Install via `conda <https://anaconda.org/spm-lab/sparse-ir>`_::
43
+
44
+ conda install -c spm-lab sparse-ir
45
+
46
+ sparse-ir requires `numpy <https://numpy.org/>`_, `scipy <https://scipy.org/>`_,
47
+ and `pylibsparseir <https://pypi.org/project/pylibsparseir>`_ (a thin Python wrapper
48
+ for the `libsparseir <https://github.com/SpM-lab/libsparseir>`_ C API).
49
+
50
+ To manually install the current development version, you can use the following::
51
+
52
+ # Only recommended for developers - no automatic updates!
53
+ git clone https://github.com/SpM-lab/sparse-ir
54
+ cd sparse-ir
55
+ uv sync
56
+
57
+ Note: `uv` is a fast Python package manager. If you don't have it installed,
58
+ you can install it with ``pip install uv`` or use ``pip install -e .`` instead.
59
+
60
+ Building documentation
61
+ ----------------------
62
+ To build the documentation locally, first install the development dependencies::
63
+
64
+ uv sync --group doc
65
+
66
+ Then build the documentation::
67
+
68
+ uv run sphinx-build -M html doc _build/html
69
+
70
+ The documentation will be available in ``_build/html/html/index.html``.
71
+
72
+ Documentation and tutorial
73
+ --------------------------
74
+ Check out our `comprehensive tutorial`_, where we self-contained
75
+ notebooks for several many-body methods - GF(2), GW, Eliashberg equations,
76
+ Lichtenstein formula, FLEX, ... - are presented.
77
+
78
+ Refer to the `API documentation`_ for more details on how to work
79
+ with the python library.
80
+
81
+ There is also a `Julia library`_ and (currently somewhat restricted)
82
+ `C library with Fortran bindings`_ available for the IR basis and sparse sampling.
83
+
84
+ .. _comprehensive tutorial: https://spm-lab.github.io/sparse-ir-tutorial
85
+ .. _API documentation: https://sparse-ir.readthedocs.io
86
+ .. _Julia library: https://github.com/SpM-lab/SparseIR.jl
87
+ .. _C library with Fortran bindings: https://github.com/SpM-lab/libsparseir
88
+
89
+ Getting started
90
+ ---------------
91
+ Here is a full second-order perturbation theory solver (GF(2)) in a few
92
+ lines of Python code::
93
+
94
+ # Construct the IR basis and sparse sampling for fermionic propagators
95
+ import sparse_ir, numpy as np
96
+ basis = sparse_ir.FiniteTempBasis('F', beta=10, wmax=8, eps=1e-6)
97
+ stau = sparse_ir.TauSampling(basis)
98
+ siw = sparse_ir.MatsubaraSampling(basis, positive_only=True)
99
+
100
+ # Solve the single impurity Anderson model coupled to a bath with a
101
+ # semicircular states with unit half bandwidth.
102
+ U = 1.2
103
+ def rho0w(w):
104
+ return np.sqrt(1-w.clip(-1,1)**2) * 2/np.pi
105
+
106
+ # Compute the IR basis coefficients for the non-interacting propagator
107
+ rho0l = basis.v.overlap(rho0w)
108
+ G0l = -basis.s * rho0l
109
+
110
+ # Self-consistency loop: alternate between second-order expression for the
111
+ # self-energy and the Dyson equation until convergence.
112
+ Gl = G0l
113
+ Gl_prev = 0
114
+ while np.linalg.norm(Gl - Gl_prev) > 1e-6:
115
+ Gl_prev = Gl
116
+ Gtau = stau.evaluate(Gl)
117
+ Sigmatau = U**2 * Gtau**3
118
+ Sigmal = stau.fit(Sigmatau)
119
+ Sigmaiw = siw.evaluate(Sigmal)
120
+ G0iw = siw.evaluate(G0l)
121
+ Giw = 1/(1/G0iw - Sigmaiw)
122
+ Gl = siw.fit(Giw)
123
+
124
+ You may want to start with reading up on the `intermediate representation`_.
125
+ It is tied to the analytic continuation of bosonic/fermionic spectral
126
+ functions from (real) frequencies to imaginary time, a transformation mediated
127
+ by a kernel ``K``. The kernel depends on a cutoff, which you should choose to
128
+ be ``lambda_ >= beta * W``, where ``beta`` is the inverse temperature and ``W``
129
+ is the bandwidth.
130
+
131
+ One can now perform a `singular value expansion`_ on this kernel, which
132
+ generates two sets of orthonormal basis functions, one set ``v[l](w)`` for
133
+ real frequency side ``w``, and one set ``u[l](tau)`` for the same obejct in
134
+ imaginary (Euclidean) time ``tau``, together with a "coupling" strength
135
+ ``s[l]`` between the two sides.
136
+
137
+ By this construction, the imaginary time basis can be shown to be *optimal* in
138
+ terms of compactness.
139
+
140
+ .. _intermediate representation: https://arxiv.org/abs/2106.12685
141
+ .. _singular value expansion: https://w.wiki/3poQ
142
+
143
+ License and citation
144
+ --------------------
145
+ This software is released under the MIT License. See LICENSE.txt for details.
146
+
147
+ If you find the intermediate representation, sparse sampling, or this software
148
+ useful in your research, please consider citing the following papers:
149
+
150
+ - Hiroshi Shinaoka et al., `Phys. Rev. B 96, 035147`_ (2017)
151
+ - Jia Li et al., `Phys. Rev. B 101, 035144`_ (2020)
152
+ - Markus Wallerberger et al., `SoftwareX 21, 101266`_ (2023)
153
+
154
+ If you are discussing sparse sampling in your research specifically, please
155
+ also consider citing an independently discovered, closely related approach, the
156
+ MINIMAX isometry method (Merzuk Kaltak and Georg Kresse,
157
+ `Phys. Rev. B 101, 205145`_, 2020).
158
+
159
+ .. _Phys. Rev. B 96, 035147: https://doi.org/10.1103/PhysRevB.96.035147
160
+ .. _Phys. Rev. B 101, 035144: https://doi.org/10.1103/PhysRevB.101.035144
161
+ .. _SoftwareX 21, 101266: https://doi.org/10.1016/j.softx.2022.101266
162
+ .. _Phys. Rev. B 101, 205145: https://doi.org/10.1103/PhysRevB.101.205145
163
+
164
+ Development
165
+ -----------
166
+
167
+ Updating pylibsparseir Dependency
168
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
169
+ When updating the ``pylibsparseir`` dependency version, you must update it in
170
+ **both** ``pyproject.toml`` and ``.conda/meta.yaml`` to maintain consistency:
171
+
172
+ 1. **Update pyproject.toml**::
173
+
174
+ # Edit dependencies in pyproject.toml
175
+ dependencies = [
176
+ "pylibsparseir>=0.8.0,<0.9.0", # Update version range
177
+ ]
178
+
179
+ 2. **Update .conda/meta.yaml**::
180
+
181
+ # Edit both host and run requirements in .conda/meta.yaml
182
+ requirements:
183
+ host:
184
+ - spm-lab::pylibsparseir >=0.8.0,<0.9.0
185
+ run:
186
+ - spm-lab::pylibsparseir >=0.8.0,<0.9.0
187
+
188
+ 3. **Verify consistency**::
189
+
190
+ python check_libsparseir_version_consistency.py
191
+
192
+ This should output ``✅ Version specifications are consistent!``
193
+
194
+ 4. **Commit changes**::
195
+
196
+ git add pyproject.toml .conda/meta.yaml
197
+ git commit -m "chore: update pylibsparseir dependency to >=0.8.0,<0.9.0"
198
+
199
+ Version Consistency Check
200
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
201
+ This repository includes a tool to ensure consistency between different package managers:
202
+
203
+ - **Version Consistency Check**: Ensures that ``pylibsparseir`` version
204
+ specifications in ``pyproject.toml`` and ``.conda/meta.yaml`` are consistent.
205
+
206
+ Run the check manually::
207
+
208
+ python check_libsparseir_version_consistency.py
209
+
210
+ Or install as a pre-commit hook::
211
+
212
+ pip install pre-commit
213
+ pre-commit install
214
+
215
+ Release Process
216
+ ~~~~~~~~~~~~~~~
217
+ To release a new version (e.g., ``2.0.0a10``):
218
+
219
+ 1. **Create a working branch for version bump**::
220
+
221
+ git checkout mainline
222
+ git pull origin mainline
223
+ git checkout -b bump-to-2.0.0a10
224
+
225
+ 2. **Update version in pyproject.toml**::
226
+
227
+ # Edit pyproject.toml: version = "2.0.0a10"
228
+
229
+ 3. **Commit and push**::
230
+
231
+ git add pyproject.toml
232
+ git commit -m "Bump to v2.0.0a10"
233
+ git push --set-upstream origin bump-to-2.0.0a10
234
+
235
+ 4. **Create Pull Request and merge to mainline**
236
+
237
+ 5. **Create and push tag**::
238
+
239
+ git checkout mainline
240
+ git pull origin mainline
241
+ git tag v2.0.0a10
242
+ git push origin v2.0.0a10
243
+
244
+ 6. **Automated builds** (triggered by tag push):
245
+
246
+ - PyPI: ``wheel.yml`` workflow builds and uploads to PyPI
247
+ - conda: ``conda.yml`` workflow builds and uploads to SpM-lab channel
248
+
249
+ Both workflows are automatically triggered when a tag starting with ``v`` is pushed.
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "sparse-ir"
3
- version = "2.1.0"
3
+ version = "2.1.2"
4
4
  description = "Python bindings for the libsparseir library, providing efficient sparse intermediate representation for many-body physics calculations"
5
- readme = "README.md"
5
+ readme = "README.rst"
6
6
  requires-python = ">=3.10"
7
7
  dependencies = [
8
8
  "numpy",
9
9
  "scipy",
10
- "pylibsparseir>=0.8.0,<0.9.0",
10
+ "pylibsparseir>=0.8.3,<0.10.0",
11
11
  ]
12
12
  authors = [
13
13
  {name = "SpM-lab"}
@@ -15,10 +15,12 @@ authors = [
15
15
  license = "MIT"
16
16
  keywords = ["physics", "many-body", "green-functions", "sparse-ir"]
17
17
  classifiers = [
18
- "Development Status :: 3 - Alpha",
18
+ "Development Status :: 5 - Production/Stable",
19
19
  "Intended Audience :: Science/Research",
20
20
  "Programming Language :: Python :: 3",
21
21
  "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Programming Language :: Python :: 3.14",
22
24
  "Topic :: Scientific/Engineering :: Physics",
23
25
  ]
24
26
 
@@ -5,12 +5,28 @@ High-level Python classes for FiniteTempBasis
5
5
  """
6
6
  from typing import Optional
7
7
  import numpy as np
8
- from pylibsparseir.core import basis_new, basis_get_size, basis_get_svals, basis_get_u, basis_get_v, basis_get_uhat, basis_get_default_tau_sampling_points, basis_get_default_omega_sampling_points, basis_get_default_matsubara_sampling_points
9
- from pylibsparseir.constants import SPIR_STATISTICS_FERMIONIC, SPIR_STATISTICS_BOSONIC
8
+ from pylibsparseir.core import (
9
+ basis_new,
10
+ basis_get_svals,
11
+ basis_get_u,
12
+ basis_get_v,
13
+ basis_get_uhat,
14
+ basis_get_default_tau_sampling_points,
15
+ basis_get_default_matsubara_sampling_points,
16
+ )
17
+ from pylibsparseir.constants import (
18
+ SPIR_STATISTICS_FERMIONIC,
19
+ SPIR_STATISTICS_BOSONIC,
20
+ )
10
21
  from .kernel import LogisticKernel
11
- from .abstract import AbstractBasis
22
+ from .abstract import AbstractBasis, AbstractKernel
12
23
  from .sve import SVEResult
13
- from .poly import PiecewiseLegendrePolyVector, PiecewiseLegendrePolyFTVector, FunctionSet, FunctionSetFT
24
+ from .poly import (
25
+ PiecewiseLegendrePolyVector,
26
+ PiecewiseLegendrePolyFTVector,
27
+ FunctionSet,
28
+ FunctionSetFT,
29
+ )
14
30
 
15
31
  class FiniteTempBasis(AbstractBasis):
16
32
  r"""Intermediate representation (IR) basis for given temperature.
@@ -43,7 +59,17 @@ class FiniteTempBasis(AbstractBasis):
43
59
  giw = gl @ basis.uhat([1, 3, 5, 7])
44
60
  """
45
61
 
46
- def __init__(self, statistics: str, beta: float, wmax: float, eps: float = np.finfo(np.float64).eps, sve_result: Optional[SVEResult] = None, max_size: int =-1):
62
+ def __init__(
63
+ self,
64
+ statistics: str,
65
+ beta: float,
66
+ wmax: float,
67
+ eps: Optional[float] = None,
68
+ *,
69
+ max_size: Optional[int] = None,
70
+ kernel: Optional[AbstractKernel] = None,
71
+ sve_result: Optional[SVEResult] = None,
72
+ ):
47
73
  """
48
74
  Initialize finite temperature basis.
49
75
 
@@ -55,31 +81,65 @@ class FiniteTempBasis(AbstractBasis):
55
81
  Inverse temperature
56
82
  wmax : float
57
83
  Frequency cutoff
58
- eps : float
59
- Relative truncation threshold for the singular values,
60
- defaulting to the machine epsilon (2.2e-16)
84
+ eps : float, optional
85
+ Relative truncation threshold for the singular values.
86
+ Defaults to machine epsilon (~2.2e-16).
87
+ max_size : int, optional
88
+ Maximum basis size. If given, only at most the ``max_size`` most
89
+ significant singular values and associated basis functions are
90
+ retained.
91
+ kernel : AbstractKernel, optional
92
+ Kernel to use for the basis. If not given, a LogisticKernel is
93
+ created from beta * wmax. (Deprecated: kernel is inferred from
94
+ statistics.)
95
+ sve_result : SVEResult, optional
96
+ Precomputed SVE result. If not given, the SVE is computed.
61
97
  """
98
+ if not (beta > 0):
99
+ raise ValueError("inverse temperature beta must be positive")
100
+ if not (wmax >= 0):
101
+ raise ValueError("frequency cutoff must be non-negative")
102
+
62
103
  self._statistics = statistics
63
104
  self._beta = beta
64
105
  self._wmax = wmax
65
106
  self._lambda = beta * wmax
107
+
108
+ # Handle eps default
109
+ if eps is None:
110
+ eps = np.finfo(np.float64).eps
66
111
  self._eps = eps
67
112
 
68
- # Create kernel
69
- if statistics == 'F' or statistics == 'B':
113
+ # Handle max_size
114
+ if max_size is None:
115
+ max_size = -1
116
+
117
+ # Create or use provided kernel
118
+ if kernel is not None:
119
+ # Backward compatibility: use provided kernel
120
+ self._kernel = kernel
121
+ elif statistics in ('F', 'B'):
70
122
  self._kernel = LogisticKernel(self._lambda)
71
123
  else:
72
- raise ValueError(f"Invalid statistics: {statistics} expected 'F' or 'B'")
124
+ raise ValueError(
125
+ f"Invalid statistics: {statistics}, expected 'F' or 'B'"
126
+ )
73
127
 
74
- # Compute SVE
128
+ # Compute SVE if not provided
75
129
  if sve_result is None:
76
130
  self._sve = SVEResult(self._kernel, eps)
77
131
  else:
78
132
  self._sve = sve_result
79
133
 
80
134
  # Create basis
81
- stats_int = SPIR_STATISTICS_FERMIONIC if statistics == 'F' else SPIR_STATISTICS_BOSONIC
82
- self._ptr = basis_new(stats_int, self._beta, self._wmax, self._eps, self._kernel._ptr, self._sve._ptr, max_size)
135
+ stats_int = (
136
+ SPIR_STATISTICS_FERMIONIC if statistics == 'F'
137
+ else SPIR_STATISTICS_BOSONIC
138
+ )
139
+ self._ptr = basis_new(
140
+ stats_int, self._beta, self._wmax, self._eps,
141
+ self._kernel._ptr, self._sve._ptr, max_size
142
+ )
83
143
 
84
144
  u_funcs = FunctionSet(basis_get_u(self._ptr))
85
145
  v_funcs = FunctionSet(basis_get_v(self._ptr))
@@ -168,8 +228,11 @@ class FiniteTempBasis(AbstractBasis):
168
228
 
169
229
  @property
170
230
  def accuracy(self):
171
- """Overall accuracy bound."""
172
- return self.s[-1] / self.s[0]
231
+ """Overall truncation error bound."""
232
+ sve_s = self.sve_result.s
233
+ if sve_s.size > self.size:
234
+ return sve_s[self.size] / sve_s[0]
235
+ return sve_s[-1] / sve_s[0]
173
236
 
174
237
  @property
175
238
  def shape(self):
@@ -260,4 +323,4 @@ def finite_temp_bases(beta, wmax, eps=None, sve_result=None):
260
323
  """
261
324
  fermion_basis = FiniteTempBasis('F', beta, wmax, eps, sve_result=sve_result)
262
325
  boson_basis = FiniteTempBasis('B', beta, wmax, eps, sve_result=sve_result)
263
- return fermion_basis, boson_basis
326
+ return fermion_basis, boson_basis
@@ -332,7 +332,7 @@ class MatsubaraSampling:
332
332
  )
333
333
  if status != COMPUTATION_SUCCESS:
334
334
  raise RuntimeError(f"Failed to fit sampling: {status}")
335
- return output['real']
335
+ return output['real'] + 1j * output['imag']
336
336
 
337
337
  @property
338
338
  def cond(self):
@@ -1,4 +1,5 @@
1
- # Copyright (C) 2020-2025 Satoshi Terasaki, Markus Wallerberger, Hiroshi Shinaoka, and others
1
+ # Copyright (C) 2020-2025 Satoshi Terasaki, Markus Wallerberger,
2
+ # Hiroshi Shinaoka, and others
2
3
  # SPDX-License-Identifier: MIT
3
4
  """
4
5
  SVE (Singular Value Expansion) functionality for SparseIR.
@@ -7,10 +8,40 @@ This module provides Python wrappers for SVE computation and results.
7
8
  """
8
9
  import numpy as np
9
10
 
10
- from pylibsparseir.core import _lib, sve_result_new, sve_result_get_svals, sve_result_get_size
11
+ from pylibsparseir.constants import (
12
+ SPIR_TWORK_FLOAT64,
13
+ SPIR_TWORK_FLOAT64X2,
14
+ )
15
+ from pylibsparseir.core import (
16
+ _lib,
17
+ sve_result_new,
18
+ sve_result_get_svals,
19
+ sve_result_get_size,
20
+ )
11
21
  from .abstract import AbstractKernel
12
22
  from .kernel import LogisticKernel, RegularizedBoseKernel
13
23
 
24
+
25
+ def _resolve_work_dtype(work_dtype):
26
+ if work_dtype is None:
27
+ return None
28
+
29
+ if isinstance(work_dtype, str):
30
+ work_dtype = work_dtype.lower()
31
+ if work_dtype in {"float64", "double"}:
32
+ return SPIR_TWORK_FLOAT64
33
+ if work_dtype in {"float64x2", "ddouble"}:
34
+ return SPIR_TWORK_FLOAT64X2
35
+ raise TypeError(f"unexpected work_dtype string {work_dtype!r}")
36
+
37
+ dtype = np.dtype(work_dtype)
38
+ if dtype == np.float64:
39
+ return SPIR_TWORK_FLOAT64
40
+ if dtype.itemsize > np.dtype(np.float64).itemsize:
41
+ return SPIR_TWORK_FLOAT64X2
42
+ raise TypeError(f"unsupported work_dtype {dtype}")
43
+
44
+
14
45
  class SVEResult:
15
46
  """
16
47
  Result of a singular value expansion (SVE).
@@ -19,7 +50,14 @@ class SVEResult:
19
50
  the SVE of an integral kernel.
20
51
  """
21
52
 
22
- def __init__(self, kernel: AbstractKernel, eps: float, cutoff: float=-1, n_sv: int=-1):
53
+ def __init__(
54
+ self,
55
+ kernel: AbstractKernel,
56
+ eps: float,
57
+ cutoff: float = -1,
58
+ n_sv: int = -1,
59
+ work_dtype=None,
60
+ ):
23
61
  """
24
62
  Compute SVE of the given kernel.
25
63
 
@@ -37,14 +75,23 @@ class SVEResult:
37
75
  returned.
38
76
  """
39
77
  if not isinstance(kernel, (LogisticKernel, RegularizedBoseKernel)):
40
- raise TypeError("kernel must be LogisticKernel or RegularizedBoseKernel")
78
+ raise TypeError(
79
+ "kernel must be LogisticKernel or RegularizedBoseKernel"
80
+ )
41
81
 
42
82
  self._kernel = kernel # Store kernel for later use
43
83
  self._eps = eps
44
84
  self._cutoff = cutoff
45
85
  self._n_sv = n_sv
46
86
 
47
- self._ptr = sve_result_new(kernel._ptr, eps, cutoff=cutoff, lmax=n_sv)
87
+ twork = _resolve_work_dtype(work_dtype)
88
+ self._ptr = sve_result_new(
89
+ kernel._ptr,
90
+ eps,
91
+ cutoff=cutoff,
92
+ lmax=n_sv,
93
+ Twork=twork,
94
+ )
48
95
 
49
96
  def __len__(self):
50
97
  return sve_result_get_size(self._ptr)
@@ -59,7 +106,12 @@ class SVEResult:
59
106
  _lib.spir_sve_result_release(self._ptr)
60
107
 
61
108
 
62
- def compute(kernel, eps=np.finfo(np.float64).eps, n_sv=-1):
109
+ def compute(
110
+ kernel,
111
+ eps=np.finfo(np.float64).eps,
112
+ n_sv=-1,
113
+ work_dtype=None,
114
+ ):
63
115
  """Perform truncated singular value expansion of a kernel.
64
116
 
65
117
  Perform a truncated singular value expansion (SVE) of an integral
@@ -85,8 +137,12 @@ def compute(kernel, eps=np.finfo(np.float64).eps, n_sv=-1):
85
137
  n_sv (int):
86
138
  Maximum basis size. If given, only at most the ``n_sv`` most
87
139
  significant singular values and associated singular functions are
140
+ returned. Defaults to -1, which means all singular values are
88
141
  returned.
89
- Defaulting to -1, which means all singular values are returned.
142
+ work_dtype (dtype-like or str, optional):
143
+ Working data type used during the SVE / SVD computation. Accepts
144
+ ``numpy.float64``, ``float``, or strings such as ``"float64"`` or
145
+ ``"float64x2"``. Defaults to ``float64x2`` for maximal precision.
90
146
 
91
147
  Returns:
92
148
  An ``SVEResult`` containing the truncated singular value expansion.
@@ -94,8 +150,14 @@ def compute(kernel, eps=np.finfo(np.float64).eps, n_sv=-1):
94
150
 
95
151
  if eps is None:
96
152
  eps = np.finfo(np.float64).eps
97
- return SVEResult(kernel, eps=eps, cutoff=-1, n_sv=n_sv)
153
+ return SVEResult(
154
+ kernel,
155
+ eps=eps,
156
+ cutoff=-1,
157
+ n_sv=n_sv,
158
+ work_dtype=work_dtype,
159
+ )
98
160
 
99
161
 
100
162
  # Backward compatibility
101
- compute_sve = compute
163
+ compute_sve = compute
@@ -0,0 +1,249 @@
1
+ Metadata-Version: 2.4
2
+ Name: sparse-ir
3
+ Version: 2.1.2
4
+ Summary: Python bindings for the libsparseir library, providing efficient sparse intermediate representation for many-body physics calculations
5
+ Author: SpM-lab
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/SpM-lab/sparse-r
8
+ Project-URL: Repository, https://github.com/SpM-lab/sparse-r
9
+ Project-URL: Bug Tracker, https://github.com/SpM-lab/sparse-r/issues
10
+ Keywords: physics,many-body,green-functions,sparse-ir
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Topic :: Scientific/Engineering :: Physics
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/x-rst
20
+ License-File: LICENSE.txt
21
+ Requires-Dist: numpy
22
+ Requires-Dist: scipy
23
+ Requires-Dist: pylibsparseir<0.10.0,>=0.8.3
24
+ Dynamic: license-file
25
+
26
+ sparse-ir - A library for the intermediate representation of propagators
27
+ ========================================================================
28
+ This library provides routines for constructing and working with the
29
+ intermediate representation of correlation functions. It provides:
30
+
31
+ - on-the-fly computation of basis functions for arbitrary cutoff Λ
32
+ - basis functions and singular values are accurate to full precision
33
+ - routines for sparse sampling
34
+
35
+
36
+ Installation
37
+ ------------
38
+ Install via `pip <https://pypi.org/project/sparse-ir>`_::
39
+
40
+ pip install sparse-ir
41
+
42
+ Install via `conda <https://anaconda.org/spm-lab/sparse-ir>`_::
43
+
44
+ conda install -c spm-lab sparse-ir
45
+
46
+ sparse-ir requires `numpy <https://numpy.org/>`_, `scipy <https://scipy.org/>`_,
47
+ and `pylibsparseir <https://pypi.org/project/pylibsparseir>`_ (a thin Python wrapper
48
+ for the `libsparseir <https://github.com/SpM-lab/libsparseir>`_ C API).
49
+
50
+ To manually install the current development version, you can use the following::
51
+
52
+ # Only recommended for developers - no automatic updates!
53
+ git clone https://github.com/SpM-lab/sparse-ir
54
+ cd sparse-ir
55
+ uv sync
56
+
57
+ Note: `uv` is a fast Python package manager. If you don't have it installed,
58
+ you can install it with ``pip install uv`` or use ``pip install -e .`` instead.
59
+
60
+ Building documentation
61
+ ----------------------
62
+ To build the documentation locally, first install the development dependencies::
63
+
64
+ uv sync --group doc
65
+
66
+ Then build the documentation::
67
+
68
+ uv run sphinx-build -M html doc _build/html
69
+
70
+ The documentation will be available in ``_build/html/html/index.html``.
71
+
72
+ Documentation and tutorial
73
+ --------------------------
74
+ Check out our `comprehensive tutorial`_, where we self-contained
75
+ notebooks for several many-body methods - GF(2), GW, Eliashberg equations,
76
+ Lichtenstein formula, FLEX, ... - are presented.
77
+
78
+ Refer to the `API documentation`_ for more details on how to work
79
+ with the python library.
80
+
81
+ There is also a `Julia library`_ and (currently somewhat restricted)
82
+ `C library with Fortran bindings`_ available for the IR basis and sparse sampling.
83
+
84
+ .. _comprehensive tutorial: https://spm-lab.github.io/sparse-ir-tutorial
85
+ .. _API documentation: https://sparse-ir.readthedocs.io
86
+ .. _Julia library: https://github.com/SpM-lab/SparseIR.jl
87
+ .. _C library with Fortran bindings: https://github.com/SpM-lab/libsparseir
88
+
89
+ Getting started
90
+ ---------------
91
+ Here is a full second-order perturbation theory solver (GF(2)) in a few
92
+ lines of Python code::
93
+
94
+ # Construct the IR basis and sparse sampling for fermionic propagators
95
+ import sparse_ir, numpy as np
96
+ basis = sparse_ir.FiniteTempBasis('F', beta=10, wmax=8, eps=1e-6)
97
+ stau = sparse_ir.TauSampling(basis)
98
+ siw = sparse_ir.MatsubaraSampling(basis, positive_only=True)
99
+
100
+ # Solve the single impurity Anderson model coupled to a bath with a
101
+ # semicircular states with unit half bandwidth.
102
+ U = 1.2
103
+ def rho0w(w):
104
+ return np.sqrt(1-w.clip(-1,1)**2) * 2/np.pi
105
+
106
+ # Compute the IR basis coefficients for the non-interacting propagator
107
+ rho0l = basis.v.overlap(rho0w)
108
+ G0l = -basis.s * rho0l
109
+
110
+ # Self-consistency loop: alternate between second-order expression for the
111
+ # self-energy and the Dyson equation until convergence.
112
+ Gl = G0l
113
+ Gl_prev = 0
114
+ while np.linalg.norm(Gl - Gl_prev) > 1e-6:
115
+ Gl_prev = Gl
116
+ Gtau = stau.evaluate(Gl)
117
+ Sigmatau = U**2 * Gtau**3
118
+ Sigmal = stau.fit(Sigmatau)
119
+ Sigmaiw = siw.evaluate(Sigmal)
120
+ G0iw = siw.evaluate(G0l)
121
+ Giw = 1/(1/G0iw - Sigmaiw)
122
+ Gl = siw.fit(Giw)
123
+
124
+ You may want to start with reading up on the `intermediate representation`_.
125
+ It is tied to the analytic continuation of bosonic/fermionic spectral
126
+ functions from (real) frequencies to imaginary time, a transformation mediated
127
+ by a kernel ``K``. The kernel depends on a cutoff, which you should choose to
128
+ be ``lambda_ >= beta * W``, where ``beta`` is the inverse temperature and ``W``
129
+ is the bandwidth.
130
+
131
+ One can now perform a `singular value expansion`_ on this kernel, which
132
+ generates two sets of orthonormal basis functions, one set ``v[l](w)`` for
133
+ real frequency side ``w``, and one set ``u[l](tau)`` for the same obejct in
134
+ imaginary (Euclidean) time ``tau``, together with a "coupling" strength
135
+ ``s[l]`` between the two sides.
136
+
137
+ By this construction, the imaginary time basis can be shown to be *optimal* in
138
+ terms of compactness.
139
+
140
+ .. _intermediate representation: https://arxiv.org/abs/2106.12685
141
+ .. _singular value expansion: https://w.wiki/3poQ
142
+
143
+ License and citation
144
+ --------------------
145
+ This software is released under the MIT License. See LICENSE.txt for details.
146
+
147
+ If you find the intermediate representation, sparse sampling, or this software
148
+ useful in your research, please consider citing the following papers:
149
+
150
+ - Hiroshi Shinaoka et al., `Phys. Rev. B 96, 035147`_ (2017)
151
+ - Jia Li et al., `Phys. Rev. B 101, 035144`_ (2020)
152
+ - Markus Wallerberger et al., `SoftwareX 21, 101266`_ (2023)
153
+
154
+ If you are discussing sparse sampling in your research specifically, please
155
+ also consider citing an independently discovered, closely related approach, the
156
+ MINIMAX isometry method (Merzuk Kaltak and Georg Kresse,
157
+ `Phys. Rev. B 101, 205145`_, 2020).
158
+
159
+ .. _Phys. Rev. B 96, 035147: https://doi.org/10.1103/PhysRevB.96.035147
160
+ .. _Phys. Rev. B 101, 035144: https://doi.org/10.1103/PhysRevB.101.035144
161
+ .. _SoftwareX 21, 101266: https://doi.org/10.1016/j.softx.2022.101266
162
+ .. _Phys. Rev. B 101, 205145: https://doi.org/10.1103/PhysRevB.101.205145
163
+
164
+ Development
165
+ -----------
166
+
167
+ Updating pylibsparseir Dependency
168
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
169
+ When updating the ``pylibsparseir`` dependency version, you must update it in
170
+ **both** ``pyproject.toml`` and ``.conda/meta.yaml`` to maintain consistency:
171
+
172
+ 1. **Update pyproject.toml**::
173
+
174
+ # Edit dependencies in pyproject.toml
175
+ dependencies = [
176
+ "pylibsparseir>=0.8.0,<0.9.0", # Update version range
177
+ ]
178
+
179
+ 2. **Update .conda/meta.yaml**::
180
+
181
+ # Edit both host and run requirements in .conda/meta.yaml
182
+ requirements:
183
+ host:
184
+ - spm-lab::pylibsparseir >=0.8.0,<0.9.0
185
+ run:
186
+ - spm-lab::pylibsparseir >=0.8.0,<0.9.0
187
+
188
+ 3. **Verify consistency**::
189
+
190
+ python check_libsparseir_version_consistency.py
191
+
192
+ This should output ``✅ Version specifications are consistent!``
193
+
194
+ 4. **Commit changes**::
195
+
196
+ git add pyproject.toml .conda/meta.yaml
197
+ git commit -m "chore: update pylibsparseir dependency to >=0.8.0,<0.9.0"
198
+
199
+ Version Consistency Check
200
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
201
+ This repository includes a tool to ensure consistency between different package managers:
202
+
203
+ - **Version Consistency Check**: Ensures that ``pylibsparseir`` version
204
+ specifications in ``pyproject.toml`` and ``.conda/meta.yaml`` are consistent.
205
+
206
+ Run the check manually::
207
+
208
+ python check_libsparseir_version_consistency.py
209
+
210
+ Or install as a pre-commit hook::
211
+
212
+ pip install pre-commit
213
+ pre-commit install
214
+
215
+ Release Process
216
+ ~~~~~~~~~~~~~~~
217
+ To release a new version (e.g., ``2.0.0a10``):
218
+
219
+ 1. **Create a working branch for version bump**::
220
+
221
+ git checkout mainline
222
+ git pull origin mainline
223
+ git checkout -b bump-to-2.0.0a10
224
+
225
+ 2. **Update version in pyproject.toml**::
226
+
227
+ # Edit pyproject.toml: version = "2.0.0a10"
228
+
229
+ 3. **Commit and push**::
230
+
231
+ git add pyproject.toml
232
+ git commit -m "Bump to v2.0.0a10"
233
+ git push --set-upstream origin bump-to-2.0.0a10
234
+
235
+ 4. **Create Pull Request and merge to mainline**
236
+
237
+ 5. **Create and push tag**::
238
+
239
+ git checkout mainline
240
+ git pull origin mainline
241
+ git tag v2.0.0a10
242
+ git push origin v2.0.0a10
243
+
244
+ 6. **Automated builds** (triggered by tag push):
245
+
246
+ - PyPI: ``wheel.yml`` workflow builds and uploads to PyPI
247
+ - conda: ``conda.yml`` workflow builds and uploads to SpM-lab channel
248
+
249
+ Both workflows are automatically triggered when a tag starting with ``v`` is pushed.
@@ -0,0 +1,3 @@
1
+ numpy
2
+ scipy
3
+ pylibsparseir<0.10.0,>=0.8.3
@@ -19,14 +19,36 @@ class TestSVEAccuracy:
19
19
  """Test that basis accuracy meets expected bounds."""
20
20
  eps = 1e-6
21
21
  basis = sparse_ir.FiniteTempBasis(stat, beta, wmax, eps)
22
+ sve_s = basis.sve_result.s
22
23
 
23
- # Basic properties
24
- assert 0 < basis.accuracy <= basis.significance[-1]
24
+ # Accuracy is the relative significance of the first singular value
25
+ # excluded from the basis.
26
+ assert sve_s.size > basis.size
27
+ expected_accuracy = sve_s[basis.size] / sve_s[0]
28
+ assert basis.accuracy == expected_accuracy
25
29
  assert basis.significance[0] == 1.0
26
- assert basis.accuracy <= basis.s[-1] / basis.s[0]
30
+ assert basis.accuracy < eps <= basis.significance[-1]
27
31
 
28
- # Accuracy should be better than requested epsilon (with some tolerance)
29
- assert basis.accuracy <= 10 * eps, f"Accuracy {basis.accuracy} should be close to eps {eps}"
32
+ def test_accuracy_with_max_size(self):
33
+ """Test accuracy when max_size, rather than epsilon, truncates."""
34
+ eps = 1e-6
35
+ basis = sparse_ir.FiniteTempBasis(
36
+ 'F', 1.0, 42.0, eps, max_size=5
37
+ )
38
+ sve_s = basis.sve_result.s
39
+
40
+ assert basis.size == 5
41
+ assert basis.accuracy == sve_s[basis.size] / sve_s[0]
42
+ assert basis.accuracy > eps
43
+ assert basis.accuracy < basis.significance[-1]
44
+
45
+ def test_accuracy_without_excluded_singular_value(self):
46
+ """Test the fallback when the SVE contains no excluded value."""
47
+ basis = sparse_ir.FiniteTempBasis('F', 1e-3, 1e-3, 1e-100)
48
+ sve_s = basis.sve_result.s
49
+
50
+ assert sve_s.size == basis.size
51
+ assert basis.accuracy == sve_s[-1] / sve_s[0]
30
52
 
31
53
  @pytest.mark.parametrize("stat,beta,wmax", BASIS_PARAMS)
32
54
  def test_singular_value_properties(self, stat, beta, wmax):
@@ -133,4 +155,3 @@ class TestBasisConsistency:
133
155
  assert 5 <= f_basis.size <= 100
134
156
  assert 5 <= b_basis.size <= 100
135
157
 
136
-
sparse_ir-2.1.0/PKG-INFO DELETED
@@ -1,22 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: sparse-ir
3
- Version: 2.1.0
4
- Summary: Python bindings for the libsparseir library, providing efficient sparse intermediate representation for many-body physics calculations
5
- Author: SpM-lab
6
- License-Expression: MIT
7
- Project-URL: Homepage, https://github.com/SpM-lab/sparse-r
8
- Project-URL: Repository, https://github.com/SpM-lab/sparse-r
9
- Project-URL: Bug Tracker, https://github.com/SpM-lab/sparse-r/issues
10
- Keywords: physics,many-body,green-functions,sparse-ir
11
- Classifier: Development Status :: 3 - Alpha
12
- Classifier: Intended Audience :: Science/Research
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.12
15
- Classifier: Topic :: Scientific/Engineering :: Physics
16
- Requires-Python: >=3.10
17
- Description-Content-Type: text/markdown
18
- License-File: LICENSE.txt
19
- Requires-Dist: numpy
20
- Requires-Dist: scipy
21
- Requires-Dist: pylibsparseir<0.9.0,>=0.8.0
22
- Dynamic: license-file
@@ -1,22 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: sparse-ir
3
- Version: 2.1.0
4
- Summary: Python bindings for the libsparseir library, providing efficient sparse intermediate representation for many-body physics calculations
5
- Author: SpM-lab
6
- License-Expression: MIT
7
- Project-URL: Homepage, https://github.com/SpM-lab/sparse-r
8
- Project-URL: Repository, https://github.com/SpM-lab/sparse-r
9
- Project-URL: Bug Tracker, https://github.com/SpM-lab/sparse-r/issues
10
- Keywords: physics,many-body,green-functions,sparse-ir
11
- Classifier: Development Status :: 3 - Alpha
12
- Classifier: Intended Audience :: Science/Research
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.12
15
- Classifier: Topic :: Scientific/Engineering :: Physics
16
- Requires-Python: >=3.10
17
- Description-Content-Type: text/markdown
18
- License-File: LICENSE.txt
19
- Requires-Dist: numpy
20
- Requires-Dist: scipy
21
- Requires-Dist: pylibsparseir<0.9.0,>=0.8.0
22
- Dynamic: license-file
@@ -1,3 +0,0 @@
1
- numpy
2
- scipy
3
- pylibsparseir<0.9.0,>=0.8.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes