|
| 1 | +function fine_ωGrid_test(Λ::Float, degree, ratio::Float) where {Float} |
| 2 | + ############## use composite grid ############################################# |
| 3 | + N = Int(floor(log(Λ) / log(ratio) + 1)) |
| 4 | + |
| 5 | + grid = CompositeGrid.LogDensedGrid( |
| 6 | + :cheb,# The top layer grid is :gauss, optimized for integration. For interpolation use :cheb |
| 7 | + [0.0, Λ],# The grid is defined on [0.0, β] |
| 8 | + [0.0,],# and is densed at 0.0 and β, as given by 2nd and 3rd parameter. |
| 9 | + N,# N of log grid |
| 10 | + Λ / ratio^(N - 1), # minimum interval length of log grid |
| 11 | + degree, # N of bottom layer |
| 12 | + Float |
| 13 | + ) |
| 14 | + |
| 15 | + return grid |
| 16 | + #return vcat(-grid[end:-1:1], grid) |
| 17 | +end |
| 18 | + |
| 19 | +function fine_τGrid_test(Λ::Float,degree,ratio::Float) where {Float} |
| 20 | + ############## use composite grid ############################################# |
| 21 | + # Generating a log densed composite grid with LogDensedGrid() |
| 22 | + npo = Int(ceil(log(Λ) / log(ratio))) - 2 # subintervals on [0,1/2] in tau space (# subintervals on [0,1] is 2*npt) |
| 23 | + grid = CompositeGrid.LogDensedGrid( |
| 24 | + :gauss,# The top layer grid is :gauss, optimized for integration. For interpolation use :cheb |
| 25 | + [0.0, 1.0],# The grid is defined on [0.0, β] |
| 26 | + [0.0, 1.0],# and is densed at 0.0 and β, as given by 2nd and 3rd parameter. |
| 27 | + npo,# N of log grid |
| 28 | + 0.5 / ratio^(npo-1), # minimum interval length of log grid |
| 29 | + degree, # N of bottom layer |
| 30 | + Float |
| 31 | + ) |
| 32 | + #print(grid[1:length(grid)÷2+1]) |
| 33 | + #print(grid+reverse(grid)) |
| 34 | + # println("Composite expoential grid size: $(length(grid))") |
| 35 | + println("fine grid size: $(length(grid)) within [$(grid[1]), $(grid[end])]") |
| 36 | + return grid |
| 37 | + |
| 38 | +end |
| 39 | + |
| 40 | +@inline function A1(L::T) where {T} |
| 41 | + |
| 42 | + return T(2 * expinti(-L) - 2 * expinti(-2 * L) - exp(-2 * L) * (exp(L) - 1)^2 / L) |
| 43 | + |
| 44 | +end |
| 45 | + |
| 46 | +@inline function A2(a::T, beta::T, L::T) where {T} |
| 47 | + |
| 48 | + return T(expinti(-a * L) - expinti(-(a + beta) * L)) |
| 49 | + #return T(-shi(a * L) + shi((a + 1) * L)) |
| 50 | +end |
| 51 | + |
| 52 | +""" |
| 53 | +``F(x, y) = (1-exp(x+y))/(x+y)`` |
| 54 | +""" |
| 55 | +@inline function A3(a::T, b::T, L::T) where {T} |
| 56 | + lamb = (a + b) * L |
| 57 | + if abs(lamb) > Tiny |
| 58 | + return (1 - exp(-lamb)) / (a + b) |
| 59 | + else |
| 60 | + return T(L * (1 - lamb / 2.0 + lamb^2 / 6.0 - lamb^3 / 24.0)) |
| 61 | + end |
| 62 | +end |
| 63 | + |
| 64 | +function uni_ngrid( isFermi, Λ::Float) where {Float} |
| 65 | + ngrid = Float[] |
| 66 | + n = 0 |
| 67 | + while (2n+1)*π<Λ |
| 68 | + append!(ngrid, n) |
| 69 | + n += 1 |
| 70 | + end |
| 71 | + if isFermi |
| 72 | + return vcat(-ngrid[end:-1:1] .-1, ngrid) |
| 73 | + else |
| 74 | + return vcat(-ngrid[end:-1:2], ngrid) |
| 75 | + end |
| 76 | +end |
| 77 | + |
| 78 | +function find_closest_indices(a, b) |
| 79 | + closest_indices = [] |
| 80 | + for i in 1:length(b) |
| 81 | + min_diff = Inf |
| 82 | + closest_idx = 0 |
| 83 | + for j in 1:length(a) |
| 84 | + diff = abs(a[j] - b[i]) |
| 85 | + if diff < min_diff |
| 86 | + min_diff = diff |
| 87 | + closest_idx = j |
| 88 | + end |
| 89 | + end |
| 90 | + push!(closest_indices, closest_idx) |
| 91 | + end |
| 92 | + return closest_indices |
| 93 | +end |
| 94 | + |
| 95 | +function Freq2Index(isFermi, ωnList) |
| 96 | + if isFermi |
| 97 | + # ωn=(2n+1)π |
| 98 | + return [Int(round((ωn / π - 1) / 2)) for ωn in ωnList] |
| 99 | + else |
| 100 | + # ωn=2nπ |
| 101 | + return [Int(round(ωn / π / 2)) for ωn in ωnList] |
| 102 | + end |
| 103 | +end |
| 104 | +function nGrid_test(isFermi, Λ::Float, degree, ratio::Float) where {Float} |
| 105 | + # generate n grid from a logarithmic fine grid |
| 106 | + np = Int(round(log(10*10 *10*Λ) / log(ratio))) |
| 107 | + xc = [(i - 1) / degree for i = 1:degree] |
| 108 | + panel = [ratio^(i - 1) - 1 for i = 1:(np+1)] |
| 109 | + nGrid = zeros(Int, np * degree) |
| 110 | + for i = 1:np |
| 111 | + a, b = panel[i], panel[i+1] |
| 112 | + nGrid[(i-1)*degree+1:i*degree] = Freq2Index(isFermi, a .+ (b - a) .* xc) |
| 113 | + end |
| 114 | + unique!(nGrid) |
| 115 | + #return nGrid |
| 116 | + if isFermi |
| 117 | + return vcat(-nGrid[end:-1:1] .-1, nGrid) |
| 118 | + else |
| 119 | + return vcat(-nGrid[end:-1:2], nGrid) |
| 120 | + end |
| 121 | +end |
| 122 | + |
| 123 | +function find_indices_optimized(a, b) |
| 124 | + indices = [] |
| 125 | + for i in 1:length(b) |
| 126 | + for j in 1:length(a) |
| 127 | + if abs(b[i] - a[j])<1e-16 |
| 128 | + push!(indices, j) |
| 129 | + break |
| 130 | + end |
| 131 | + end |
| 132 | + end |
| 133 | + return indices |
| 134 | +end |
| 135 | + |
| 136 | +function ωQR(kernel, rtol, print::Bool = true) |
| 137 | + # print && println(τ.grid[end], ", ", τ.panel[end]) |
| 138 | + # print && println(ω.grid[end], ", ", ω.panel[end]) |
| 139 | + ################# find the rank ############################## |
| 140 | + """ |
| 141 | + For a given index k, decompose R=[R11, R12; 0, R22] where R11 is a k×k matrix. |
| 142 | + If R11 is well-conditioned, then |
| 143 | + σᵢ(R11) ≤ σᵢ(kernel) for 1≤i≤k, and |
| 144 | + σⱼ(kernel) ≤ σⱼ₋ₖ(R22) for k+1≤j≤N |
| 145 | + See Page 487 of the book: Golub, G.H. and Van Loan, C.F., 2013. Matrix computations. 4th. Johns Hopkins. |
| 146 | + Thus, the effective rank is defined as the minimal k that satisfy rtol≤ σ₁(R22)/σ₁(kernel) |
| 147 | + """ |
| 148 | + Nτ, Nω = size(kernel) |
| 149 | + |
| 150 | + u, σ, v = svd(kernel) |
| 151 | + rank, err = 1, 0.0 |
| 152 | + for (si, s) in enumerate(σ) |
| 153 | + # println(si, " => ", s / σ[1]) |
| 154 | + if s / σ[1] < rtol |
| 155 | + rank = si - 1 |
| 156 | + err = s[1] / σ[1] |
| 157 | + break |
| 158 | + end |
| 159 | + end |
| 160 | + print && println("Kernel ϵ-rank = ", rank, ", rtol ≈ ", err) |
| 161 | + |
| 162 | + Q, R, p = qr(kernel, Val(true)) # julia qr has a strange design, Val(true) will do a pivot QR |
| 163 | + # size(R) == (Nτ, Nω) if Nω>Nτ |
| 164 | + # or size(R) == (Nω, Nω) if Nω<Nτ |
| 165 | + |
| 166 | + for idx = rank:min(Nτ, Nω) |
| 167 | + if Nω > Nτ |
| 168 | + R22 = R[idx:Nτ, idx:Nω] |
| 169 | + else |
| 170 | + R22 = R[idx:Nω, idx:Nω] |
| 171 | + end |
| 172 | + u2, s2, v2 = svd(R22) |
| 173 | + # println(idx, " => ", s2[1] / σ[1]) |
| 174 | + if s2[1] / σ[1] < rtol |
| 175 | + rank = idx |
| 176 | + err = s2[1] / σ[1] |
| 177 | + break |
| 178 | + end |
| 179 | + end |
| 180 | + print && println("DLR rank = ", rank, ", rtol ≈ ", err) |
| 181 | + |
| 182 | + # @assert err ≈ 4.58983288255442e-13 |
| 183 | + |
| 184 | + return p[1:rank] |
| 185 | +end |
0 commit comments