Skip to content

Commit e1da4ea

Browse files
committed
Fix bug with NaNs from NLSolve
1 parent b63e8e1 commit e1da4ea

2 files changed

Lines changed: 50 additions & 2 deletions

File tree

src/KPS3.jl

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,31 @@ function find_steady_state_inner(s::KPS3, X, prn=false; delta=0.0)
511511
end
512512

513513
if prn println("\nStarted function test_nlsolve...") end
514-
results = nlsolve(test_initial_condition!, X, xtol=1e-6, ftol=1e-6, autoscale=true, iterations=1000)
514+
# Provide explicit Jacobian using central finite differences to work around
515+
# NLSolversBase >= 7.10 producing subnormal Jacobian entries via DifferentiationInterface,
516+
# which cause NaN in NLsolve autoscale (subnormal column norms squared underflow to zero).
517+
n_vars = length(X)
518+
_F1 = zeros(SimFloat, n_vars)
519+
_F2 = zeros(SimFloat, n_vars)
520+
_xp = zeros(SimFloat, n_vars)
521+
_xm = zeros(SimFloat, n_vars)
522+
function jac!(J, x)
523+
h_factor = cbrt(eps(SimFloat))
524+
for j in 1:n_vars
525+
copyto!(_xp, x)
526+
copyto!(_xm, x)
527+
h = max(abs(x[j]), one(SimFloat)) * h_factor
528+
_xp[j] += h
529+
_xm[j] -= h
530+
test_initial_condition!(_F1, _xp)
531+
test_initial_condition!(_F2, _xm)
532+
@views J[:, j] .= (_F1 .- _F2) ./ (2h)
533+
end
534+
# Flush near-zero entries whose squares would underflow, preventing NaN in autoscale
535+
threshold = sqrt(floatmin(SimFloat))
536+
@. J = ifelse(abs(J) < threshold, zero(SimFloat), J)
537+
end
538+
results = nlsolve(test_initial_condition!, jac!, X, xtol=1e-6, ftol=1e-6, autoscale=true, iterations=1000)
515539
if prn println("\nresult: $results") end
516540
results.zero
517541
end

src/KPS4.jl

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,31 @@ function find_steady_state!(s::KPS4; prn=false, delta = 0.01, stiffness_factor=0
686686
end
687687
if prn println("\nStarted function test_nlsolve...") end
688688
X00 = zeros(SimFloat, 2*(s.set.segments+KITE_PARTICLES-1)+2)
689-
results = nlsolve(test_initial_condition!, X00, autoscale=true, xtol=4e-7, ftol=4e-7, iterations=s.set.max_iter)
689+
# Provide explicit Jacobian using central finite differences to work around
690+
# NLSolversBase >= 7.10 producing subnormal Jacobian entries via DifferentiationInterface,
691+
# which cause NaN in NLsolve autoscale (subnormal column norms squared underflow to zero).
692+
n_vars = length(X00)
693+
_F1 = zeros(SimFloat, n_vars)
694+
_F2 = zeros(SimFloat, n_vars)
695+
_xp = zeros(SimFloat, n_vars)
696+
_xm = zeros(SimFloat, n_vars)
697+
function jac!(J, x)
698+
h_factor = cbrt(eps(SimFloat))
699+
for j in 1:n_vars
700+
copyto!(_xp, x)
701+
copyto!(_xm, x)
702+
h = max(abs(x[j]), one(SimFloat)) * h_factor
703+
_xp[j] += h
704+
_xm[j] -= h
705+
test_initial_condition!(_F1, _xp)
706+
test_initial_condition!(_F2, _xm)
707+
@views J[:, j] .= (_F1 .- _F2) ./ (2h)
708+
end
709+
# Flush near-zero entries whose squares would underflow, preventing NaN in autoscale
710+
threshold = sqrt(floatmin(SimFloat))
711+
@. J = ifelse(abs(J) < threshold, zero(SimFloat), J)
712+
end
713+
results = nlsolve(test_initial_condition!, jac!, X00, autoscale=true, xtol=4e-7, ftol=4e-7, iterations=s.set.max_iter)
690714
if prn println("\nresult: $results") end
691715
y0, yd0 = init(s, results.zero; upwind_dir)
692716
set_v_wind_ground!(s, calc_height(s), s.set.v_wind; upwind_dir)

0 commit comments

Comments
 (0)