DifferentialEquations.jl icon indicating copy to clipboard operation
DifferentialEquations.jl copied to clipboard

Domain Errors and Log Transforms

Open azev77 opened this issue 3 years ago • 1 comments

It works for the following set of parameters:

using DifferentialEquations, Plots;
function ngm!(dX, X, θ, t)
    C, K          = X
    ρ, γ, z, α, δ = θ
    dC = ((α*z*(K^(α-1.0)) -δ - ρ)/(γ)) * (C)
    dK = z*K^(α) - δ*K - C
    dX .= (dC, dK)
end

α=0.20; γ=6.0; δ=0.25; z=1.0; ρ = δ*(α*γ-1.0)
K0 = 1.0; C0 = (1-(1/γ))*z*(K0)^α;

X0 = [C0, K0]
tspan = (0.0, 2.0)
θ = [ρ, γ, z, α, δ]
prob = ODEProblem(ngm!, X0, tspan, θ)
sol = solve(prob)
plot(sol)

Problem 1: if I widen tspan it reports success but the solution is no longer accurate at all for large t. Incorrectly reporting a success is risky. Unless it's somehow within the tolerance...

tspan = (0.0, 100.0)                   # time span
prob = ODEProblem(ngm!, X0, tspan, θ) # problem
sol = solve(prob)
plot(sol, label=["C(t)" "K(t)"])
plot!([CSS KSS 0.0],  seriestype = :hline, lab=["CSS" "KSS" ""], color="grey", l=:dash)

Partial sol: adjusting the tolerance improves it (slower to solve), but it's still not good

tspan = (0.0, 100.0)                   # time span
prob = ODEProblem(ngm!, X0, tspan, θ) # problem
sol = solve(prob,reltol=1e-12)
plot(sol, label=["C(t)" "K(t)"])
plot!([CSS KSS 0.0],  seriestype = :hline, lab=["CSS" "KSS" ""], color="grey", l=:dash)

Main problem, when I increase α from 0.2 to 0.5 I get a DomainError

tspan = (0.0, 30.0) 
α=0.50; γ=6.0; δ=0.25; z=1.0; ρ = δ*(α*γ-1.0)
θ = [ρ, γ, z, α, δ]
prob = ODEProblem(ngm!, X0, tspan, θ) # problem

julia> sol = solve(prob)
ERROR: DomainError with -0.3526915679295306:
Exponentiation yielding a complex result requires a complex argument.
Replace x^y with (x+0im)^y, Complex(x)^y, or similar.
Stacktrace:
  [1] throw_exp_domainerror(x::Float64)
    @ Base.Math .\math.jl:37
  [2] ^
    @ .\math.jl:901 [inlined]
  [3] ngm!(dX::Vector{Float64}, X::Vector{Float64}, θ::Vector{Float64}, t::Float64)
    @ Main .\Untitled-1:6
  [4] ODEFunction
    @ C:\Users\azevelev\.julia\packages\SciMLBase\YasGG\src\scimlfunctions.jl:1624 [inlined]

The problem is the terms K^(α-1.0) and K^(α) in the DE. I believe this can be solved somehow w/ the transform exp(K) and then computing log of the solution to get back the original variable. Economists encounter these types of domain errors all the time. What are the best practices for doing this?

PS: I can eventually solve the problem w/ the new parameters in this simple problem, my point is I wanna know how to handle these issues in general.

azev77 avatar Aug 03 '22 17:08 azev77

Log transforms can make it numerically easier to stay positive. It's not automated so you'd have to do this by hand, for now, though there's work in MTK to do this.

https://diffeq.sciml.ai/stable/basics/faq/#My-ODE-goes-negative-but-should-stay-positive,-what-tools-can-help?

ChrisRackauckas avatar Aug 04 '22 15:08 ChrisRackauckas