Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,44 @@ terms of compactness.
[intermediate representation]: https://arxiv.org/abs/2106.12685
[singular value expansion]: https://w.wiki/3poQ

Migrating from SparseIR.jl v1
-----------------------------
Since version 2, SparseIR.jl wraps the libsparseir C library instead of
computing the basis in Julia. The singular value expansion (SVE) and the
polynomial internals of v1 are no longer accessible from Julia, and a few
constructor signatures changed. The table maps the v1 code that no longer runs
to its v2 replacement (`basis` is a `FiniteTempBasis`, `β = SparseIR.β(basis)`).

| v1 | v2 |
|----|----|
| `FiniteTempBasis{S}(β, ωmax)`, `FiniteTempBasis(S(), β, ωmax)` (`ε` optional) | `FiniteTempBasis{S}(β, ωmax, ε)`: `ε` is required |
| `finite_temp_bases(β, ωmax)` | `finite_temp_bases(β, ωmax, ε)` |
| `SVEResult(kernel; ε)` | `SparseIR.SVEResult(kernel, ε)` |
| `SVEResult(kernel; Twork=Float64x2)` | `SparseIR.SVEResult(kernel, ε; Twork=SparseIR.SPIR_TWORK_FLOAT64X2)` |
| `basis.sve_result.u`, `basis.sve_result.v` | not available; an `SVEResult` holds only the singular values `s`. Use `basis.u`, `basis.v` (in `τ` and `ω`) |
| `SparseIR.default_sampling_points(basis.sve_result.u, length(basis))` | `2 .* SparseIR.default_tau_sampling_points(basis) ./ β .- 1` (the same points, ascending, in `x ∈ (-1, 1)`) |
| `SparseIR.default_sampling_points(basis.sve_result.u, L)` | the same expression with `basis[1:L]` (for `L ≤ length(basis)`) or a basis of size `L` built with `max_size=L` and a smaller `ε` |
| `SparseIR.default_sampling_points(basis.sve_result.v, L)` | `default_omega_sampling_points(basis) ./ SparseIR.ωmax(basis)` with a basis of size `L`, as above |
| `SparseIR.default_matsubara_sampling_points(basis.uhat_full, L; positive_only)` | `SparseIR.default_matsubara_sampling_points(basis[1:L]; positive_only)` (for `L ≤ length(basis)`); `basis.uhat_full` and `fence` were removed |
| `SparseIR.roots`, `SparseIR.sign_changes`, `SparseIR.find_extrema` | removed; the default sampling points are computed by libsparseir |
| `basis.accuracy`, `SparseIR.sve_result(basis)`, `SparseIR.kernel(basis)` | `SparseIR.accuracy(basis)`, `basis.sve_result`, `basis.kernel` |
| `TauSampling(basis; factorize=false)`, `MatsubaraSampling(basis; factorize=false)` | the `factorize` keyword was removed |
| `TauSampling(basis).τ` | `TauSampling(basis).tau` or `sampling_points(smpl)` |
| `SparseIR.TauSampling64` | `SparseIR.TauSampling64F` (fermions) or `SparseIR.TauSampling64B` (bosons) |
| user-defined subtypes of `SparseIR.AbstractKernel` | not supported; only `LogisticKernel` and `RegularizedBoseKernel` |

Two behaviors changed without an error:

- `MatsubaraSampling(basis; sampling_points=ωn)` keeps the order of `ωn`
(v1 sorted it in ascending order); `evaluate` returns and `fit` expects the
values in the given order.
- `basis.u(τ)` also accepts `τ ∈ [-β, 0)`, where it returns the values
continued with the (anti-)periodicity of the statistics; v1 was defined on
`[0, β]` only.

`SparseIR.default_tau_sampling_points(basis)`, `SparseIR.default_matsubara_sampling_points(basis)`
and `default_omega_sampling_points(basis)` return the same points as in v1.

Development
-----------
If you are developing `SparseIR.jl` together with the Rust backend in the sibling
Expand Down
42 changes: 42 additions & 0 deletions llms.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# SparseIR.jl

> Julia wrapper of libsparseir (the C API of sparse-ir-rs) for the intermediate representation (IR) of many-body propagators: IR bases, sparse sampling in imaginary time and Matsubara frequency, and the discrete Lehmann representation (DLR). This file describes version 2; code written for version 1 needs the changes listed under "Migrating from v1".

## Documentation

