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

Odd numerical instability in solving a nonlinear damped pendulum BVP collocation problem #38

Closed
00krishna opened this issue Aug 19, 2021 · 1 comment

Comments

@00krishna
Copy link

I notice an odd numerical instability in solving a simple nonlinear collocation problem. So the problem is taken from Toby Driscoll's book on numerical methods, chap 10, example 10.4.2. The equation is:

$θ'' + 0.05θ' + sinθ = 0$ with $θ(0) = 2.5, θ(8.0) = -2.0$.

The code is below. The problem is that the NonLinearSolve results are really inconsistent. I discretize the problem, but
sometimes the solver will give me the result, and other times the solver gives a Singular Matrix error. For example I might
discretize with 50 points and it gives me a Singular Matrix error, but with 49 points it gives me a solution. The numbers 49 and 50 are just make up for explanatory purposes. And the other odd thing is that sometimes at a given n, it will give a result and at other times it will either give the Singular Matrix error or just return a vector if Inf. So not sure what the issue is.

Here is the code.

using NonlinearSolve, BandedMatrices, ComponentArrays, Plots

function first_derivative_matrix(n, h)
    D = BandedMatrix{Float64}(undef, (n,n), (2,2))
    D[band(0)] .= 0
    D[band(1)] .= 0.5
    D[band(-1)] .= -0.5
    D[1, 1:3] = [-1.5, 2.0, -0.5]
    D[n, end-2:end] = [0.5, -2.0, 1.5]
    D = D/h   
end

function second_derivative_matrix(n, h)
    D = BandedMatrix{Float64}(undef, (n,n), (4,4))
    D[band(0)] .= -2.0
    D[band(1)] .= 1.0
    D[band(-1)] .= 1.0
    D[1, 1:4] = [2, -5, 4, -1]
    D[n, end-3:end] = [-1, 4, -5, 2]
    D = D/h^2   
end


function make_discrete(tspan, n)
    x = LinRange(tspan[1], tspan[2], n)
    h = (tspan[2] - tspan[1])/n
    return (x, h)
end

function objective(u, p)
    Dxx, Dx, h = p.Dxx, p.Dx, p.h
    f = Dxx*u .+ 0.05*Dx*u .+ sin.(u)
    f[1] = (u[1] - 2.5)/h^2
    f[end] = (u[end] + 2.0)/h^2
    return f
end

n = 100
tspan = (0.0, 8.0)
Θ,h = make_discrete(tspan, n)
Dx = first_derivative_matrix(n, h)
Dxx = second_derivative_matrix(n, h) 

p = ComponentArray(Dx = Dx, Dxx = Dxx, h = h) 

u0 = ones(n)
prob = NonlinearProblem{false}(objective, u0, p)
solver = solve(prob, NewtonRaphson(), tol=1e-8)

plot(Θ, solver)

Try n from a list of [10, 20, 30, 40], and at least one of them should give a solution and one of them should give Singular Matrix errors. Could this be a conditioning problem? In the objective function I divided f[1], f[end] the boundary condition by h^2 to improve the conditioning.

@00krishna
Copy link
Author

The issue just seems to be that Newton methods can diverge. So the solutions are to use a smaller time-step or h. Or you can use methods like trust-region newton or linesearch, according to @ChrisRackauckas .

avik-pal pushed a commit that referenced this issue Nov 1, 2024
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

1 participant