Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 1 addition & 24 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,5 @@ concurrency:

jobs:
tests:
name: "Tests"
strategy:
fail-fast: false
matrix:
version:
- "1"
- "lts"
- "pre"
os:
- ubuntu-latest
arch:
- x64
include:
- version: "1.10"
os: windows-latest
arch: x64
- version: "1.10"
os: macOS-latest
arch: x64
uses: "SciML/.github/.github/workflows/tests.yml@v1"
with:
julia-version: "${{ matrix.version }}"
julia-arch: "${{ matrix.arch }}"
os: "${{ matrix.os }}"
uses: "SciML/.github/.github/workflows/grouped-tests.yml@v1"
secrets: "inherit"
6 changes: 5 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ DataCollocationsDataInterpolationsExt = "DataInterpolations"
[compat]
ArrayInterface = "7"
DataInterpolations = "6.4, 7, 8"
Documenter = "1"
JLArrays = "0.3"
OrdinaryDiffEq = "6, 7"
Plots = "1"
Test = "1"
julia = "1.10"

[extras]
Expand All @@ -26,9 +29,10 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
JLArrays = "27aeb0d3-9eb9-45fb-866b-73c2ecf80fcb"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
docs = ["Documenter", "DataInterpolations", "OrdinaryDiffEq", "Plots"]
test = ["DataInterpolations", "JET", "JLArrays", "OrdinaryDiffEq", "Test"]
test = ["DataInterpolations", "JET", "JLArrays", "OrdinaryDiffEq", "Pkg", "Test"]
12 changes: 12 additions & 0 deletions test/qa/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[deps]
DataCollocations = "9454e98c-75cb-4dbc-9573-481819719962"
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[sources]
DataCollocations = {path = "../.."}

[compat]
JET = "0.9, 0.10"
Test = "1"
julia = "1.10"
25 changes: 25 additions & 0 deletions test/qa/qa.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using DataCollocations
using Test
using JET

@testset "JET Static Analysis" begin
# Test kernel functions for type stability
@testset "calckernel optimization" begin
kernels = [
EpanechnikovKernel(), UniformKernel(), TriangularKernel(),
QuarticKernel(), TriweightKernel(), TricubeKernel(),
GaussianKernel(), CosineKernel(), LogisticKernel(),
SigmoidKernel(), SilvermanKernel(),
]
@testset "$kernel" for kernel in kernels
JET.@test_opt target_modules = (DataCollocations,) DataCollocations.calckernel(kernel, 0.5)
end
end

# Test main collocate_data function
@testset "collocate_data optimization" begin
data = rand(2, 20)
tpoints = collect(range(0.0, 1.0, length = 20))
JET.@test_opt target_modules = (DataCollocations,) collocate_data(data, tpoints, TriangularKernel(), 0.1)
end
end
217 changes: 102 additions & 115 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,142 +1,129 @@
using Pkg
using DataCollocations
using Test
using OrdinaryDiffEq
using DataInterpolations
using JLArrays
using JET

@testset "DataCollocations.jl" begin
bounded_support_kernels = [
EpanechnikovKernel(), UniformKernel(), TriangularKernel(),
QuarticKernel(), TriweightKernel(), TricubeKernel(), CosineKernel(),
]
const GROUP = get(ENV, "GROUP", "All")

unbounded_support_kernels = [
GaussianKernel(), LogisticKernel(), SigmoidKernel(), SilvermanKernel(),
]
if GROUP == "QA"
Pkg.activate(joinpath(@__DIR__, "qa"))
Pkg.develop(PackageSpec(path = dirname(@__DIR__)))
Pkg.instantiate()
include(joinpath(@__DIR__, "qa", "qa.jl"))
else
@testset "DataCollocations.jl" begin
bounded_support_kernels = [
EpanechnikovKernel(), UniformKernel(), TriangularKernel(),
QuarticKernel(), TriweightKernel(), TricubeKernel(), CosineKernel(),
]

@testset "Kernel Functions" begin
ts = collect(-5.0:0.1:5.0)
@testset "Kernels with support from -1 to 1" begin
minus_one_index = findfirst(x -> ==(x, -1.0), ts)
plus_one_index = findfirst(x -> ==(x, 1.0), ts)
@testset "$kernel" for (kernel, x0) in zip(
bounded_support_kernels,
[0.75, 0.5, 1.0, 15.0 / 16.0, 35.0 / 32.0, 70.0 / 81.0, pi / 4.0]
)
ws = DataCollocations.calckernel.((kernel,), ts)
# t < -1
@test all(ws[1:(minus_one_index - 1)] .== 0.0)
# t > 1
@test all(ws[(plus_one_index + 1):end] .== 0.0)
# -1 < t <1
@test all(ws[(minus_one_index + 1):(plus_one_index - 1)] .> 0.0)
# t = 0
@test DataCollocations.calckernel(kernel, 0.0) == x0
unbounded_support_kernels = [
GaussianKernel(), LogisticKernel(), SigmoidKernel(), SilvermanKernel(),
]

@testset "Kernel Functions" begin
ts = collect(-5.0:0.1:5.0)
@testset "Kernels with support from -1 to 1" begin
minus_one_index = findfirst(x -> ==(x, -1.0), ts)
plus_one_index = findfirst(x -> ==(x, 1.0), ts)
@testset "$kernel" for (kernel, x0) in zip(
bounded_support_kernels,
[0.75, 0.5, 1.0, 15.0 / 16.0, 35.0 / 32.0, 70.0 / 81.0, pi / 4.0]
)
ws = DataCollocations.calckernel.((kernel,), ts)
# t < -1
@test all(ws[1:(minus_one_index - 1)] .== 0.0)
# t > 1
@test all(ws[(plus_one_index + 1):end] .== 0.0)
# -1 < t <1
@test all(ws[(minus_one_index + 1):(plus_one_index - 1)] .> 0.0)
# t = 0
@test DataCollocations.calckernel(kernel, 0.0) == x0
end
end
end
@testset "Kernels with unbounded support" begin
@testset "$kernel" for (kernel, x0) in zip(
unbounded_support_kernels,
[1 / (sqrt(2 * pi)), 0.25, 1 / pi, 1 / (2 * sqrt(2))]
)
# t = 0
@test DataCollocations.calckernel(kernel, 0.0) == x0
@testset "Kernels with unbounded support" begin
@testset "$kernel" for (kernel, x0) in zip(
unbounded_support_kernels,
[1 / (sqrt(2 * pi)), 0.25, 1 / pi, 1 / (2 * sqrt(2))]
)
# t = 0
@test DataCollocations.calckernel(kernel, 0.0) == x0
end
end
end
end

@testset "Collocation of data" begin
f(u, p, t) = p .* u
rc = 2
ps = repeat([-0.001], rc)
tspan = (0.0, 10.0) # Reduced time span
u0 = 3.4 .+ ones(rc)
t = collect(range(minimum(tspan); stop = maximum(tspan), length = 100)) # Reduced data points
prob = ODEProblem(f, u0, tspan, ps)
data = Array(solve(prob, Tsit5(); saveat = t, abstol = 1.0e-12, reltol = 1.0e-12))
@testset "$kernel" for kernel in [
bounded_support_kernels..., unbounded_support_kernels...,
]
u′, u = collocate_data(data, t, kernel, 0.1) # Higher bandwidth
@test sum(abs2, u - data) < 1.0e-6 # More lenient tolerance
end
@testset "$kernel" for kernel in [bounded_support_kernels...]
# Errors out as the bandwidth is too low
@test_throws ErrorException collocate_data(data, t, kernel, 0.001)
@testset "Collocation of data" begin
f(u, p, t) = p .* u
rc = 2
ps = repeat([-0.001], rc)
tspan = (0.0, 10.0) # Reduced time span
u0 = 3.4 .+ ones(rc)
t = collect(range(minimum(tspan); stop = maximum(tspan), length = 100)) # Reduced data points
prob = ODEProblem(f, u0, tspan, ps)
data = Array(solve(prob, Tsit5(); saveat = t, abstol = 1.0e-12, reltol = 1.0e-12))
@testset "$kernel" for kernel in [
bounded_support_kernels..., unbounded_support_kernels...,
]
u′, u = collocate_data(data, t, kernel, 0.1) # Higher bandwidth
@test sum(abs2, u - data) < 1.0e-6 # More lenient tolerance
end
@testset "$kernel" for kernel in [bounded_support_kernels...]
# Errors out as the bandwidth is too low
@test_throws ErrorException collocate_data(data, t, kernel, 0.001)
end
end
end

@testset "DataInterpolations Extension" begin
# Test with simple data
t = 0.0:0.1:1.0
data = sin.(t)
tpoints_sample = 0.05:0.1:0.95
@testset "DataInterpolations Extension" begin
# Test with simple data
t = 0.0:0.1:1.0
data = sin.(t)
tpoints_sample = 0.05:0.1:0.95

# Test that the extension method works
du, u = collocate_data(data, collect(t), collect(tpoints_sample), LinearInterpolation)
@test length(du) == length(tpoints_sample)
@test length(u) == length(tpoints_sample)
end
# Test that the extension method works
du, u = collocate_data(data, collect(t), collect(tpoints_sample), LinearInterpolation)
@test length(du) == length(tpoints_sample)
@test length(u) == length(tpoints_sample)
end

@testset "Interface Compatibility" begin
@testset "BigFloat support" begin
# Test that BigFloat inputs are supported and eltype is preserved
tpoints = BigFloat.(collect(range(0.0, stop = 10.0, length = 30)))
data = BigFloat.(reshape(sin.(Float64.(tpoints)), 1, :))
bandwidth = BigFloat(0.5)
@testset "Interface Compatibility" begin
@testset "BigFloat support" begin
# Test that BigFloat inputs are supported and eltype is preserved
tpoints = BigFloat.(collect(range(0.0, stop = 10.0, length = 30)))
data = BigFloat.(reshape(sin.(Float64.(tpoints)), 1, :))
bandwidth = BigFloat(0.5)

kernels = [
EpanechnikovKernel(), UniformKernel(), TriangularKernel(),
QuarticKernel(), TriweightKernel(), TricubeKernel(),
GaussianKernel(), CosineKernel(), LogisticKernel(),
SigmoidKernel(), SilvermanKernel(),
]
kernels = [
EpanechnikovKernel(), UniformKernel(), TriangularKernel(),
QuarticKernel(), TriweightKernel(), TricubeKernel(),
GaussianKernel(), CosineKernel(), LogisticKernel(),
SigmoidKernel(), SilvermanKernel(),
]

@testset "$kernel" for kernel in kernels
u_prime, u = collocate_data(data, tpoints, kernel, bandwidth)
@test eltype(u_prime) == BigFloat
@test eltype(u) == BigFloat
@testset "$kernel" for kernel in kernels
u_prime, u = collocate_data(data, tpoints, kernel, bandwidth)
@test eltype(u_prime) == BigFloat
@test eltype(u) == BigFloat
end
end
end

@testset "GPU array error message" begin
# Test that GPU-like arrays (JLArrays) give a clear error message
# instead of cryptic scalar indexing errors
tpoints = JLArray([1.0, 2.0, 3.0, 4.0, 5.0])
data = JLArray([1.0 2.0 3.0 4.0 5.0])
@testset "GPU array error message" begin
# Test that GPU-like arrays (JLArrays) give a clear error message
# instead of cryptic scalar indexing errors
tpoints = JLArray([1.0, 2.0, 3.0, 4.0, 5.0])
data = JLArray([1.0 2.0 3.0 4.0 5.0])

@test_throws ArgumentError collocate_data(data, tpoints)
@test_throws ArgumentError collocate_data(data, tpoints)

# Also test that only GPU tpoints triggers error
tpoints_cpu = collect(1.0:5.0)
@test_throws ArgumentError collocate_data(data, tpoints_cpu)
# Also test that only GPU tpoints triggers error
tpoints_cpu = collect(1.0:5.0)
@test_throws ArgumentError collocate_data(data, tpoints_cpu)

# And only GPU data triggers error
data_cpu = reshape(collect(1.0:5.0), 1, :)
@test_throws ArgumentError collocate_data(data_cpu, tpoints)
end
end

@testset "JET Static Analysis" begin
# Test kernel functions for type stability
@testset "calckernel optimization" begin
kernels = [
EpanechnikovKernel(), UniformKernel(), TriangularKernel(),
QuarticKernel(), TriweightKernel(), TricubeKernel(),
GaussianKernel(), CosineKernel(), LogisticKernel(),
SigmoidKernel(), SilvermanKernel(),
]
@testset "$kernel" for kernel in kernels
JET.@test_opt target_modules = (DataCollocations,) DataCollocations.calckernel(kernel, 0.5)
# And only GPU data triggers error
data_cpu = reshape(collect(1.0:5.0), 1, :)
@test_throws ArgumentError collocate_data(data_cpu, tpoints)
end
end

# Test main collocate_data function
@testset "collocate_data optimization" begin
data = rand(2, 20)
tpoints = collect(range(0.0, 1.0, length = 20))
JET.@test_opt target_modules = (DataCollocations,) collocate_data(data, tpoints, TriangularKernel(), 0.1)
end
end
end
6 changes: 6 additions & 0 deletions test/test_groups.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[Core]
versions = ["lts", "1", "pre"]
os = ["ubuntu-latest", "windows-latest", "macos-latest"]

[QA]
versions = ["lts", "1"]
Loading