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

Add verbose option to solvers #142

Merged
merged 1 commit into from
Dec 17, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add verbose option to solvers
gerlero committed Dec 17, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit b04fcd88a834da3f008e25d162b5fe27669388c0
2 changes: 1 addition & 1 deletion src/ParamEstim.jl
Original file line number Diff line number Diff line change
@@ -138,7 +138,7 @@ end
(cf::RSSCostFunction)(params::AbstractVector) = cf(candidate(cf, params))

_solve(cf::RSSCostFunction, params::AbstractVector) = _solve(cf, cf._func(params))
_solve(::RSSCostFunction, prob::Problem) = solve(prob)
_solve(::RSSCostFunction, prob::Problem) = solve(prob, verbose = false)
_solve(::RSSCostFunction, sol::Solution) = sol

"""
12 changes: 8 additions & 4 deletions src/finite.jl
Original file line number Diff line number Diff line change
@@ -161,6 +161,7 @@ Uses backward Euler time discretization and a second-order central difference sc

# Keyword arguments
- `abstol=1e-3`: nonlinear solver tolerance.
- `verbose=true`: whether warnings are emitted if solving is unsuccessful.

---

@@ -174,13 +175,15 @@ Solve the `DirichletProblem` `prob` with a finite-difference scheme.

# Keyword arguments
- `abstol=1e-3`: nonlinear solver tolerance.
- `verbose=true`: whether warnings are emitted if solving is unsuccessful.
"""
function solve(prob::Union{
DirichletProblem{<:DiffusionEquation{1}},
FiniteProblem{<:DiffusionEquation{1}},
},
alg::FiniteDifference;
abstol = 1e-3)
abstol = 1e-3,
verbose = true)
if prob isa DirichletProblem
@argcheck iszero(prob.ob) "FiniteDifference only supports fixed boundaries"
@argcheck isnothing(alg._pre) "pre not valid for a DirichletProblem (use BoltzmannODE directly instead)"
@@ -204,7 +207,8 @@ function solve(prob::Union{
prob.i isa Number
presol = solve(DirichletProblem(prob.eq, i = prob.i, b = prob.b),
alg._pre,
abstol = abstol)
abstol = abstol,
verbose = verbose)
if presol.retcode != ReturnCode.Success
θ .= prob.i
return FiniteSolution(r,
@@ -348,8 +352,8 @@ function solve(prob::Union{
end
end

function solve(prob::FiniteProblem{<:DiffusionEquation{1}}; abstol = 1e-3)
solve(prob, FiniteDifference(pre = BoltzmannODE()), abstol = abstol)
function solve(prob::FiniteProblem{<:DiffusionEquation{1}}; abstol = 1e-3, verbose = true)
solve(prob, FiniteDifference(pre = BoltzmannODE()), abstol = abstol, verbose = verbose)
end

"""
26 changes: 17 additions & 9 deletions src/integration.jl
Original file line number Diff line number Diff line change
@@ -55,7 +55,11 @@ monotonicity(odeprob::ODEProblem)::Int = sign(odeprob.u0[2])
const _ODE_ALG = RadauIIA5()
const _ODE_MAXITERS = 1000

function _init(odeprob::ODEProblem, alg::BoltzmannODE; i = nothing, abstol = 0)
function _init(odeprob::ODEProblem,
::BoltzmannODE;
i = nothing,
abstol = 0,
verbose = true)
if !isnothing(i)
direction = monotonicity(odeprob)

@@ -70,17 +74,18 @@ function _init(odeprob::ODEProblem, alg::BoltzmannODE; i = nothing, abstol = 0)
_ODE_ALG,
maxiters = _ODE_MAXITERS,
callback = past_limit,
verbose = false)
verbose = verbose)
end

return init(odeprob, _ODE_ALG, maxiters = _ODE_MAXITERS, verbose = false)
return init(odeprob, _ODE_ALG, maxiters = _ODE_MAXITERS, verbose = verbose)
end

function _init(prob::Union{CauchyProblem, SorptivityProblem},
alg::BoltzmannODE;
i = nothing,
abstol = 0)
_init(boltzmann(prob), alg, i = i, abstol = abstol)
abstol = 0,
verbose = true)
_init(boltzmann(prob), alg, i = i, abstol = abstol, verbose = verbose)
end

function _reinit!(integrator, prob::CauchyProblem)
@@ -96,15 +101,18 @@ function _reinit!(integrator, prob::SorptivityProblem)
end

"""
solve(prob::CauchyProblem[, alg::BoltzmannODE]) -> Solution
solve(prob::SorptivityProblem[, alg::BoltzmannODE]) -> Solution
solve(prob::CauchyProblem[, alg::BoltzmannODE; verbose]) -> Solution
solve(prob::SorptivityProblem[, alg::BoltzmannODE; verbose]) -> Solution

Solve the problem `prob`.

# Arguments
- `prob`: problem to solve.
- `alg=BoltzmannODE()`: algorithm to use.

# Keyword arguments
- `verbose=true`: whether warnings are emitted if solving is unsuccessful.

# References
GERLERO, G. S.; BERLI, C. L. A.; KLER, P. A. Open-source high-performance software packages for direct and inverse solving of horizontal capillary flow.
Capillarity, 2023, vol. 6, no. 2, p. 31-40.
@@ -113,8 +121,8 @@ See also: [`Solution`](@ref), [`BoltzmannODE`](@ref)
"""
function solve(prob::Union{CauchyProblem, SorptivityProblem},
alg::BoltzmannODE = BoltzmannODE();
abstol = 1e-3)
odesol = solve!(_init(prob, alg, abstol = abstol))
verbose = true)
odesol = solve!(_init(prob, alg, verbose = verbose))

@assert odesol.retcode != ReturnCode.Success

34 changes: 27 additions & 7 deletions src/shooting.jl
Original file line number Diff line number Diff line change
@@ -21,13 +21,13 @@
function _init(prob::DirichletProblem, alg::BoltzmannODE; d_dob, abstol)
return _init(CauchyProblem(prob.eq, b = prob.b, d_dob = d_dob, ob = prob.ob),
alg,
i = prob.i, abstol = abstol)
i = prob.i, abstol = abstol, verbose = false)
end

function _shoot!(integrator, prob::DirichletProblem; d_dob, abstol)
return _shoot!(integrator,
CauchyProblem(prob.eq, b = prob.b, d_dob = d_dob, ob = prob.ob),
i = prob.i, abstol = abstol)
CauchyProblem(prob.eq, b = prob.b, d_dob = d_dob, ob = prob.ob), i = prob.i,
abstol = abstol)
end

"""
@@ -42,6 +42,7 @@
# Keyword arguments
- `abstol=1e-3`: absolute tolerance for the initial condition.
- `maxiters=100`: maximum number of iterations.
- `verbose=true`: whether warnings are emitted if solving is unsuccessful.

# References
GERLERO, G. S.; BERLI, C. L. A.; KLER, P. A. Open-source high-performance software packages for direct and inverse solving of horizontal capillary flow.
@@ -51,7 +52,8 @@
"""
function solve(prob::DirichletProblem, alg::BoltzmannODE = BoltzmannODE();
abstol = 1e-3,
maxiters = 100)
maxiters = 100,
verbose = true)
@argcheck abstol ≥ zero(abstol)
@argcheck maxiters ≥ 0

@@ -71,6 +73,9 @@
@assert integrator.sol.retcode != ReturnCode.Success
retcode = integrator.sol.retcode == ReturnCode.Terminated ? ReturnCode.Success :
integrator.sol.retcode
if verbose && !SciMLBase.successful_retcode(integrator.sol)
@warn "Problem has a trivial solution but failed to obtain it"

Check warning on line 77 in src/shooting.jl

Codecov / codecov/patch

src/shooting.jl#L77

Added line #L77 was not covered by tests
end
return Solution(integrator.sol, prob, alg, _retcode = retcode, _niter = 0)
end

@@ -90,6 +95,9 @@
end
end

if verbose
@warn "Maximum number of iterations reached without convergence"
end
return Solution(integrator.sol,
prob,
alg,
@@ -103,7 +111,8 @@
return _init(SorptivityProblem(prob.eq, b = b, S = 2prob.Qb / prob._αh / ob, ob = ob),
alg,
i = prob.i,
abstol = abstol)
abstol = abstol,
verbose = false)
end

function _shoot!(integrator, prob::FlowrateProblem; b, abstol)
@@ -126,6 +135,7 @@
# Keyword arguments
- `abstol=1e-3`: absolute tolerance for the initial condition.
- `maxiters=100`: maximum number of iterations.
- `verbose=true`: whether warnings are emitted if solving is unsuccessful.

# References
GERLERO, G. S.; BERLI, C. L. A.; KLER, P. A. Open-source high-performance software packages for direct and inverse solving of horizontal capillary flow.
@@ -135,7 +145,8 @@
"""
function solve(prob::FlowrateProblem; alg::BoltzmannODE = BoltzmannODE(),
abstol = 1e-3,
maxiters = 100)
maxiters = 100,
verbose = true)
@argcheck abstol ≥ zero(abstol)
@argcheck maxiters ≥ 0

@@ -153,10 +164,16 @@
if monotonicity(prob) == 0
integrator, resid = _shoot!(integrator, prob, b = prob.i, abstol = abstol)
@assert iszero(resid)
@assert integrator.sol.retcode != ReturnCode.Success
retcode = integrator.sol.retcode == ReturnCode.Terminated ? ReturnCode.Success :
integrator.sol.retcode
if verbose && !SciMLBase.successful_retcode(integrator.sol)
@warn "Problem has a trivial solution but failed to obtain it"

Check warning on line 171 in src/shooting.jl

Codecov / codecov/patch

src/shooting.jl#L171

Added line #L171 was not covered by tests
end
return Solution(integrator.sol,
prob,
alg,
_retcode = ReturnCode.Success,
_retcode = retcode,
_niter = 0)
end

@@ -174,6 +191,9 @@
end
end

if verbose
@warn "Maximum number of iterations reached without convergence"

Check warning on line 195 in src/shooting.jl

Codecov / codecov/patch

src/shooting.jl#L194-L195

Added lines #L194 - L195 were not covered by tests
end
return Solution(integrator.sol,
prob,
alg,
13 changes: 2 additions & 11 deletions test/test_dirichlet.jl
Original file line number Diff line number Diff line change
@@ -121,17 +121,8 @@

@testset "unsolved" begin
prob = DirichletProblem(identity, i = 0, b = 1)
θ = solve(prob, maxiters = 0)
θ = @test_logs (:warn, "Maximum number of iterations reached without convergence") solve(prob,
maxiters = 0)
@test θ.retcode == ReturnCode.MaxIters
end

@testset "unsolvable" begin
prob = DirichletProblem(identity, i = -1e-3, b = 1)
θ = solve(prob)
@test_broken θ.retcode == ReturnCode.Unstable

prob = DirichletProblem(identity, i = 0, b = -1)
θ = solve(prob)
@test_broken θ.retcode == ReturnCode.Unstable
end
end