@@ -259,13 +259,10 @@ function _compute_estimate(
259259 # If we substitute `T.(coefs)` in the expression below, then allocations occur. We
260260 # therefore perform the broadcasting first. See
261261 # https://github.com/JuliaLang/julia/issues/39151.
262- _coefs = T .(coefs)
263- # NOTE the denominator: while doing T(step)^Q should technically be possible and correct,
264- # without flipping the order of ^ Q and T(), the current code crashes in _limit_step
265- # because of dimension mismatch. However, the output now has wrong units.
266262 #
267- # TODO : fix the output units. The numerical value is correct in a simple test.
268- return sum (fs .* _coefs) ./ T (step ^ Q)
263+ # We strip units because the estimate coefficients are just weights for values of f.
264+ _coefs = ustrip (T .(coefs))
265+ return sum (fs .* _coefs) ./ T (step) ^ Q
269266end
270267
271268# Check the method and derivative orders for consistency.
@@ -361,18 +358,27 @@ estimate of the derivative.
361358function estimate_step (
362359 m:: UnadaptedFiniteDifferenceMethod , f:: TF , x:: T ,
363360) where {TF,T<: Number }
364- step, acc = _compute_step_acc_default (m, x)
361+ step, acc = withUnit .(
362+ unit (x),
363+ _compute_step_acc_default (m, x) .* unit (x)
364+ )
365365 return _limit_step (m, x, step, acc)
366366end
367367function estimate_step (
368368 m:: AdaptedFiniteDifferenceMethod{P,Q} , f:: TF , x:: T ,
369369) where {P,Q,TF,T<: Number }
370- ∇f_magnitude, f_magnitude = _estimate_magnitudes (m. bound_estimator, f, x)
371- if ∇f_magnitude == 0.0 || f_magnitude == 0.0
372- step, acc = _compute_step_acc_default (m, x)
373- else
374- step, acc = _compute_step_acc (m, ∇f_magnitude, eps (f_magnitude))
375- end
370+ @show ∇f_magnitude, f_magnitude = _estimate_magnitudes (m. bound_estimator, f, x)
371+ step, acc = withUnit .(
372+ (
373+ unit (x),
374+ unit (f |> eltype) / unit (x) ^ Q
375+ ),
376+ if ∇f_magnitude == 0.0 || f_magnitude == 0.0
377+ _compute_step_acc_default (m, x)
378+ else
379+ _compute_step_acc (m, ∇f_magnitude, eps (f_magnitude))
380+ end
381+ )
376382 return _limit_step (m, x, step, acc)
377383end
378384
@@ -413,19 +419,26 @@ end
413419function _limit_step (
414420 m:: FiniteDifferenceMethod , x:: T , step:: Number , acc:: Number ,
415421) where {T<: Number }
422+ xunit = unit (x)
416423 # First, limit the step size based on the maximum range.
417- step_max = m. max_range / maximum (abs .(m. grid))
424+ step_max = withUnit (
425+ xunit,
426+ m. max_range / maximum (abs .(m. grid))
427+ )
418428 if step > step_max
419429 step = step_max
420- acc = NaN
430+ acc = withUnit (xunit, NaN )
421431 end
422432 # Second, prevent very large step sizes, which can occur for high-order methods or
423433 # slowly-varying functions.
424- step_default, _ = _compute_step_acc_default (m, x)
434+ step_default, _ = withUnit .(
435+ xunit,
436+ _compute_step_acc_default (m, x)
437+ )
425438 step_max_default = 1000 step_default
426439 if step > step_max_default
427440 step = step_max_default
428- acc = NaN
441+ acc = withUnit (xunit, NaN )
429442 end
430443 return step, acc
431444end
@@ -597,3 +610,21 @@ function extrapolate_fdm(
597610 kw_args...
598611 )
599612end
613+
614+ """
615+ Attaches a given unit to a given value, if it is dimensionless.
616+ If the value is not dimensionless, attempts a conversion to the given unit.
617+ """
618+ function withUnit (targetUnit, value)
619+
620+ if Unitful. dimension (value) == Unitful. NoDims
621+
622+ value .* targetUnit
623+
624+ else
625+
626+ Unitful. uconvert (targetUnit, value)
627+
628+ end # if
629+
630+ end # function
0 commit comments