Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plane interpolation #306

Merged
merged 67 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
e541ce8
add interpolation
svchb Nov 29, 2023
d09e779
basic working
svchb Nov 30, 2023
fd3c98b
support periodic
svchb Nov 30, 2023
118585b
allow to define different smoothing_length
svchb Nov 30, 2023
a4e306d
more precisely identify system regions
svchb Nov 30, 2023
d0d4e85
to improve accuracy calc shepard
svchb Dec 1, 2023
7f11ce6
add support for multiple points
svchb Dec 1, 2023
2d7334c
add line interpolation
svchb Dec 1, 2023
0a5a580
add doc
svchb Dec 1, 2023
2c10d6c
format
svchb Dec 1, 2023
69e8ddf
add test
svchb Dec 1, 2023
567e1fb
Merge branch 'main' into add_interpolation
svchb Dec 1, 2023
27065cc
small change to doc
svchb Dec 1, 2023
238671e
revert accidental change
svchb Dec 1, 2023
1512816
fix
svchb Dec 1, 2023
959e36e
another fix
svchb Dec 1, 2023
a0c9694
format
svchb Dec 1, 2023
b0a22e4
format
svchb Dec 1, 2023
9f3b68b
also interpolate pressure and velocity
svchb Dec 1, 2023
c83061e
lower tolerance
svchb Dec 1, 2023
f9b8bef
add example plot
svchb Dec 1, 2023
54ffa68
missing dependency
svchb Dec 1, 2023
9d2b15e
format
svchb Dec 1, 2023
51567d6
add func
svchb Dec 1, 2023
a7786fd
add doc
svchb Dec 1, 2023
4278910
add test
svchb Dec 1, 2023
fcfb065
add another test
svchb Dec 1, 2023
9106912
comment out example
svchb Dec 1, 2023
363bfcb
remove pyplot again
svchb Dec 1, 2023
5a89022
fix
svchb Dec 1, 2023
589f7b3
format
svchb Dec 1, 2023
3351d74
small update improve accuracy
svchb Dec 12, 2023
a995d03
Merge branch 'main' into plane_interpolation
svchb Dec 12, 2023
6044f55
Merge branch 'plane_interpolation' of github.com:svchb/TrixiParticles…
svchb Dec 12, 2023
cd8ddc5
update
svchb Dec 12, 2023
f6b3829
up
svchb Dec 12, 2023
7a5c42e
fix
svchb Dec 13, 2023
c6165f0
format
svchb Dec 13, 2023
9226364
Merge branch 'main' into plane_interpolation
svchb Jan 16, 2024
6136f7d
fix plots
svchb Jan 16, 2024
8cddffa
fix plots.jl plot
svchb Jan 16, 2024
f4c2204
cleanup
svchb Jan 16, 2024
fb16b70
fix tests
svchb Jan 16, 2024
1b450dd
cleanup
svchb Jan 16, 2024
babdde0
cleanup
svchb Jan 16, 2024
3025102
fix docs
svchb Jan 16, 2024
bb57d18
fix doc
svchb Jan 16, 2024
a865c41
remove unused func
svchb Jan 16, 2024
073558c
remove unused code
svchb Jan 16, 2024
6b9bb14
fix
svchb Jan 16, 2024
497bcd4
fix viscosity
svchb Jan 22, 2024
9486a04
working 3d example for plane interpolation
svchb Jan 23, 2024
586f639
add 2d plot as well for 3d case
svchb Jan 23, 2024
8659c44
add docs
svchb Jan 23, 2024
e2f991d
fix tests
svchb Jan 23, 2024
cf5558f
fix
svchb Jan 23, 2024
e62453c
fix plot
svchb Jan 23, 2024
699beaa
fix comments
svchb Jan 23, 2024
3e7ad09
fix comment
svchb Jan 23, 2024
971be6f
update
svchb Jan 23, 2024
db52b69
format
svchb Jan 23, 2024
e47ae70
add Plots
svchb Jan 23, 2024
86837d1
fix
svchb Jan 23, 2024
12ff4ef
adjust plot
svchb Jan 23, 2024
010ddb9
reduce time
svchb Jan 23, 2024
626712c
Update interpolation.jl
svchb Jan 25, 2024
78d20e3
Update interpolation_plane.jl
svchb Jan 25, 2024
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
5 changes: 4 additions & 1 deletion examples/fluid/rectangular_tank_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ smoothing_kernel = SchoenbergCubicSplineKernel{2}()

fluid_density_calculator = ContinuityDensity()
viscosity = ArtificialViscosityMonaghan(alpha=0.02, beta=0.0)
viscosity_wall = ViscosityAdami(nu=1.0)
Copy link
Member

Choose a reason for hiding this comment

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

Why use no-slip boundaries? This should be our simplest example file. No moving fluid, no density diffusion, free-slip boundaries.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is not covered currently since no-slip is only used with EDAC at the moment. In my tutorial writing I have added a variation of this testcase which is even simpler and is called minimal.jl.


fluid_system = WeaklyCompressibleSPHSystem(tank.fluid, fluid_density_calculator,
state_equation, smoothing_kernel,
Expand All @@ -44,11 +45,13 @@ fluid_system = WeaklyCompressibleSPHSystem(tank.fluid, fluid_density_calculator,

# ==========================================================================================
# ==== Boundary

boundary_density_calculator = AdamiPressureExtrapolation()
boundary_model = BoundaryModelDummyParticles(tank.boundary.density, tank.boundary.mass,
state_equation=state_equation,
boundary_density_calculator,
smoothing_kernel, smoothing_length)
smoothing_kernel, smoothing_length,
viscosity=viscosity_wall)

# Uncomment to use repulsive boundary particles by Monaghan & Kajtar.
# Also change spacing ratio and boundary layers (see comment above).
Expand Down
8 changes: 8 additions & 0 deletions examples/fluid/rectangular_tank_3d.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using TrixiParticles

trixi_include(@__MODULE__, joinpath(examples_dir(), "fluid", "rectangular_tank_2d.jl"),
fluid_particle_spacing=0.05, initial_fluid_size=(1.0, 1.0, 0.9),
tank_size=(1.0, 1.0, 1.2), acceleration=(0.0, 0.0, -9.81),
smoothing_kernel=SchoenbergCubicSplineKernel{3}(), tspan=(0.0, 1.0),
maxiters=10^5, fluid_density_calculator=ContinuityDensity(),
clip_negative_pressure=false)
113 changes: 113 additions & 0 deletions examples/postprocessing/interpolation_plane.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Example for using interpolation
svchb marked this conversation as resolved.
Show resolved Hide resolved
#######################################################################################
using TrixiParticles
using Plots
using Plots.PlotMeasures

trixi_include(@__MODULE__, joinpath(examples_dir(), "fluid", "rectangular_tank_2d.jl"),
tspan=(0.0, 0.1))

# Interpolation parameters
interpolation_start = [0.0, 0.0]
interpolation_end = [1.0, 1.0]
resolution = 0.005

# We can interpolate a plane by providing the lower left and top right coordinates of a plane.
# Per default the same `smoothing_length` will be used as during the simulation.
original_plane = interpolate_plane_2d(interpolation_start, interpolation_end, resolution,
semi, fluid_system, sol)
original_x = [point[1] for point in original_plane.coord]
original_y = [point[2] for point in original_plane.coord]
original_density = original_plane.density

# Plane with double smoothing length
# Utilizing a higher `smoothing_length` in SPH interpolation increases the amount of smoothing,
# thereby reducing the visibility of disturbances. It also increases the distance
# from free surfaces where the fluid is cut off. This adjustment in `smoothing_length`
# can affect both the accuracy and smoothness of the interpolated results.
double_smoothing_plane = interpolate_plane_2d(interpolation_start, interpolation_end,
resolution, semi, fluid_system, sol,
smoothing_length=2.0 * smoothing_length)
double_x = [point[1] for point in double_smoothing_plane.coord]
double_y = [point[2] for point in double_smoothing_plane.coord]
double_density = double_smoothing_plane.density

# Plane with half smoothing length
svchb marked this conversation as resolved.
Show resolved Hide resolved
# Employing a lower `smoothing_length` in SPH interpolation reduces the amount of smoothing,
# consequently increasing the visibility of disturbances. Simultaneously, it allows for a more
# precise cutoff of the fluid at free surfaces. This change in `smoothing_length` can impact the
# balance between the detail of disturbances captured and the precision of fluid representation near surfaces.
half_smoothing_plane = interpolate_plane_2d(interpolation_start, interpolation_end,
resolution,
semi, fluid_system, sol,
smoothing_length=0.5 * smoothing_length)
half_x = [point[1] for point in half_smoothing_plane.coord]
half_y = [point[2] for point in half_smoothing_plane.coord]
half_density = half_smoothing_plane.density

scatter1 = scatter(original_x, original_y, zcolor=original_density, marker=:circle,
markersize=2, markercolor=:viridis, markerstrokewidth=0)
scatter2 = scatter(double_x, double_y, zcolor=double_density, marker=:circle, markersize=2,
markercolor=:viridis, markerstrokewidth=0)
scatter3 = scatter(half_x, half_y, zcolor=half_density, marker=:circle, markersize=2,
markercolor=:viridis, markerstrokewidth=0)

plot1 = plot(scatter1, xlabel="X Coordinate", ylabel="Y Coordinate",
title="Density Distribution", colorbar_title="Density", ylim=(0.0, 1.0),
svchb marked this conversation as resolved.
Show resolved Hide resolved
legend=false, clim=(1000, 1010), colorbar=true)
plot2 = plot(scatter2, xlabel="X Coordinate", ylabel="Y Coordinate",
title="Density with 2x Smoothing Length", colorbar_title="Density",
ylim=(0.0, 1.0), legend=false, clim=(1000, 1010), colorbar=true)
plot3 = plot(scatter3, xlabel="X Coordinate", ylabel="Y Coordinate",
title="Density with 0.5x Smoothing Length", colorbar_title="Density",
ylim=(0.0, 1.0), legend=false, clim=(1000, 1010), colorbar=true)

trixi_include(@__MODULE__, joinpath(examples_dir(), "fluid", "rectangular_tank_3d.jl"),
tspan=(0.0, 0.01), initial_fluid_size=(2.0, 1.0, 0.9),
tank_size=(2.0, 1.0, 1.2))

# Interpolation parameters
p1 = [0.0, 0.0, 0.0]
p2 = [1.0, 1.0, 0.1]
p3 = [1.0, 0.5, 0.2]
resolution = 0.025

# We can also interpolate a 3D plane but in this case we have to provide 3 points instead!
original_plane = interpolate_plane_3d(p1, p2, p3, resolution, semi,
fluid_system, sol)
original_x = [point[1] for point in original_plane.coord]
original_y = [point[2] for point in original_plane.coord]
original_z = [point[3] for point in original_plane.coord]
original_density = original_plane.density

scatter_3d = scatter3d(original_x, original_y, original_z, marker_z=original_density,
color=:viridis, markerstrokewidth=0)

plot_3d = plot(scatter_3d, xlabel="X", ylabel="Y", zlabel="Z",
svchb marked this conversation as resolved.
Show resolved Hide resolved
title="3D Scatter Plot with Density Coloring", legend=false,
clim=(1000, 1010), colorbar=false)

# Interpolation parameters
p1 = [0.5, 0.0, 0.0]
p2 = [0.5, 1.0, 0.0]
p3 = [0.5, 0.0, 1.0]
resolution = 0.01

# We can also interpolate a 3D plane but in this case we have to provide 3 points instead!
original_plane = interpolate_plane_3d(p1, p2, p3, resolution, semi,
fluid_system, sol)
original_y = [point[2] for point in original_plane.coord]
original_z = [point[3] for point in original_plane.coord]
original_density = original_plane.density

# by ignoring the z coordinate we can also plot this into a 2D plane
scatter_3d_in_2d = scatter(original_y, original_z, zcolor=original_density,
marker=:circle, markersize=4,
markercolor=:viridis, markerstrokewidth=0)

plot_3d_in_2d = plot(scatter_3d_in_2d, xlabel="Y", ylabel="Z",
title="3D in 2D Scatter Plot", legend=false, clim=(1000, 1010),
colorbar=true)
svchb marked this conversation as resolved.
Show resolved Hide resolved

combined_plot = plot(plot1, plot2, plot3, plot_3d, plot_3d_in_2d, layout=(3, 2),
size=(1000, 1500), margin=3mm)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Example for using interpolation
#######################################################################################
using TrixiParticles
# this needs to be commented out to use PythonPlot
svchb marked this conversation as resolved.
Show resolved Hide resolved
using Plots

trixi_include(@__MODULE__, joinpath(examples_dir(), "fluid", "rectangular_tank_2d.jl"))
Expand Down
2 changes: 1 addition & 1 deletion src/TrixiParticles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ export VoxelSphere, RoundSphere, reset_wall!
export ShepardKernelCorrection, KernelCorrection, AkinciFreeSurfaceCorrection,
GradientCorrection, BlendedGradientCorrection, MixedKernelGradientCorrection
export nparticles
export interpolate_line, interpolate_point
export interpolate_line, interpolate_point, interpolate_plane_3d, interpolate_plane_2d

end # module
169 changes: 168 additions & 1 deletion src/general/interpolation.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,175 @@
using LinearAlgebra

@doc raw"""
interpolate_plane_2d(min_corner, max_corner, resolution, semi, ref_system, sol;
smoothing_length=ref_system.smoothing_length, cut_off_bnd=true)

Interpolates properties along a plane in a TrixiParticles simulation.
The region for interpolation is defined by its lower left and top right corners,
with a specified resolution determining the density of the interpolation points.

The function generates a grid of points within the defined region,
spaced uniformly according to the given resolution.

# Arguments
- `min_corner`: The lower left corner of the interpolation region.
- `max_corner`: The top right corner of the interpolation region.
- `resolution`: The distance between adjacent interpolation points in the grid.
- `semi`: The semidiscretization used for the simulation.
- `ref_system`: The reference system for the interpolation.
- `sol`: The solution state from which the properties are interpolated.

# Keywords
- `cut_off_bnd`: `cut_off_bnd`: Boolean to indicate if quantities should be set to zero when a
point is "closer" to a boundary than to the fluid system
(see an explanation for "closer" below). Defaults to `true`.
- `smoothing_length`: The smoothing length used in the interpolation. Default is `ref_system.smoothing_length`.

# Returns
- A `NamedTuple` of arrays containing interpolated properties at each point within the plane.

!!! note
- The interpolation accuracy is subject to the density of particles and the chosen smoothing length.
- With `cut_off_bnd`, a density-based estimation of the surface is used, which is not as
accurate as a real surface reconstruction.

# Examples
```julia
# Interpolating across a plane from [0.0, 0.0] to [1.0, 1.0] with a resolution of 0.2
results = interpolate_plane_2d([0.0, 0.0], [1.0, 1.0], 0.2, semi, ref_system, sol)
```
"""
function interpolate_plane_2d(min_corner, max_corner, resolution, semi, ref_system, sol;
smoothing_length=ref_system.smoothing_length,
cut_off_bnd=true)
dims = length(min_corner)
if dims != 2 || length(max_corner) != 2
throw(ArgumentError("Function is intended for 2D coordinates only"))
svchb marked this conversation as resolved.
Show resolved Hide resolved
end

if any(min_corner .> max_corner)
throw(ArgumentError("`min_corner` should be smaller than `max_corner` in every dimension"))
end

# Calculate the number of points in each dimension based on the resolution
no_points_x = ceil(Int, (max_corner[1] - min_corner[1]) / resolution) + 1
no_points_y = ceil(Int, (max_corner[2] - min_corner[2]) / resolution) + 1

x_range = range(min_corner[1], max_corner[1], length=no_points_x)
y_range = range(min_corner[2], max_corner[2], length=no_points_y)

# Generate points within the plane
points_coords = [SVector(x, y) for x in x_range, y in y_range]

results = interpolate_point(points_coords, semi, ref_system, sol,
smoothing_length=smoothing_length,
cut_off_bnd=cut_off_bnd)

# Find indices where neighbor_count > 0
indices = findall(x -> x > 0, results.neighbor_count)

# Filter all arrays in the named tuple using these indices
filtered_results = map(x -> x[indices], results)

return filtered_results
end

@doc raw"""
interpolate_plane_3d(point1, point2, point3, resolution, semi, ref_system, sol;
smoothing_length=ref_system.smoothing_length, cut_off_bnd=true)

Interpolates properties along a plane in a 3D space in a TrixiParticles simulation.
The plane for interpolation is defined by three points in 3D space,
with a specified resolution determining the density of the interpolation points.

The function generates a grid of points on a parallelogram within the plane defined by the three points, spaced uniformly according to the given resolution.

# Arguments
- `point1`: The first point defining the plane.
- `point2`: The second point defining the plane.
- `point3`: The third point defining the plane. The points must not be collinear.
- `resolution`: The distance between adjacent interpolation points in the grid.
- `semi`: The semidiscretization used for the simulation.
- `ref_system`: The reference system for the interpolation.
- `sol`: The solution state from which the properties are interpolated.

# Keywords
- `cut_off_bnd`: Boolean to indicate if quantities should be set to zero when a
point is "closer" to a boundary than to the fluid system
(see an explanation for "closer" below). Defaults to `true`.
- `smoothing_length`: The smoothing length used in the interpolation. Default is `ref_system.smoothing_length`.

# Returns
- A `NamedTuple` of arrays containing interpolated properties at each point within the plane.

!!! note
- The interpolation accuracy is subject to the density of particles and the chosen smoothing length.
- With `cut_off_bnd`, a density-based estimation of the surface is used which is not as
accurate as a real surface reconstruction.

# Examples
```julia
# Interpolating across a plane defined by points [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], and [0.0, 1.0, 0.0]
# with a resolution of 0.1
results = interpolate_plane_3d([0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], 0.1, semi, ref_system, sol)
svchb marked this conversation as resolved.
Show resolved Hide resolved
```
"""
function interpolate_plane_3d(point1, point2, point3, resolution, semi, ref_system, sol;
smoothing_length=ref_system.smoothing_length,
cut_off_bnd=true)
# Verify that points are in 3D space
if length(point1) != 3 || length(point2) != 3 || length(point3) != 3
throw(ArgumentError("all points must be 3D coordinates"))
end

point1_ = SVector{3}(point1)
point2_ = SVector{3}(point2)
point3_ = SVector{3}(point3)

# Vectors defining the edges of the parallelogram
edge1 = point2_ - point1_
edge2 = point3_ - point1_

# Check if the points are collinear
if norm(cross(edge1, edge2)) == 0
throw(ArgumentError("the points must not be collinear"))
end

# Determine the number of points along each edge
num_points_edge1 = ceil(Int, norm(edge1) / resolution)
num_points_edge2 = ceil(Int, norm(edge2) / resolution)

# Create a set of points on the plane
points_coords = Vector{SVector{3, Float64}}(undef,
(num_points_edge1 + 1) *
(num_points_edge2 + 1))
index = 1
for i in 0:num_points_edge1
for j in 0:num_points_edge2
point_on_plane = point1 + (i / num_points_edge1) * edge1 +
(j / num_points_edge2) * edge2
points_coords[index] = point_on_plane
index += 1
end
end

# Interpolate using the generated points
results = interpolate_point(points_coords, semi, ref_system, sol,
smoothing_length=smoothing_length,
cut_off_bnd=cut_off_bnd)

# Filter results
indices = findall(x -> x > 0, results.neighbor_count)
filtered_results = map(x -> x[indices], results)

return filtered_results
end

@doc raw"""
interpolate_line(start, end_, no_points, semi, ref_system, sol; endpoint=true,
smoothing_length=ref_system.smoothing_length, cut_of_bnd=true)

Interpolates properties along a line in an TrixiParticles simulation.
Interpolates properties along a line in a TrixiParticles simulation.
The line interpolation is accomplished by generating a series of
evenly spaced points between `start` and `end_`.
If `endpoint` is `false`, the line is interpolated between the start and end points,
Expand Down
1 change: 1 addition & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
Expand Down
32 changes: 32 additions & 0 deletions test/examples/examples.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@
@test sol.retcode == ReturnCode.Success
end

@trixi_testset "fluid/rectangular_tank_3d.jl" begin
@test_nowarn trixi_include(@__MODULE__,
joinpath(examples_dir(), "fluid",
"rectangular_tank_3d.jl"), tspan=(0.0, 0.1))
@test sol.retcode == ReturnCode.Success
end

@trixi_testset "fluid/rectangular_tank_3d.jl with SummationDensity" begin
@test_nowarn trixi_include(@__MODULE__,
joinpath(examples_dir(), "fluid",
"rectangular_tank_3d.jl"), tspan=(0.0, 0.1),
fluid_density_calculator=SummationDensity(),
clip_negative_pressure=true)
@test sol.retcode == ReturnCode.Success
end

@trixi_testset "fluid/rectangular_tank_edac_2d.jl" begin
@test_nowarn trixi_include(@__MODULE__,
joinpath(examples_dir(), "fluid",
Expand Down Expand Up @@ -136,4 +152,20 @@
"n_body_benchmark_reference_faster.jl"))
end
end

@testset verbose=true "Postprocessing" begin
@trixi_testset "postprocessing/interpolation_plane.jl" begin
@test_nowarn trixi_include(@__MODULE__,
joinpath(examples_dir(), "postprocessing",
"interpolation_plane.jl"),
tspan=(0.0, 0.01))
@test sol.retcode == ReturnCode.Success
end
@trixi_testset "postprocessing/interpolation_point_line.jl" begin
@test_nowarn trixi_include(@__MODULE__,
joinpath(examples_dir(), "postprocessing",
"interpolation_point_line.jl"))
@test sol.retcode == ReturnCode.Success
end
end
end
Loading