Here is an approximation tested with some typical values of a
, b
, and c
:
using QuadGK, BenchmarkTools
a = 0.0003
b = [1.0, 1.5, 2.3, 0.6]
c = 1.e-4 * b
function exact_integrand(t, a, b, c)
return exp(a*t) / sum(b[i] * exp(c[i]*t) for i in eachindex(b,c))
end
approx_exp(x) = 1 + x
function approx_integrand(t, a, b, c)
approx_exp(a*t) / sum(b[i] * approx_exp(c[i]*t) for i in eachindex(b,c))
end
If we plot the exact and approximate integrands we see the following:
The approximation looks very good and both traces appear to be simple linear functions. So we can try a one-point quadrature rule that samples the integrand at the center of the integration interval:
ts = 0:0.01:1
ints_exact = [quadgk(t -> exact_integrand(t,a,b,c), 0, t)[1] for t in ts]
ints_approx = [t * approx_integrand(t/2,a,b,c) for t in ts]
@show maximum(abs, (ints_exact - ints_approx))
which produces
maximum(abs, ints_exact - ints_approx) = 1.4760460631535466e-9
The timing for the approximate and exact integrands:
julia> @btime approx_integrand(0.95, $a, $b, $c)
7.800 ns (0 allocations: 0 bytes)
0.1852089640409081
julia> @btime exact_integrand(0.95, $a, $b, $c)
31.194 ns (0 allocations: 0 bytes)
0.1852089689678891