|
293 | 293 |
|
294 | 294 | # This dispatch is needed based on how Terminating Callback works!
|
295 | 295 | # This intentially drops the `abstol` and `reltol` arguments
|
296 |
| -function (cache::NonlinearTerminationModeCache)(integrator::DiffEqBase.AbstractODEIntegrator, |
| 296 | +function (cache::NonlinearTerminationModeCache)(integrator::SciMLBase.AbstractODEIntegrator, |
297 | 297 | abstol::Number, reltol::Number, min_t)
|
298 | 298 | retval = cache(cache.mode, get_du(integrator), integrator.u, integrator.uprev)
|
299 | 299 | (min_t === nothing || integrator.t ≥ min_t) && return retval
|
|
517 | 517 |
|
518 | 518 | NONLINEARSOLVE_DEFAULT_NORM(u) = norm(u)
|
519 | 519 | NONLINEARSOLVE_DEFAULT_NORM(f::F, u) where {F} = norm(f.(u))
|
| 520 | + |
| 521 | +@inline __fast_scalar_indexing(args...) = all(ArrayInterface.fast_scalar_indexing, args) |
| 522 | + |
| 523 | +@inline __maximum_abs(op::F, x, y) where {F} = __maximum(abs ∘ op, x, y) |
| 524 | +## Nonallocating version of maximum(op.(x, y)) |
| 525 | +@inline function __maximum(op::F, x, y) where {F} |
| 526 | + if __fast_scalar_indexing(x, y) |
| 527 | + return maximum(@closure((xᵢyᵢ)->begin |
| 528 | + xᵢ, yᵢ = xᵢyᵢ |
| 529 | + return op(xᵢ, yᵢ) |
| 530 | + end), zip(x, y)) |
| 531 | + else |
| 532 | + return mapreduce(@closure((xᵢ, yᵢ)->op(xᵢ, yᵢ)), max, x, y) |
| 533 | + end |
| 534 | +end |
| 535 | + |
| 536 | +@inline function __norm_op(::typeof(Base.Fix2(norm, 2)), op::F, x, y) where {F} |
| 537 | + if __fast_scalar_indexing(x, y) |
| 538 | + return sqrt(sum(@closure((xᵢyᵢ)->begin |
| 539 | + xᵢ, yᵢ = xᵢyᵢ |
| 540 | + return op(xᵢ, yᵢ)^2 |
| 541 | + end), zip(x, y))) |
| 542 | + else |
| 543 | + return sqrt(mapreduce(@closure((xᵢ, yᵢ)->(op(xᵢ, yᵢ)^2)), +, x, y)) |
| 544 | + end |
| 545 | +end |
| 546 | + |
| 547 | +@inline __norm_op(norm::N, op::F, x, y) where {N, F} = norm(op.(x, y)) |
| 548 | + |
| 549 | +function __nonlinearsolve_is_approx(x::Number, y::Number; atol = false, |
| 550 | + rtol = atol > 0 ? false : sqrt(eps(promote_type(typeof(x), typeof(y))))) |
| 551 | + return isapprox(x, y; atol, rtol) |
| 552 | +end |
| 553 | +function __nonlinearsolve_is_approx(x, y; atol = false, |
| 554 | + rtol = atol > 0 ? false : sqrt(eps(promote_type(eltype(x), eltype(y))))) |
| 555 | + length(x) != length(y) && return false |
| 556 | + d = __maximum_abs(-, x, y) |
| 557 | + return d ≤ max(atol, rtol * max(maximum(abs, x), maximum(abs, y))) |
| 558 | +end |
| 559 | + |
| 560 | +@inline function __add_and_norm(::Nothing, x, y) |
| 561 | + Base.depwarn("Not specifying the internal norm of termination conditions has been \ |
| 562 | + deprecated. Using inf-norm currently.", |
| 563 | + :__add_and_norm) |
| 564 | + return __maximum_abs(+, x, y) |
| 565 | +end |
| 566 | +@inline __add_and_norm(::typeof(Base.Fix1(maximum, abs)), x, y) = __maximum_abs(+, x, y) |
| 567 | +@inline __add_and_norm(::typeof(Base.Fix2(norm, Inf)), x, y) = __maximum_abs(+, x, y) |
| 568 | +@inline __add_and_norm(f::F, x, y) where {F} = __norm_op(f, +, x, y) |
0 commit comments