Skip to content

Commit

Permalink
Add verbose option to solvers
Browse files Browse the repository at this point in the history
  • Loading branch information
gerlero committed Dec 17, 2023
1 parent 8c8a684 commit 5fdb3f2
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/ParamEstim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

"""
Expand Down
12 changes: 8 additions & 4 deletions src/finite.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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.
---
Expand All @@ -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)"
Expand All @@ -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,
Expand Down Expand Up @@ -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

"""
Expand Down
26 changes: 17 additions & 9 deletions src/integration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
Expand All @@ -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.
Expand All @@ -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

Expand Down
34 changes: 27 additions & 7 deletions src/shooting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ end
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

"""
Expand All @@ -42,6 +42,7 @@ Solve the problem `prob`.
# 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.
Expand All @@ -51,7 +52,8 @@ See also: [`Solution`](@ref), [`BoltzmannODE`](@ref)
"""
function solve(prob::DirichletProblem, alg::BoltzmannODE = BoltzmannODE();
abstol = 1e-3,
maxiters = 100)
maxiters = 100,
verbose = true)
@argcheck abstol zero(abstol)
@argcheck maxiters 0

Expand All @@ -71,6 +73,9 @@ function solve(prob::DirichletProblem, alg::BoltzmannODE = BoltzmannODE();
@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"
end
return Solution(integrator.sol, prob, alg, _retcode = retcode, _niter = 0)
end

Expand All @@ -90,6 +95,9 @@ function solve(prob::DirichletProblem, alg::BoltzmannODE = BoltzmannODE();
end
end

if verbose
@warn "Maximum number of iterations reached without convergence"
end
return Solution(integrator.sol,
prob,
alg,
Expand All @@ -103,7 +111,8 @@ function _init(prob::FlowrateProblem, alg::BoltzmannODE; b, abstol)
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)
Expand All @@ -126,6 +135,7 @@ Solve the problem `prob`.
# 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.
Expand All @@ -135,7 +145,8 @@ See also: [`Solution`](@ref), [`BoltzmannODE`](@ref)
"""
function solve(prob::FlowrateProblem; alg::BoltzmannODE = BoltzmannODE(),
abstol = 1e-3,
maxiters = 100)
maxiters = 100,
verbose = true)
@argcheck abstol zero(abstol)
@argcheck maxiters 0

Expand All @@ -153,10 +164,16 @@ function solve(prob::FlowrateProblem; alg::BoltzmannODE = BoltzmannODE(),
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"
end
return Solution(integrator.sol,
prob,
alg,
_retcode = ReturnCode.Success,
_retcode = retcode,
_niter = 0)
end

Expand All @@ -174,6 +191,9 @@ function solve(prob::FlowrateProblem; alg::BoltzmannODE = BoltzmannODE(),
end
end

if verbose
@warn "Maximum number of iterations reached without convergence"
end
return Solution(integrator.sol,
prob,
alg,
Expand Down
13 changes: 2 additions & 11 deletions test/test_dirichlet.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 5fdb3f2

Please sign in to comment.