Skip to content
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

Incorrect integration results depending on integration bounds, using quadgk directly works #85

Closed
cpf-work opened this issue Jun 15, 2022 · 1 comment
Assignees

Comments

@cpf-work
Copy link

cpf-work commented Jun 15, 2022

This comes from obtaining electron densities in a density of states given a chemical potential eta. Here's a MWE which shows the issue

using Integrals
using QuadGK
using Plots

function integrand(E::Real, eta::Real)
    return exp(-E^2/2) / (sqrt(2π) * (exp(E-eta) + 1))
end

function using_quadgk(eta::Real, lim::Real)
    iq(x) = integrand(x, eta)
    res, err = quadgk(iq, -lim, lim)
    return res
end

function using_integrals(eta::Real, lim::Real)
    ip = IntegralProblem(integrand, -lim, lim, eta)
    return solve(ip, QuadGKJL())[1]
end

er = LinRange(-30, 2, 200)
lim = 100
plot(er, using_quadgk.(er, lim), yscale=:log10, label="QuadGK")
plot!(er, using_integrals.(er, lim), yscale=:log10, label="Integrals")

lim100

lim = 1000
plot(er, using_quadgk.(er, lim), yscale=:log10, label="QuadGK")
plot!(er, using_integrals.(er, lim), yscale=:log10, label="Integrals")

lim1000

The function should be smooth, so the calculation from Integrals.jl doesn't make sense. I've also tested other solver algorithms, but they give me also wrong results in varying degree.

Julia 1.6.6
Integrals v3.0.2

@cpf-work cpf-work changed the title Incorrect integration results depending on integration bounds, using quadqk directly works Incorrect integration results depending on integration bounds, using quadgk directly works Jun 16, 2022
@ArnoStrouwen
Copy link
Member

It is because the tolerances default to different values.
This works:

using Integrals
using QuadGK
using Plots

function integrand(E::Real, eta::Real)
    return exp(-E^2/2) / (sqrt(2π) * (exp(E-eta) + 1))
end

function using_quadgk(eta::Real, lim::Real)
    iq(x) = integrand(x, eta)
    res, err = quadgk(iq, -lim, lim)
    return res
end

function using_integrals(eta::Real, lim::Real)
    ip = IntegralProblem(integrand, -lim, lim, eta)
    return solve(ip, QuadGKJL();abstol=0.0)[1]
end

er = LinRange(-30, 2, 200)
lim = 100
plot(er, using_quadgk.(er, lim), yscale=:log10, label="QuadGK");
plot!(er, using_integrals.(er, lim), yscale=:log10, label="Integrals")

It is not unsurprising that the integral evaluates wrongly when it is a very small number unless you put the abstol to also be incredibly small.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants