diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 34e5c3eb..4519a562 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -63,7 +63,7 @@ jobs: - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 with: - directories: src,examples + directories: src,examples,ext - uses: codecov/codecov-action@v4 with: files: lcov.info diff --git a/Project.toml b/Project.toml index 35d453df..afec47fa 100644 --- a/Project.toml +++ b/Project.toml @@ -20,10 +20,17 @@ TrixiBase = "9a0f1c46-06d5-4909-a5a3-ce25d3fa3284" TypedPolynomials = "afbbf031-7a57-5f58-a1b9-b774a0fad08d" WriteVTK = "64499a7a-5c06-52f2-abe2-ccb03c286192" +[weakdeps] +Meshes = "eacbb407-ea5a-433e-ab97-5258b1ca43fa" + +[extensions] +KernelInterpolationMeshesExt = "Meshes" + [compat] DiffEqCallbacks = "3" ForwardDiff = "0.10.36" LinearAlgebra = "1" +Meshes = "0.46" Printf = "1" ReadVTK = "0.2" RecipesBase = "1.3.4" @@ -31,9 +38,12 @@ Reexport = "1.2" SciMLBase = "2.26" SimpleUnPack = "1.1" SpecialFunctions = "2" -StaticArrays = "1" +StaticArrays = "1.9" TimerOutputs = "0.5.23" TrixiBase = "0.1.3" TypedPolynomials = "0.4.1" WriteVTK = "1.18" julia = "1.10" + +[extras] +Meshes = "eacbb407-ea5a-433e-ab97-5258b1ca43fa" diff --git a/README.md b/README.md index 469a4de1..9180d92c 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,10 @@ julia> using Pkg julia> Pkg.add("Plots") ``` -To create special node sets, you might also want to install [QuasiMonteCarlo.jl](https://github.com/SciML/QuasiMonteCarlo.jl) and -for solving time-dependent partial differential equations [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) in a -similar way as above for Plots.jl. See the documentation for more examples on how to use these packages in combination with -KernelInterpolation.jl. +To create special node sets, you might also want to install [QuasiMonteCarlo.jl](https://github.com/SciML/QuasiMonteCarlo.jl) or +[Meshes.jl](https://github.com/JuliaGeometry/Meshes.jl) and for solving time-dependent partial differential equations +[OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) in a similar way as above for Plots.jl. See the documentation for more +examples on how to use these packages in combination with KernelInterpolation.jl. ## Usage @@ -129,6 +129,7 @@ for more details. ## Referencing You can directly refer to KernelInterpolation.jl as + ```bibtex @misc{lampert2024kernel, title={{K}ernel{I}nterpolation.jl: {M}ultivariate (generalized) scattered data interpolation diff --git a/docs/Project.toml b/docs/Project.toml index 27f5053c..7bd6bdc7 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,9 +1,11 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Meshes = "eacbb407-ea5a-433e-ab97-5258b1ca43fa" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" QuasiMonteCarlo = "8a4e6c94-4038-4cdc-81c3-7e6ffdb2a71b" [compat] Documenter = "1" +Meshes = "0.46" Plots = "1.9" QuasiMonteCarlo = "0.3" diff --git a/docs/src/development.md b/docs/src/development.md index a5315386..8d56319b 100644 --- a/docs/src/development.md +++ b/docs/src/development.md @@ -19,7 +19,7 @@ cd KernelInterpolation.jl mkdir run cd run julia --project=. -e 'using Pkg; Pkg.develop(PackageSpec(path=".."))' # Install local KernelInterpolation.jl clone -julia --project=. -e 'using Pkg; Pkg.add(["Plots", "QuasiMonteCarlo", "OrdinaryDiffEq"])' # Install additional packages +julia --project=. -e 'using Pkg; Pkg.add(["Plots", "QuasiMonteCarlo", "Meshes", "OrdinaryDiffEq"])' # Install additional packages ``` If you use other packages for executing KernelInterpolation.jl, you can add them to the project in the `run` diff --git a/docs/src/index.md b/docs/src/index.md index 420b0efe..e9a074f6 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -36,10 +36,10 @@ julia> using Pkg julia> Pkg.add("Plots") ``` -To create special node sets, you might also want to install [QuasiMonteCarlo.jl](https://github.com/SciML/QuasiMonteCarlo.jl) and -for solving time-dependent partial differential equations [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) in a -similar way as above for Plots.jl. See the documentation for more examples on how to use these packages in combination with -KernelInterpolation.jl. +To create special node sets, you might also want to install [QuasiMonteCarlo.jl](https://github.com/SciML/QuasiMonteCarlo.jl) or +[Meshes.jl](https://github.com/JuliaGeometry/Meshes.jl) and for solving time-dependent partial differential equations +[OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) in a similar way as above for Plots.jl. See the documentation for more +examples on how to use these packages in combination with KernelInterpolation.jl. ## Usage @@ -129,6 +129,7 @@ for more details. ## Referencing You can directly refer to KernelInterpolation.jl as + ```bibtex @misc{lampert2024kernel, title={{K}ernel{I}nterpolation.jl: {M}ultivariate (generalized) scattered data interpolation diff --git a/docs/src/nodesets.md b/docs/src/nodesets.md index 8824c3c3..9d7ff1f8 100644 --- a/docs/src/nodesets.md +++ b/docs/src/nodesets.md @@ -84,6 +84,22 @@ nodes_halton = NodeSet(nodes_matrix') For the available sampling algorithms in QuasiMonteCarlo.jl, see the [overview in the documentation](https://docs.sciml.ai/QuasiMonteCarlo/stable/samplers/). +Another possibility to create more advanced [`NodeSet`](@ref)s is by using the package [Meshes.jl](https://github.com/JuliaGeometry/Meshes.jl) and the sampling +algorithms defined therein. For example, we can create a regularly sampled set of nodes on the surface of a sphere by running: + +```@example nodesets +using Meshes: Meshes, Sphere, Point, RegularSampling +sphere = Sphere(Point(0.0, 0.0, 0.0), 1.0) +sampler = RegularSampling(20, 30) +points = Meshes.sample(sphere, sampler) +nodes = NodeSet(collect(points)) +``` + +For more information on the available sampling algorithms in Meshes.jl, see the [documentation](https://juliageometry.github.io/MeshesDocs/stable/algorithms/sampling/). +In the documentation of Meshes.jl, you can also find information on how to create more complex geometries like ellipsoids, tori, and many more. +In general, a `PointSet` from Meshes.jl or a `Vector` of `Point`s can be directly passed to the constructor of a [`NodeSet`](@ref) and vice versa can a +[`NodeSet`](@ref) be passed to the constructor of a `PointSet`. + More complicated [`NodeSet`](@ref)s consisting of different shapes can be created, e.g., by `merge`ing different [`NodeSet`](@ref)s. ## Visualizing [`NodeSet`](@ref)s diff --git a/docs/src/pdes.md b/docs/src/pdes.md index 923c157a..f1c1d942 100644 --- a/docs/src/pdes.md +++ b/docs/src/pdes.md @@ -211,7 +211,7 @@ c_0 = (u_0)_X. For the solution of the DAE system, KernelInterpolation.jl uses the library [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl), which already provides a wide range of time integration methods. Note that this is a differential-algebraic equation (DAE) system, which is more difficult to solve than a simple ODE system. Thus, -we are restricted to specialized time integration methods, which can handle DAEs. We recommend using the `Rodas5` method, which is a Rosenbrock method for stiff DAEs. See +we are restricted to specialized time integration methods, which can handle DAEs. We recommend using the `Rodas5P` method, which is a Rosenbrock method for stiff DAEs. See also the [documentation of OrdinaryDiffEq.jl](https://docs.sciml.ai/DiffEqDocs/latest/tutorials/dae_example/) for more information. In KernelInterpolation.jl, you can use the constructor of a [`Semidiscretization`](@ref) in a very similar way as [`SpatialDiscretization`](@ref), but with the additional diff --git a/ext/KernelInterpolationMeshesExt.jl b/ext/KernelInterpolationMeshesExt.jl new file mode 100644 index 00000000..f4e844c5 --- /dev/null +++ b/ext/KernelInterpolationMeshesExt.jl @@ -0,0 +1,23 @@ +module KernelInterpolationMeshesExt + +using Meshes: Meshes, Point, PointSet, to +using KernelInterpolation: KernelInterpolation + +# Meshes.jl uses Unitful.jl for units, which is not available in KernelInterpolation.jl +# Thus, we need to remove the units from the Point struct +val(u) = u.val +val(p::Point) = val.(to(p)) + +function KernelInterpolation.NodeSet(points::Vector{P}) where P <: Point + return KernelInterpolation.NodeSet(val.(points)) +end + +function KernelInterpolation.NodeSet(points::PointSet) + return KernelInterpolation.NodeSet(points.geoms) +end + +function Meshes.PointSet(nodes::KernelInterpolation.NodeSet) + return Meshes.PointSet(Tuple.(nodes.nodes)) +end + +end diff --git a/src/KernelInterpolation.jl b/src/KernelInterpolation.jl index 9bc613f8..ce429f4d 100644 --- a/src/KernelInterpolation.jl +++ b/src/KernelInterpolation.jl @@ -9,7 +9,7 @@ using RecipesBase: RecipesBase, @recipe, @series using SciMLBase: ODEFunction, ODEProblem, ODESolution, DiscreteCallback, u_modified! using SimpleUnPack: @unpack using SpecialFunctions: besselk, loggamma -using StaticArrays: StaticArrays, MVector +using StaticArrays: StaticArrays, MVector, SVector using Reexport: @reexport using TimerOutputs: TimerOutputs, print_timer, reset_timer! @reexport using TrixiBase: trixi_include diff --git a/src/nodes.jl b/src/nodes.jl index 7ed9a663..ee1633c5 100644 --- a/src/nodes.jl +++ b/src/nodes.jl @@ -38,6 +38,11 @@ function NodeSet(nodes::Vector{MVector{Dim, RealT}}) where {Dim, RealT} q = separation_distance(nodes) NodeSet{Dim, RealT}(nodes, q) end +function NodeSet(nodes::Vector{SVector{Dim, RealT}}) where {Dim, RealT} + nodes = MVector.(nodes) + q = separation_distance(nodes) + NodeSet{Dim, RealT}(nodes, q) +end function NodeSet(nodes::AbstractVector{Vector{RealT}}) where {RealT} n = length(nodes) @assert n > 0 diff --git a/test/Project.toml b/test/Project.toml index b6f8a517..3d120bb6 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -2,6 +2,7 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" ExplicitImports = "7d51a73a-1435-4ff3-83d9-f097790105c7" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Meshes = "eacbb407-ea5a-433e-ab97-5258b1ca43fa" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" QuasiMonteCarlo = "8a4e6c94-4038-4cdc-81c3-7e6ffdb2a71b" @@ -14,8 +15,9 @@ WriteVTK = "64499a7a-5c06-52f2-abe2-ccb03c286192" Aqua = "0.8.3" ExplicitImports = "1.0.1" LinearAlgebra = "1" +Meshes = "0.46" OrdinaryDiffEq = "6.68" Plots = "1.25.11" Random = "1" -StaticArrays = "1" +StaticArrays = "1.9" Test = "1" diff --git a/test/test_examples_pde.jl b/test/test_examples_pde.jl index 502fb5cc..9d07f6fe 100644 --- a/test/test_examples_pde.jl +++ b/test/test_examples_pde.jl @@ -47,10 +47,13 @@ EXAMPLES_DIR = joinpath(examples_dir(), "PDEs") pde_test=true, atol=1e-6) # stability issues end - @ki_testset "advection_3d_basic.jl" begin - @test_include_example(joinpath(EXAMPLES_DIR, "advection_3d_basic.jl"), - l2=0.055338785034078526, linf=0.004385483831323006, - pde_test=true, tspan=(0.0, 0.1)) + # Windows CI suddenly takes much smaller time steps for some reason + if !Sys.iswindows() + @ki_testset "advection_3d_basic.jl" begin + @test_include_example(joinpath(EXAMPLES_DIR, "advection_3d_basic.jl"), + l2=0.055338785034078526, linf=0.004385483831323006, + pde_test=true, tspan=(0.0, 0.1)) + end end @ki_testset "advection_diffusion_2d_basic.jl" begin diff --git a/test/test_unit.jl b/test/test_unit.jl index aa1aa689..ad12d35e 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -5,6 +5,7 @@ using KernelInterpolation using LinearAlgebra: norm, Symmetric, I using OrdinaryDiffEq: solve, Rodas5P using StaticArrays: MVector +using Meshes: Sphere, Point, PointSet, RegularSampling, sample using Plots include("test_util.jl") @@ -553,6 +554,16 @@ include("test_util.jl") for node in nodeset14_1 @test isapprox(norm(node), 1.0) end + + # Meshes.jl extension + sphere = Sphere(Point(0.0, 0.0, 0.0), 1.0) + sampler = RegularSampling(5, 6) + points = sample(sphere, sampler) + nodeset_15 = @test_nowarn NodeSet(collect(points)) + @test nodeset_15 isa NodeSet{3, Float64} + @test length(nodeset_15) == 32 + ps = PointSet(Point(1.0, 2.0, 3.0), Point(4.0, 5.0, 6.0)) + @test PointSet(NodeSet(ps)) == ps end @testset "Interpolation" begin