sparse_ir_core/basis_trait.rs
1//! Basis trait for IR and DLR representations
2//!
3//! This module provides a common trait for different basis representations
4//! (IR basis, DLR basis, augmented basis, etc.) in imaginary-time/frequency domains.
5
6use crate::error::Error;
7use crate::freq::MatsubaraFreq;
8use crate::traits::StatisticsType;
9
10/// Common trait for basis representations in imaginary-time/frequency domains
11///
12/// This trait abstracts over different basis representations:
13/// - `FiniteTempBasis`: IR (Intermediate Representation) basis
14/// - `DiscreteLehmannRepresentation`: DLR basis
15/// - `AugmentedBasis`: IR basis with additional functions
16///
17/// Each basis provides:
18/// - Physical parameters (β, ωmax, Λ)
19/// - Basis size and accuracy information
20/// - Default sampling points for τ and Matsubara frequencies
21///
22/// # Type Parameters
23/// * `S` - Statistics type (Fermionic or Bosonic)
24pub trait Basis<S: StatisticsType> {
25 /// Inverse temperature β
26 ///
27 /// # Returns
28 /// The inverse temperature in units where ℏ = kB = 1
29 fn beta(&self) -> f64;
30
31 /// Maximum frequency ωmax
32 ///
33 /// The basis functions are designed to accurately represent
34 /// spectral functions with support in [-ωmax, ωmax].
35 ///
36 /// # Returns
37 /// The maximum frequency cutoff
38 fn wmax(&self) -> f64;
39
40 /// Kernel parameter Λ = β × ωmax
41 ///
42 /// This is the dimensionless parameter that controls the basis.
43 ///
44 /// # Returns
45 /// The dimensionless parameter Λ
46 fn lambda(&self) -> f64 {
47 self.beta() * self.wmax()
48 }
49
50 /// Number of basis functions
51 ///
52 /// # Returns
53 /// The size of the basis (number of basis functions)
54 fn size(&self) -> usize;
55
56 /// Accuracy of the basis
57 ///
58 /// Upper bound to the relative error of representing a propagator
59 /// with the given number of basis functions.
60 ///
61 /// # Returns
62 /// A number between 0 and 1 representing the accuracy
63 fn accuracy(&self) -> f64;
64
65 /// Significance of each basis function
66 ///
67 /// Returns a vector where `σ[i]` (0 ≤ σ[i] ≤ 1) is the significance
68 /// level of the i-th basis function. If ε is the desired accuracy,
69 /// then any basis function where σ[i] < ε can be neglected.
70 ///
71 /// For the IR basis: σ[i] = s[i] / s[0]
72 /// For the DLR basis: σ[i] = 1.0 (all poles equally significant)
73 ///
74 /// # Returns
75 /// Vector of significance values for each basis function
76 fn significance(&self) -> Vec<f64>;
77
78 /// Get singular values (non-normalized)
79 ///
80 /// Returns the singular values S_l of the basis in physical units; for
81 /// `FiniteTempBasis`, S_l = sqrt(β ωmax/2) ωmax^ypower s_l with s_l those of
82 /// the SVE.
83 /// These are the absolute values, not normalized by s[0].
84 ///
85 /// # Returns
86 /// Vector of singular values
87 fn svals(&self) -> Vec<f64>;
88
89 /// Get default tau sampling points
90 ///
91 /// Returns sampling points in imaginary time τ ∈ [-β/2, β/2].
92 /// These are chosen to provide near-optimal conditioning of the
93 /// sampling matrix.
94 ///
95 /// # Returns
96 /// Vector of tau sampling points
97 ///
98 /// # Errors
99 ///
100 /// [`Error::NotSupported`] if the basis has no default tau sampling points,
101 /// e.g. an IR basis whose SVE has too few singular functions (see
102 /// `FiniteTempBasis::default_tau_sampling_points`)
103 fn default_tau_sampling_points(&self) -> Result<Vec<f64>, Error>;
104
105 /// Get default Matsubara sampling points
106 ///
107 /// Returns sampling points in Matsubara frequency space.
108 /// These are chosen to provide near-optimal conditioning.
109 ///
110 /// # Arguments
111 /// * `positive_only` - If true, only return non-negative frequencies
112 ///
113 /// # Returns
114 /// Vector of Matsubara frequency sampling points
115 ///
116 /// # Errors
117 ///
118 /// [`Error::NotSupported`] if the basis is a DLR (use the points of its IR
119 /// basis), or its basis functions have no definite parity (an SVE that is
120 /// not centrosymmetric, #183)
121 fn default_matsubara_sampling_points(
122 &self,
123 positive_only: bool,
124 ) -> Result<Vec<MatsubaraFreq<S>>, Error>
125 where
126 S: 'static;
127
128 /// Evaluate basis functions at imaginary time points
129 ///
130 /// Computes the value of basis functions at given τ points.
131 /// For IR basis: u_l(τ)
132 /// For DLR basis: the pole functions u_p(τ), one column per pole
133 ///
134 /// # Arguments
135 /// * `tau` - Imaginary time points τ ∈ [-β, β]; negative τ uses the
136 /// (anti)periodicity of the statistics
137 ///
138 /// # Returns
139 /// Matrix of shape [tau.len(), self.size()] where result[i, l] = u_l(τ_i)
140 ///
141 /// An empty `tau` gives a `[0, size]` matrix.
142 ///
143 /// # Errors
144 ///
145 /// [`Error::OutOfDomain`] if a τ is outside [-β, β] or NaN; no value is
146 /// computed then.
147 fn evaluate_tau(&self, tau: &[f64]) -> Result<crate::Matrix<f64>, Error>;
148
149 /// Evaluate basis functions at Matsubara frequencies
150 ///
151 /// Computes the value of basis functions at given Matsubara frequencies.
152 /// For IR basis: û_l(iν)
153 /// For DLR basis: basis functions in Matsubara space
154 ///
155 /// # Arguments
156 /// * `freqs` - Matsubara frequencies
157 ///
158 /// # Returns
159 /// Matrix of shape [freqs.len(), self.size()] where result[i, l] = û_l(iν_i)
160 ///
161 /// An empty `freqs` gives a `[0, size]` matrix.
162 ///
163 /// # Errors
164 ///
165 /// Implementors may return errors. The bases of this crate
166 /// (`FiniteTempBasis` and `DiscreteLehmannRepresentation`)
167 /// never do: every `MatsubaraFreq<S>` has the parity of the statistics, so
168 /// every frequency can be evaluated.
169 fn evaluate_matsubara(
170 &self,
171 freqs: &[MatsubaraFreq<S>],
172 ) -> Result<crate::Matrix<num_complex::Complex<f64>>, Error>
173 where
174 S: 'static;
175
176 /// Evaluate spectral basis functions at real frequencies
177 ///
178 /// Computes the value of spectral basis functions at given real frequencies.
179 /// For IR basis: V_l(ω)
180 /// Not supported for the DLR basis (see Errors)
181 ///
182 /// # Arguments
183 /// * `omega` - Real frequency points in [-ωmax, ωmax]
184 ///
185 /// # Returns
186 /// Matrix of shape [omega.len(), self.size()] where result[i, l] = V_l(ω_i)
187 ///
188 /// An empty `omega` gives a `[0, size]` matrix.
189 ///
190 /// # Errors
191 ///
192 /// * [`Error::OutOfDomain`] if an ω is outside [-ωmax, ωmax] or NaN
193 /// * [`Error::NotSupported`] for the DLR basis
194 fn evaluate_omega(&self, omega: &[f64]) -> Result<crate::Matrix<f64>, Error>;
195
196 /// Get default omega (real frequency) sampling points
197 ///
198 /// Returns sampling points on the real-frequency axis ω ∈ [-ωmax, ωmax].
199 /// These are used as pole locations for the Discrete Lehmann Representation (DLR).
200 ///
201 /// The sampling points are chosen as the roots/extrema of the L-th basis function
202 /// in the spectral domain, providing near-optimal conditioning.
203 ///
204 /// # Returns
205 /// Vector of real-frequency sampling points in [-ωmax, ωmax]
206 ///
207 /// # Errors
208 ///
209 /// [`Error::NotSupported`] if the basis is an IR basis whose SVE has too
210 /// few singular functions (the DLR returns its poles)
211 fn default_omega_sampling_points(&self) -> Result<Vec<f64>, Error>;
212}