@@ -220,7 +220,7 @@ function LagrangeInterpolation(
220220end
221221
222222"""
223- AkimaInterpolation(u, t; extrapolation::ExtrapolationType.T = ExtrapolationType.None, extrapolation_left::ExtrapolationType.T = ExtrapolationType.None,
223+ AkimaInterpolation(u, t; modified = false, extrapolation::ExtrapolationType.T = ExtrapolationType.None, extrapolation_left::ExtrapolationType.T = ExtrapolationType.None,
224224 extrapolation_right::ExtrapolationType.T = ExtrapolationType.None, cache_parameters = false)
225225
226226It is a spline interpolation built from cubic polynomials. It forms a continuously differentiable function. For more details, refer: [https://en.wikipedia.org/wiki/Akima_spline](https://en.wikipedia.org/wiki/Akima_spline).
@@ -233,6 +233,11 @@ Extrapolation extends the last cubic polynomial on each side.
233233
234234## Keyword Arguments
235235
236+ - `modified`: if `true`, use the modified Akima (makima) formula for the slopes at the knots,
237+ which adds an extra term `|m_{i+1} + m_i| / 2` to each weight. Tends to reduce overshoot
238+ and oscillation on data with flat regions or repeated values. See
239+ [https://blogs.mathworks.com/cleve/2019/04/29/makima-piecewise-cubic-interpolation/](https://blogs.mathworks.com/cleve/2019/04/29/makima-piecewise-cubic-interpolation/).
240+ Defaults to `false`.
236241 - `extrapolation`: The extrapolation type applied left and right of the data. Possible options
237242 are `ExtrapolationType.None` (default), `ExtrapolationType.Constant`, `ExtrapolationType.Linear`
238243 `ExtrapolationType.Extension`, `ExtrapolationType.Periodic` and `ExtrapolationType.Reflective`.
@@ -284,7 +289,8 @@ struct AkimaInterpolation{uType, tType, IType, bType, cType, dType, T} <:
284289end
285290
286291function AkimaInterpolation (
287- u, t; extrapolation:: ExtrapolationType.T = ExtrapolationType. None,
292+ u, t; modified:: Bool = false ,
293+ extrapolation:: ExtrapolationType.T = ExtrapolationType. None,
288294 extrapolation_left:: ExtrapolationType.T = ExtrapolationType. None,
289295 extrapolation_right:: ExtrapolationType.T = ExtrapolationType. None, cache_parameters = false , assume_linear_t = 1.0e-2
290296 )
@@ -303,16 +309,30 @@ function AkimaInterpolation(
303309 m[end - 1 ] = 2 m[end - 2 ] - m[end - 3 ]
304310 m[end ] = 2 m[end - 1 ] - m[end - 2 ]
305311
306- b = (m[4 : end ] .+ m[1 : (end - 3 )]) ./ 2
307- dm = abs .(diff (m))
308- f1 = dm[3 : (n + 2 )]
309- f2 = dm[1 : n]
310- f12 = f1 + f2
311- ind = findall (f12 .> 1.0e-9 * maximum (f12))
312- b[ind] = (
313- f1[ind] .* m[ind .+ 1 ] .+
314- f2[ind] .* m[ind .+ 2 ]
315- ) ./ f12[ind]
312+ if modified
313+ # Modified Akima (makima): adds |m_{i+1} + m_i| / 2 to each weight, which
314+ # reduces overshoot on flat regions. The simple-average fallback still
315+ # guards the case where all four neighboring slopes vanish.
316+ w1 = abs .(m[4 : end ] .- m[3 : (end - 1 )]) .+
317+ abs .(m[4 : end ] .+ m[3 : (end - 1 )]) ./ 2
318+ w2 = abs .(m[2 : (end - 2 )] .- m[1 : (end - 3 )]) .+
319+ abs .(m[2 : (end - 2 )] .+ m[1 : (end - 3 )]) ./ 2
320+ w12 = w1 .+ w2
321+ b = (m[2 : (end - 2 )] .+ m[3 : (end - 1 )]) ./ 2
322+ ind = findall (w12 .> 1.0e-9 * maximum (w12))
323+ b[ind] = (w1[ind] .* m[ind .+ 1 ] .+ w2[ind] .* m[ind .+ 2 ]) ./ w12[ind]
324+ else
325+ b = (m[4 : end ] .+ m[1 : (end - 3 )]) ./ 2
326+ dm = abs .(diff (m))
327+ f1 = dm[3 : (n + 2 )]
328+ f2 = dm[1 : n]
329+ f12 = f1 + f2
330+ ind = findall (f12 .> 1.0e-9 * maximum (f12))
331+ b[ind] = (
332+ f1[ind] .* m[ind .+ 1 ] .+
333+ f2[ind] .* m[ind .+ 2 ]
334+ ) ./ f12[ind]
335+ end
316336 c = (3 .* m[3 : (end - 2 )] .- 2 .* b[1 : (end - 1 )] .- b[2 : end ]) ./ dt
317337 d = (b[1 : (end - 1 )] .+ b[2 : end ] .- 2 .* m[3 : (end - 2 )]) ./ dt .^ 2
318338
0 commit comments