Skip to content

Commit 055e4f6

Browse files
committed
Actually extremum boundary conditions
1 parent e279765 commit 055e4f6

File tree

6 files changed

+50
-39
lines changed

6 files changed

+50
-39
lines changed

docs/pages.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
pages = ["index.md",
44
"Getting Started with BVP solving in Julia" => "tutorials/getting_started.md",
5-
"Tutorials" => Any["tutorials/continuation.md",
6-
"tutorials/solve_nlls_bvp.md", "tutorials/inequality.md"],
5+
"Tutorials" => Any[
6+
"tutorials/continuation.md", "tutorials/solve_nlls_bvp.md", "tutorials/extremum.md"],
77
"Basics" => Any["basics/bvp_problem.md", "basics/bvp_functions.md",
88
"basics/solve.md", "basics/autodiff.md", "basics/error_control.md"],
99
"Solver Summaries and Recommendations" => Any[

docs/src/tutorials/extremum.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Solve BVP with Extremum Boundary Conditions
2+
3+
In many physical systems, boundary conditions are not always defined at fixed points such as intitial or terminal ends of the domain. Instead, we may encounter scenarios where constraints are imposed on the maximum or minimum values that the solution must attain somewhere within the domain. In such cases, we can use the `maxsol` and `minsol` functions provided by BoundaryValueDiffEq.jl to specify such extremum boundary conditions.
4+
5+
Let's walk through this functionality with an intuitive example. We still revisit the simple pendulum example here, but this time, suppose we need to impose the maximum and minimum value to our boundary conditions, specified as:
6+
7+
```math
8+
\max{u}=ub\\
9+
\min{u}=lb
10+
```
11+
12+
where `lb=-4.8161991710010925` and `ub=5.0496477654230745`. So the states must conform that the maximum value of the state should be `lb` while the minimum value of the state should be `ub`. To solve such problems, we can simply use the `maxsol` and `minsol` functions when defining the boundary value problem in BoundaryValueDiffEq.jl.
13+
14+
```@example inequality
15+
using BoundaryValueDiffEq, Plots
16+
tspan = (0.0, pi / 2)
17+
function simplependulum!(du, u, p, t)
18+
θ = u[1]
19+
dθ = u[2]
20+
du[1] = dθ
21+
du[2] = -9.81 * sin(θ)
22+
end
23+
function bc!(residual, u, p, t)
24+
residual[1] = maxsol(u, (0.0, pi / 2)) - 5.0496477654230745
25+
residual[2] = minsol(u, (0.0, pi / 2)) + 4.8161991710010925
26+
end
27+
prob = BVProblem(simplependulum!, bc!, [pi / 2, pi / 2], tspan)
28+
sol = solve(prob, MIRK4(), dt = 0.05)
29+
plot(sol)
30+
```

docs/src/tutorials/inequality.md

Lines changed: 0 additions & 29 deletions
This file was deleted.

lib/BoundaryValueDiffEqCore/src/default_nlsolve.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ function __FastShortcutBVPCompatibleNonlinearPolyalg(
3636
return NonlinearSolvePolyAlgorithm(algs)
3737
end
3838

39+
function __FastShortcutNonlinearPolyalg(::Type{T} = Float64; concrete_jac = nothing,
40+
linsolve = nothing, autodiff = nothing) where {T}
41+
if T <: Complex
42+
algs = (NewtonRaphson(; concrete_jac, linsolve, autodiff),)
43+
else
44+
algs = (NewtonRaphson(; concrete_jac, linsolve, autodiff),
45+
NewtonRaphson(; concrete_jac, linsolve, linesearch = BackTracking(), autodiff),
46+
TrustRegion(; concrete_jac, linsolve, autodiff))
47+
end
48+
return NonlinearSolvePolyAlgorithm(algs)
49+
end
50+
3951
@inline __concrete_nonlinearsolve_algorithm(prob, alg) = alg
4052
@inline function __concrete_nonlinearsolve_algorithm(prob, ::Nothing)
4153
if prob isa NonlinearLeastSquaresProblem

lib/BoundaryValueDiffEqMIRK/src/BoundaryValueDiffEqMIRK.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ using BoundaryValueDiffEqCore: AbstractBoundaryValueDiffEqAlgorithm,
2121
DefectControl, GlobalErrorControl, SequentialErrorControl,
2222
HybridErrorControl, HOErrorControl, __use_both_error_control,
2323
__default_coloring_algorithm, DiffCacheNeeded,
24-
NoDiffCacheNeeded, __split_kwargs
24+
NoDiffCacheNeeded, __split_kwargs,
25+
__FastShortcutNonlinearPolyalg
2526

2627
using ConcreteStructs: @concrete
2728
using DiffEqBase: DiffEqBase

lib/BoundaryValueDiffEqMIRK/src/interpolation.jl

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -193,21 +193,18 @@ function (s::EvalSol{C})(tval::Number, ::Type{Val{1}}) where {C <: MIRKCache}
193193
end
194194

195195
"""
196-
n root-finding problems to find the critical points with continuous derivative polynomials
196+
Construct n root-finding problems and solve them to find the critical points with continuous derivative polynomials
197197
"""
198198
function __construct_then_solve_root_problem(
199199
sol::EvalSol{C}, tspan::Tuple) where {C <: MIRKCache}
200200
(; alg) = sol.cache
201201
n = first(size(sol))
202-
nlprobs = Vector{NonlinearProblem}(undef, n)
202+
nlprobs = Vector{SciMLBase.NonlinearProblem}(undef, n)
203+
nlsols = Vector{SciMLBase.NonlinearSolution}(undef, length(nlprobs))
204+
nlsolve_alg = __FastShortcutNonlinearPolyalg(eltype(sol.cache))
203205
for i in 1:n
204206
f = @closure (t, p) -> sol(t, Val{1})[i]
205207
nlprob = NonlinearProblem(f, sol.cache.prob.u0[i], tspan)
206-
nlprobs[i] = nlprob
207-
end
208-
nlsols = Vector{SciMLBase.NonlinearSolution}(undef, length(nlprobs))
209-
nlsolve_alg = __concrete_nonlinearsolve_algorithm(first(nlprobs), alg.nlsolve)
210-
for (i, nlprob) in enumerate(nlprobs)
211208
nlsols[i] = solve(nlprob, nlsolve_alg)
212209
end
213210
return nlsols

0 commit comments

Comments
 (0)