You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Julia is column-major; make sure innermost loop indices appear first in slice expressions (https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-column-major)
τs =collect(τs) # force array to avoid floating point errors with ranges in following χs due to (e.g. tiny negative χ)
99
103
χs = τs[end] .- τs
100
-
Is =similar(Ss, length(ks), length(ls))
104
+
halfdτs =0.5.* (τs[begin+1:end] .- τs[begin:end-1]) # precompute before loops
105
+
NS =size(Ss, 1)
106
+
Is =zeros(eltype(Ss), NS, length(ks), length(ls))
101
107
102
108
verbose && l_limber <typemax(Int) &&println("Using Limber approximation for l ≥ $l_limber")
103
109
104
110
#TODO: skip and set jl to zero if l ≳ kτ0 or another cutoff?
105
111
@tasksfor il ineachindex(ls) # parallellize independent loop iterations
106
112
@localbegin# define task-local values (declared once for all loop iterations)
107
-
∂I_∂τ =similar(Ss, length(τs))
113
+
prevs =similar(Ss, NS)
114
+
_Is =similar(Ss, NS)
108
115
end
116
+
@inboundsbegin
109
117
l = ls[il]
110
118
verbose &&print("\rLOS integrating with l = $l")
111
119
for ik ineachindex(ks)
@@ -114,26 +122,39 @@ function los_integrate(Ss::AbstractMatrix{T}, ls::AbstractVector, τs::AbstractV
114
122
χ = (l+1/2) / k
115
123
if χ > χs[1]
116
124
# χ > χini > χrec, so source function is definitely zero
117
-
S =0.0
125
+
for iS in1:NS
126
+
_Is[iS] =0.0
127
+
end
118
128
else
119
129
# interpolate between two closest points in saved array
120
130
iχ₋ =searchsortedfirst(χs, χ; rev =true)
121
131
iχ₊ = iχ₋ -1
122
132
χ₋, χ₊ = χs[iχ₋], χs[iχ₊] # now χ₋ < χ < χ₊
123
-
S₋, S₊ = Ss[iχ₋,ik], Ss[iχ₊,ik]
124
-
S = S₋ + (S₊-S₋) * (χ-χ₋) / (χ₊-χ₋)
133
+
@inbounds@simdfor iS in1:NS
134
+
S₋, S₊ = Ss[iS, iχ₋, ik], Ss[iS, iχ₊, ik]
135
+
S = S₋ + (S₊-S₋) * (χ-χ₋) / (χ₊-χ₋)
136
+
_Is[iS] =√(π/(2l+1)) * S / k
137
+
end
125
138
end
126
-
I =√(π/(2l+1)) * S / k
127
139
else
128
-
for iτ ineachindex(τs)
129
-
S = Ss[iτ,ik]
140
+
prevs .= .0# jl = 0 when χ = 0
141
+
_Is .=0.0
142
+
for iτ inlength(τs)-1:-1:1
130
143
χ = χs[iτ]
131
-
kχ = k * χ
132
-
∂I_∂τ[iτ] = S *jl(l, kχ) #TODO: rewrite LOS integral to avoid evaluating Rl with dual numbers? # TODO: rewrite LOS integral with y = kτ0 and x=τ/τ0 to cache jls independent of cosmology
144
+
_jl =jl(l, k*χ)
145
+
halfdτ = halfdτs[iτ]
146
+
@inbounds@simdfor iS in1:NS
147
+
prev = prevs[iS]
148
+
curr = Ss[iS, iτ, ik] * _jl
149
+
_Is[iS] += halfdτ * (curr + prev)
150
+
prevs[iS] = curr
151
+
end
133
152
end
134
-
I =integrate(τs, ∂I_∂τ; integrator) # integrate over τ # TODO: add starting I(τini) to fix small l?
135
153
end
136
-
Is[ik,il] = I
154
+
for iS in1:NS
155
+
Is[iS, ik, il] = _Is[iS]
156
+
end
157
+
end
137
158
end
138
159
end
139
160
verbose &&println()
@@ -257,14 +278,15 @@ function spectrum_cmb(modes::AbstractVector{<:Symbol}, prob::CosmologyProblem, j
257
278
Ss_fine[:, end, :] .=0.0# can be Inf, but is always weighted by zero-valued spherical Bessel function in LOS integration
0 commit comments