- [README](https://github.com/SpM-lab/SparseIR.jl/blob/main/README.md): installation, an example, and the full v1 → v2 migration table
- [API documentation](https://spm-lab.github.io/SparseIR.jl/stable/)
- [Notation and conventions](https://spm-lab.github.io/sparse-ir-doc/src/notation.html): statistics, τ domain, Matsubara frequencies, sign of the Green's function
- [Tutorial](https://spm-lab.github.io/sparse-ir-tutorial-v2/)

## Basic usage

```julia
using SparseIR
β, ωmax, ε = 10.0, 1.0, 1e-8
basis = FiniteTempBasis{Fermionic}(β, ωmax, ε) # ε is required
smpl_tau = TauSampling(basis) # default points: τ ∈ [0, β], ascending
smpl_iw = MatsubaraSampling(basis; positive_only=true)
gl = -basis.s .* basis.v(0.3) # IR coefficients of a single pole at ω = 0.3
gtau = evaluate(smpl_tau, gl) # dim= selects the axis of a multidimensional array
giw = evaluate(smpl_iw, gl)
gl ≈ fit(smpl_tau, gtau)
```

- `basis.u(τ)`, `basis.v(ω)`, `basis.uhat(n)` evaluate all basis functions; `basis.u[l+1]` is `U_l`; `basis[1:L]` is the basis truncated to size `L`.
- `SparseIR.β(basis)`, `SparseIR.ωmax(basis)`, `SparseIR.accuracy(basis)`, `SparseIR.significance(basis)`; also spelled `SparseIR.beta`, `SparseIR.wmax`.
- `SparseIR.default_tau_sampling_points(basis)`, `SparseIR.default_matsubara_sampling_points(basis; positive_only)`, `default_omega_sampling_points(basis)` give the default sampling points; `sampling_points(smpl)` those of a sampling object.
- Kernels: `LogisticKernel(Λ)` (default, `Λ = β ωmax`) and `RegularizedBoseKernel(Λ)` only.

## Migrating from v1

- `ε` is required: `FiniteTempBasis{S}(β, ωmax, ε)`, `FiniteTempBasis(S(), β, ωmax, ε)`, `finite_temp_bases(β, ωmax, ε)`.
- `SVEResult(kernel; ε)` → `SparseIR.SVEResult(kernel, ε)`; `Twork=Float64x2` → `Twork=SparseIR.SPIR_TWORK_FLOAT64X2`.
- An `SVEResult` has no `u` or `v`, only the singular values `s`. `basis.sve_result.u` and `basis.sve_result.v` fail.
- `SparseIR.default_sampling_points(basis.sve_result.u, length(basis))` (the SVE points in `x ∈ (-1, 1)`) → `2 .* SparseIR.default_tau_sampling_points(basis) ./ SparseIR.β(basis) .- 1`. For another size `L`, use `basis[1:L]` (`L ≤ length(basis)`) or a larger basis built with `max_size=L` and a smaller `ε`.
- `SparseIR.default_sampling_points(basis.sve_result.v, L)` → `default_omega_sampling_points(b) ./ SparseIR.ωmax(b)` for a basis `b` of size `L`.
- `SparseIR.default_matsubara_sampling_points(basis.uhat_full, L; positive_only)` → `SparseIR.default_matsubara_sampling_points(basis[1:L]; positive_only)`. `basis.uhat_full` and the `fence` keyword were removed.
- Removed: `SparseIR.roots`, `SparseIR.sign_changes`, `SparseIR.find_extrema`, the `factorize` keyword of `TauSampling`/`MatsubaraSampling`, `SparseIR.sve_result(basis)` and `SparseIR.kernel(basis)` (use the fields `basis.sve_result`, `basis.kernel`), the field `basis.accuracy` (use `SparseIR.accuracy(basis)`), user-defined subtypes of `SparseIR.AbstractKernel`.
- Renamed: `TauSampling(basis).τ` → `.tau`; `SparseIR.TauSampling64` → `SparseIR.TauSampling64F` / `SparseIR.TauSampling64B`.
- Changed silently: `MatsubaraSampling(basis; sampling_points=ωn)` keeps the order of `ωn` (v1 sorted it); `basis.u(τ)` also accepts `τ ∈ [-β, 0)` (v1 threw a `DomainError`).
- Unchanged: the default τ, Matsubara and ω sampling points are the same as in v1.
32 changes: 32 additions & 0 deletions test/spir/migration_tests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# The v2 replacements of v1 code given in the migration guide (README.md and
# llms.txt). The points returned by v1's `default_sampling_points(sve.u, L)` are
# the roots of the SVE function u_L on (-1, 1); here the same roots are checked
# with a larger basis, whose function U_L vanishes at them.

@testitem "migration: v1 SVE sampling points from a v2 basis" tags=[:julia, :spir] setup=[SIRTestSetup] begin
using Test
using SparseIR

β, ωmax=10.0, 4.0
for stat in (Fermionic(), Bosonic())
basis = get_basis(stat, β, ωmax, 1e-8)
large = get_basis(stat, β, ωmax, 1e-12)
for L in (5, 12, length(basis))
b = basis[1:L]
x = 2 .* SparseIR.default_tau_sampling_points(b) ./ SparseIR.β(b) .- 1
@test length(x) == L
@test issorted(x)
@test all(-1 .< x .< 1)
@test x ≈ -reverse(x) atol=1e-12
τ=SparseIR.β(b)/2 .* (x .+ 1)
@test maximum(abs, large.u[L + 1](τ)) <
1e-8 * maximum(abs, large.u[L + 1](range(0, β; length=201)))

y=default_omega_sampling_points(b) ./ SparseIR.ωmax(b)
@test length(y) == L
@test all(-1 .< y .< 1)
@test maximum(abs, large.v[L + 1](SparseIR.ωmax(b) .* y)) <
1e-8 * maximum(abs, large.v[L + 1](range(-ωmax, ωmax; length=201)))
end
end
end
Loading