Skip to content

Commit

Permalink
Merge pull request #12 from JuliaSpaceMissionDesign/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
andreapasquale94 authored Dec 16, 2023
2 parents a948425 + b941697 commit d370a55
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "JSMDUtils"
uuid = "67801824-9821-48b9-a814-9bfb19231086"
authors = ["JSMD Team"]
version = "1.2.0"
version = "1.2.1"

[deps]
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
Expand Down
21 changes: 12 additions & 9 deletions src/Math/Interpolation/akima.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and `N` is the spline dimension (i.e., the number of interpolated functions).
"""
struct InterpAkima{T,N} <: jMath.AbstractInterpolationMethod
n::Int
m::Int
xn::Vector{T}
yn::Matrix{T}
c::Array{T,3}
Expand Down Expand Up @@ -45,10 +46,12 @@ function InterpAkima(x::AbstractVector, y::AbstractArray)

if N == 1
ny = length(y)
m = 1
elseif N == 2
ny = size(y, 2)
m = size(y, 1)
else
throw(ArgumentError("Arrays with more than 2 dimensions are not supported"))
throw(ArgumentError("Arrays with more than 2 dimensions are not supported."))
end

ny != n && throw(ArgumentError("`x` and `y` must have the same length."))
Expand All @@ -57,13 +60,13 @@ function InterpAkima(x::AbstractVector, y::AbstractArray)
idx = sortperm(x)

xs = collect(x[idx])
ys = reshape(collect(N == 1 ? y[idx] : y[:, idx]), N, n)
ys = reshape(collect(N == 1 ? y[idx] : y[:, idx]), m, n)

# Compute the spline coefficients
@views coeffs = vcat((_assemble_akima(n, xs, ys[j, :])[:] for j in 1:N)...)
# Compute the spline coefficients
@views coeffs = vcat((_assemble_akima(n, xs, ys[j, :])[:] for j in 1:m)...)
T = eltype(coeffs)

return InterpAkima{T,N}(n, xs, ys, reshape(coeffs, (3, n - 1, N)))
return InterpAkima{T,N}(n, m, xs, ys, reshape(coeffs, (3, n - 1, m)))
end

Base.eltype(::InterpAkima{T}) where {T} = T
Expand Down Expand Up @@ -106,9 +109,9 @@ function jMath.interpolate(ak::InterpAkima{T,N}, x::Number, flat::Bool=true) whe
# Flat extrapolation settings
if flat
if x < ak.xn[1]
return SVector{N}(ak.yn[:, 1])
return SVector{ak.m}(ak.yn[:, 1])
elseif x > ak.xn[end]
return SVector{N}(ak.yn[:, end])
return SVector{ak.m}(ak.yn[:, end])
end
end

Expand All @@ -117,10 +120,10 @@ function jMath.interpolate(ak::InterpAkima{T,N}, x::Number, flat::Bool=true) whe
δx = x - ak.xn[j - 1]

# Horner polynomial evaluation
return SVector{N}(
return SVector{ak.m}(
ak.yn[i, j - 1] +
δx * (ak.c[1, j - 1, i] + δx * (ak.c[2, j - 1, i] + δx * ak.c[3, j - 1, i])) for
i in 1:N
i in 1:ak.m
)
end
end
Expand Down
18 changes: 11 additions & 7 deletions src/Math/Interpolation/cubic_splines.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ Type storing a cubic spline nodes and coefficients. `T` is the spline data type
### Fields
- `n` -- Number of node points.
- `m` -- Size of the interpolated element.
- `xn` -- Interpolated node points.
- `yn` -- Node points function values.
- `c` -- Spline polynomials coefficients.
- `type` -- Boundary conditions type.
"""
struct InterpCubicSplines{T,N} <: jMath.AbstractInterpolationMethod
n::Int
m::Int
xn::Vector{T}
yn::Matrix{T}
c::Array{T,3}
Expand Down Expand Up @@ -50,8 +52,10 @@ function InterpCubicSplines(x::AbstractVector, y::AbstractArray, type::Symbol=:N

if N == 1
ny = length(y)
m = 1
elseif N == 2
ny = size(y, 2)
m = size(y, 1)
else
throw(ArgumentError("Arrays with more than 2 dimensions are not supported."))
end
Expand All @@ -62,13 +66,13 @@ function InterpCubicSplines(x::AbstractVector, y::AbstractArray, type::Symbol=:N
idx = sortperm(x)

xs = collect(x[idx])
ys = reshape(collect(N == 1 ? y[idx] : y[:, idx]), N, n)
ys = reshape(collect(N == 1 ? y[idx] : y[:, idx]), m, n)

# Compute the spline coefficients
@views coeffs = vcat((_assemble_cspline(n, xs, ys[j, :], Val{type}())[:] for j in 1:N)...)
@views coeffs = vcat((_assemble_cspline(n, xs, ys[j, :], Val{type}())[:] for j in 1:m)...)
T = eltype(coeffs)

return InterpCubicSplines{T,N}(n, xs, ys, reshape(coeffs, (3, n - 1, N)), type)
return InterpCubicSplines{T,N}(n, m, xs, ys, reshape(coeffs, (3, n - 1, m)), type)
end

Base.eltype(::InterpCubicSplines{T}) where {T} = T
Expand Down Expand Up @@ -116,9 +120,9 @@ function jMath.interpolate(
# Flat extrapolation settings
@views if flat
if x < cs.xn[1]
return SVector{N}(cs.yn[:, 1])
return SVector{cs.m}(cs.yn[:, 1])
elseif x > cs.xn[end]
return SVector{N}(cs.yn[:, end])
return SVector{cs.m}(cs.yn[:, end])
end
end

Expand All @@ -127,10 +131,10 @@ function jMath.interpolate(
δx = x - cs.xn[j - 1]

# Horner polynomial evaluation
return SVector{N}(
return SVector{cs.m}(
cs.yn[i, j - 1] +
δx * (cs.c[1, j - 1, i] + δx * (cs.c[2, j - 1, i] + δx * cs.c[3, j - 1, i])) for
i in 1:N
i in 1:cs.m
)
end
end
Expand Down
14 changes: 13 additions & 1 deletion test/Math/interpolation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,20 @@
end
end

# Test for N-dimensional splines
# Test for N-dimensional splines (Additional test after bug #19)
zn = cos.(xn)
cs = JSMDUtils.Math.InterpCubicSplines(xn, hcat(yn, zn, zn)')

@test cs.type == :Natural

# Test node values
for j in eachindex(xn)
y = jMath.interpolate(cs, xn[j])
@test length(y) == 3
@test y [yn[j], zn[j], zn[j]] atol = 1e-11 rtol = 1e-11
end

# Test for N-dimensional splines
cs = JSMDUtils.Math.InterpCubicSplines(xn, hcat(yn, zn)')

@test cs.type == :Natural
Expand Down

2 comments on commit d370a55

@andreapasquale94
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register

Release notes:

  • Fix multidimensional interpolator error

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/97231

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.2.1 -m "<description of version>" d370a554a26cda9143608a7d1d263941836d09c1
git push origin v1.2.1

Please sign in to comment.