-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Analyse too? #67
Comments
I don't have another article (yet), but I did dust off some notes/code I had lying around and I've pulled together the beginnings of the analysis code. See https://github.com/jmert/CMB.jl/compare/spharms?expand=1. Note that I haven't written all the tests I intend to yet, so it's very possible that there are some mistakes to be found yet. |
Many thanks that's fabulous! I'll have a look at it and will let you know once it's implemented. For SpeedyWeather.jl we need to write a bunch of tests anyway, I'll ping you here when they pass. |
Hey Justin, I've used your code as guideline to write a forward and backward spectral transform for SpeedyWeather.jl. This new spectral transform is developed in SpeedyWeather/SpeedyWeather.jl#38 (still looks horrible chaotic at the moment). I got the code all running and it's nice and fast too (60x faster than where we started from, as discussed in SpeedyWeather/SpeedyWeather.jl#32) but we still have some problems with spectral leakage, that means transforming back and forth, doesn't give you (up to rounding errors) exactly the same result. First thing, I realised that your code assumes equidistant latitudes (θ in your code) which you get from julia> alms = zeros(ComplexF64,32,32)
julia> alms[3,1] = 1 # only the l=2,m=0 harmonic
julia> map = gridded(alms) # uses Gaussian latitudes
julia> alms2 = spectral(map)
julia> alms2[3,1] # should be 1+0im
1.0111458144583563 + 0.0im Using equidistant latitudes this leakage is much reduced julia> alms2[3,1]
1.0008945580663524 + 0.0im However, it's still more than one would expect from rounding errors alone. Here's a plot showing absolute error in the coefficients after that back & forth transform So for l>2 and even and m=0 the error is much larger than it should be. It's similar at different resolutions (here we use lmax=mmax=31 and 96x48 grid points) but most leakage is across degrees not orders and reduces for larger orders (e.g. alms[3,3] = 1 yields a 1e-8 leakage not 1e-3). I was hoping you have some idea where this would come from. I'd appreciate any input in the mean time I'll try to find a solution to that in your blogposts. |
Sorry, I've only just understand that CMB.jl/src/sphericalharmonics.jl Line 226 in a9907df
for Gaussian latitudes one multiplies the f1,f2 with the legendre weight of that given latitude instead? Or does that also depend on the normalization? Related, in the synthesisCMB.jl/src/sphericalharmonics.jl Lines 171 to 172 in a9907df
How would these lines change with Gaussian latitudes? I'm not worried about the aliasing, as we'll run SpeedyWeather.jl always close to the triangular truncation, e.g. lmax=85 and a256x128 grid, hence we're below Nyquist frequencies (if I got this right). |
Okay, I think I got it. I changed the |
Glad to see you've worked out some of the issues before I've had a chance to respond. I'll still give some comments, though.
function analyze_ecp_iter(map::Matrix{R}, lmax::Integer, mmax::Integer = lmax) where {R<:Real}
n, m = size(map)
tol = sqrt(eps(maximum(abs, map)))
alms = analyze_ecp(map, lmax, mmax)
for ii in 2:10 # allow up to 10 iterations before bailing
map′ = synthesize_ecp(alms, n, m)
δmap = map - map′
# check for convergence
if maximum(abs, δmap) < tol
break
end
alms .+= analyze_ecp(δmap, lmax, mmax)
end
return alms
end This is actually an approach well-known in the CMB field — see mentions of iteration in https://healpix.jpl.nasa.gov/html/facilitiesnode7.htm |
Many thanks for the clarifications. For our application we are more than happy to just use the regular Gaussian grid. I didn't know you could iteratively increase the accuracy, unfortunately, this is at the moment a bit of an overkill for us. We're more looking towards having a 16-bit transform in the future. As long as the errors are unbiased and only scale with eps, we are (fingers crossed) fine. On that note, I know from you blog article that you've looked into numerical precision issues for the polynomials, but have you also thought about similar issues within the transform? E.g. one could for example change the order of the summation. |
I haven't thought as extensively about numerical issues in the SHT, but I've tried to keep at least an eye on not doing terrible things with the implementation either. For example, using the FFT probably does better than the naive multiplication by A domain-specific thing to think about is summing from lmax to 0 rather than 0 to lmax — the assumption here is that if your map/spectra are bandwidth limited by something like a beam function, the high-ell terms are smaller in magnitude than the low-ell terms, and if there are sufficiently many small high-ell terms, it's possible for their contributions to get dropped as round-off errors in the sum. In such a case, you can in theory eek out a bit more precision without having to resort to compensated summation by just summing from smallest-to-largest magnitude terms. FYI, there's now a Part II article on my website describing the analysis steps (which you've obviously already worked out). |
Yes, I thought about that. I won't investigate this now, but maybe once we are ready to run everything in Float32, we'll look into this. Reason why I'm asking is that eventually we would like to run the transform in 16-bit arithmetic if that could give us a reasonable speedup. But that obviously depends on many factors... Many thanks for Part II, I saw it already! Great work and very good to have that as a reference. |
If you're considering e.g. for a modest 80° latitude:
|
Closing this as both synthesis/analysis are available. |
Should be closed when #68 is merged. |
CMB.jl/src/sphericalharmonics.jl
Lines 170 to 174 in 2e467aa
Hey Justin, many thanks for all your blog articles and AssociatedLegendrePolynomials.jl, great work! We are currently working on SpeedyWeather.jl, a spectral model of the atmosphere. You may have guessed that it also uses a spectral transform, much like you've defined the
synthesize_*
functions here. We have inherited the numerics from a decade old Fortran model, but want to overhaul the implementation completely. As I have learned loads from your blog articles, especially the one on "Notes on Calculating the Spherical Harmonics" I was wondering whether you have already draft/intent to write a similar one for the analysis, i.e. the inverse transform to the synthesis you've excellently described?The text was updated successfully, but these errors were encountered: